diff options
Diffstat (limited to 'addressbook/gui/widgets')
61 files changed, 24287 insertions, 6967 deletions
diff --git a/addressbook/gui/widgets/.cvsignore b/addressbook/gui/widgets/.cvsignore deleted file mode 100644 index 472fd2593f..0000000000 --- a/addressbook/gui/widgets/.cvsignore +++ /dev/null @@ -1,12 +0,0 @@ -.deps -.libs -.pure -Makefile -Makefile.in -*.lo -*.la -minicard-label-test -minicard-test -minicard-view-test -minicard-widget-test -reflow-test diff --git a/addressbook/gui/widgets/Makefile.am b/addressbook/gui/widgets/Makefile.am index e262e18f5c..f9fea781a8 100644 --- a/addressbook/gui/widgets/Makefile.am +++ b/addressbook/gui/widgets/Makefile.am @@ -1,139 +1,92 @@ -INCLUDES = \ - -DG_LOG_DOMAIN=\"e-minicard\" \ - -DEVOLUTION_GLADEDIR=\""$(gladedir)"\" \ +ruledir = $(privdatadir) +rule_DATA = addresstypes.xml address_formats.dat countrytransl.map + +noinst_LTLIBRARIES = libeabwidgets.la + +libeabwidgets_la_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DG_LOG_DOMAIN=\"eab-widgets\" \ -DEVOLUTION_ETSPECDIR=\""$(etspecdir)"\" \ - -DEVOLUTION_DATADIR=\""$(datadir)"\" \ - -DEVOLUTION_IMAGESDIR=\""$(datadir)"/images/evolution\" \ + -DEVOLUTION_GALVIEWSDIR=\""$(viewsdir)"\" \ + -DEVOLUTION_RULEDIR=\"$(ruledir)\" \ + -DEVOLUTION_IMAGESDIR=\"${imagesdir}\" \ + -DEVOLUTION_PRIVDATADIR=\"${privdatadir}\" \ -I$(top_srcdir) \ - -I$(top_srcdir)/addressbook/backend \ - -I$(top_builddir)/addressbook/backend \ - -I$(top_srcdir)/addressbook/gui/contact-editor \ + -I$(top_srcdir)/addressbook \ -I$(top_srcdir)/addressbook/gui/merging \ - -I$(top_srcdir)/addressbook/gui/component \ - -I$(top_srcdir)/widgets/misc \ + -I$(top_srcdir)/addressbook/util \ -I$(top_builddir)/shell \ - $(EVOLUTION_ADDRESSBOOK_CFLAGS) + $(EVOLUTION_DATA_SERVER_CFLAGS) \ + $(GNOME_PLATFORM_CFLAGS) \ + $(GTKHTML_CFLAGS) \ + $(CHAMPLAIN_CFLAGS) \ + $(GEO_CFLAGS) + +eabincludedir = $(privincludedir)/addressbook/gui/widgets -noinst_LIBRARIES = \ - libeminicard.a +eabinclude_HEADERS = \ + eab-config.h -libeminicard_a_SOURCES = \ +libeabwidgets_la_SOURCES = \ + eab-config.c \ + eab-contact-display.c \ + eab-contact-display.h \ + eab-contact-formatter.c \ + eab-contact-formatter.h \ + eab-gui-util.c \ + eab-gui-util.h \ + e-contact-map.c \ + e-contact-map.h \ + e-contact-map-window.c \ + e-contact-map-window.h \ + e-contact-marker.c \ + e-contact-marker.h \ + e-minicard.c \ + e-minicard.h \ + e-minicard-label.c \ + e-minicard-label.h \ + e-minicard-view.c \ + e-minicard-view.h \ + e-minicard-view-widget.c \ + e-minicard-view-widget.h \ e-addressbook-reflow-adapter.c \ e-addressbook-reflow-adapter.h \ e-addressbook-table-adapter.c \ e-addressbook-table-adapter.h \ e-addressbook-model.c \ e-addressbook-model.h \ - e-addressbook-util.c \ - e-addressbook-util.h \ + e-addressbook-selector.c \ + e-addressbook-selector.h \ e-addressbook-view.c \ e-addressbook-view.h \ - e-minicard-control.c \ - e-minicard-control.h \ - e-minicard-label.c \ - e-minicard-label.h \ - e-minicard-view-widget.c \ - e-minicard-view-widget.h \ - e-minicard-view.c \ - e-minicard-view.h \ - e-minicard-widget.c \ - e-minicard-widget.h \ - e-minicard.c \ - e-minicard.h \ - gal-view-factory-minicard.c \ - gal-view-factory-minicard.h \ gal-view-minicard.c \ - gal-view-minicard.h - -#noinst_PROGRAMS = \ -# minicard-widget-test \ -# minicard-label-test \ -# minicard-test -## reflow-test -## minicard-view-test -# -#minicard_label_test_SOURCES = \ -# test-minicard-label.c -# -#minicard_label_test_LDADD = \ -# libeminicard.a \ -# $(EVOLUTION_ADDRESSBOOK_LIBS) \ -# $(top_builddir)/e-util/libeutil.la -# -#minicard_test_SOURCES = \ -# test-minicard.c -# -#minicard_test_LDADD = \ -# libeminicard.a \ -# $(top_builddir)/addressbook/backend/ebook/libebook.la \ -# $(top_builddir)/e-util/libeutil.la \ -# $(top_builddir)/libversit/libversit.la \ -# $(top_builddir)/e-util/ename/libename.la \ -# $(top_builddir)/addressbook/gui/contact-editor/libecontacteditor.a \ -# $(top_builddir)/addressbook/gui/contact-list-editor/libecontactlisteditor.a \ -# $(top_builddir)/addressbook/printing/libecontactprint.a \ -# $(top_builddir)/addressbook/gui/merging/libecardmerging.a \ -# $(top_builddir)/widgets/misc/libemiscwidgets.a \ -# $(top_builddir)/addressbook/gui/component/select-names/libeselectnames.la \ -# $(top_builddir)/e-util/libeutil.la \ -# $(EVOLUTION_ADDRESSBOOK_LIBS) \ -# libeminicard.a -# -#reflow_test_SOURCES = \ -# test-reflow.c -# -#reflow_test_LDADD = \ -# libeminicard.a \ -# $(top_builddir)/addressbook/backend/ebook/libebook.la \ -# $(top_builddir)/e-util/libeutil.la \ -# $(top_builddir)/libversit/libversit.la \ -# $(top_builddir)/e-util/ename/libename.la \ -# $(top_builddir)/addressbook/contact-editor/libecontacteditor.a \ -# $(top_builddir)/addressbook/printing/libecontactprint.a \ -# $(top_builddir)/widgets/misc/libemiscwidgets.a \ -# $(top_builddir)/e-util/libeutil.la \ -# $(EVOLUTION_ADDRESSBOOK_LIBS) + gal-view-minicard.h \ + ea-minicard.c \ + ea-minicard.h \ + ea-minicard-view.c \ + ea-minicard-view.h \ + ea-addressbook-view.c \ + ea-addressbook-view.h \ + ea-addressbook.c \ + ea-addressbook.h -#minicard_view_test_SOURCES = \ -# test-minicard-view.c +libeabwidgets_la_LIBADD = \ + $(top_builddir)/shell/libevolution-shell.la \ + $(top_builddir)/e-util/libevolution-util.la \ + $(top_builddir)/addressbook/util/libeabutil.la \ + $(EVOLUTION_DATA_SERVER_LIBS) \ + $(GNOME_PLATFORM_LIBS) \ + $(GTKHTML_LIBS) \ + $(CHAMPLAIN_LIBS) \ + $(GEO_LIBS) -#minicard_view_test_LDADD = \ -# $(EVOLUTION_ADDRESSBOOK_LIBS) -# libeminicard.a \ -# $(top_builddir)/addressbook/backend/ebook/libebook.la \ -# $(top_builddir)/e-util/libeutil.la \ -# $(top_builddir)/libversit/libversit.la \ -# $(top_builddir)/addressbook/ename/libename.la \ -# $(top_builddir)/addressbook/contact-editor/libecontacteditor.a \ -# $(top_builddir)/addressbook/printing/libecontactprint.a \ -# $(top_builddir)/widgets/misc/libemiscwidgets.a \ -# $(top_builddir)/e-util/libeutil.la -# -#minicard_widget_test_SOURCES = \ -# e-minicard-widget-test.c -# -#minicard_widget_test_LDADD = \ -# libeminicard.a \ -# $(top_builddir)/addressbook/backend/ebook/libebook.la \ -# $(top_builddir)/e-util/libeutil.la \ -# $(top_builddir)/libversit/libversit.la \ -# $(top_builddir)/e-util/ename/libename.la \ -# $(top_builddir)/addressbook/gui/contact-editor/libecontacteditor.a \ -# $(top_builddir)/addressbook/gui/contact-list-editor/libecontactlisteditor.a \ -# $(top_builddir)/addressbook/gui/component/select-names/libeselectnames.la \ -# $(top_builddir)/addressbook/printing/libecontactprint.a \ -# $(top_builddir)/widgets/misc/libemiscwidgets.a \ -# $(top_builddir)/e-util/libeutil.la \ -# $(top_builddir)/addressbook/gui/merging/libecardmerging.a \ -# $(EVOLUTION_ADDRESSBOOK_LIBS) +dist-hook: + cd $(distdir); rm -f $(BUILT_SOURCES) -gladedir = $(datadir)/evolution/glade -glade_DATA = - -etspecdir = $(datadir)/evolution/etspec etspec_DATA= e-addressbook-view.etspec EXTRA_DIST = \ - $(glade_DATA) \ - $(etspec_DATA) -
\ No newline at end of file + $(etspec_DATA) \ + $(rule_DATA) + +-include $(top_srcdir)/git.mk diff --git a/addressbook/gui/widgets/address_formats.dat b/addressbook/gui/widgets/address_formats.dat new file mode 100644 index 0000000000..307831a94c --- /dev/null +++ b/addressbook/gui/widgets/address_formats.dat @@ -0,0 +1,214 @@ +[at] +AddressFormat=%0(%n\n)%0(%m\n)%0(Postfach %p\n)%0(%s\n)%0(%z)%w%l +BusinessAddressFormat=%0(%m\n)%0(z.Hd. %n\n)%0(Postfach %p\n)%0(%s\n)%0(%z)%w%l +CountryPosition=below + +[au] +AddressFormat=%0(%n\n)%0(%m\n)%0(%s\n)%0(PO BOX %p\n)%0(%L%w%w%R%w%w)%z +CountryPosition=BELOW + +[ax] +AddressFormat=%0(%m\n)%0(%n\n)%0(PB %p\n)%0(%s\n)%z%w%L +CountryPosition=BELOW + +[ca] +AddressFormat=%0(%N\n)%0(%M\n)%0(%S\n)%0(PO BOX %p\n)%0(%L%w%R)%,%z +CountryPosition=BELOW + +[ch] +AddressFormat=%0(%m\n)%0(%n\n)%0(P.O. Box %p\n)%0(%s\n)%z%w%l +CountryPosition=BELOW + +[ch_de] +AddressFormat=%0(%m\n)%0(%n\n)%0(Postfach %p\n)%0(%s\n)%z%w%l + +[ch_fr] +AddressFormat=%0(%m\n)%0(%n\n)%0(Case postale %p\n)%0(%s\n)%z%w%l + +[ch_it] +AddressFormat=%0(%m\n)%0(%n\n)%0(Casella postale %p\n)%0(%s\n)%z%w%l + +[cz] +AddressFormat=%0(%m\n)%0(%n\n)%0(p. p. %p\n)%0(%s\n)%z%w%w%l +CountryPosition=below + +[de] +AddressFormat=%0(%m\n)%0(%n\n)%0(Postfach %p\n)%0(%s\n)%z%w%l +CountryPosition=BELOW + +[de_nds] +AddressFormat=%0(%n\n)%0(- %m -\n)%0(Postfach %p\n)%0(%s\n)%z%w%l + +[dk] +AddressFormat=%0(%n\n)%0(%m\n)%0(%s\n)%0(Postboks %p\n)%z%w%l +CountryPosition=below + +[fi] +AddressFormat=%0(%m\n)%0(%n\n)%0(PB %p\n)%0(%s\n)%z%w%L +CountryPosition=BELOW + +[fr] +AddressFormat=%0(%m\n)%0(%n\n)%0(%s\n)%0(BP %p\n)%z%w%L +CountryPosition=BELOW + +[gl] +AddressFormat=%0(%n\n)%0(%m\n)%0(%s\n)%0(Postboks %p\n)%z%w%l +CountryPosition=below + +[hu] +AddressFormat=%0(%n\n)%0(\n%l)%0(\n%s)%0(\nPF. %p)%0(\n%z)%0(\n%r) +BusinessAddressFormat=%0(%n\n)%m\n%z%w%l%0(\n%s)%0(\nPF. %p)%0(\n%r) +CountryPosition=below + +[il] +AddressFormat=%0(%n\n)%0(%m\n)%0(ת.ד. %p\n)%0(%s\n)%0(%l%w%z) +CountryPosition=BELOW + +[jp] +AddressFormat=%0(%z%w%r)%w%l%0(\n%s)%0(\n%m)%0(\n%n) +CountryPosition=ABOVE + +[kh] +AddressFormat=%0(%m\n)%0(%n\n)%0(%s\n)%0(P.O. Box %p\n)%z%w%L%0(\n%r) +CountryPosition=BELOW + +[me] +AddressFormat=%0(%m\n)%0(%n\n)%0(%s\n)%0(poštanski fah %p\n)%z%w%l +CountryPosition=BELOW + +[me_sr] +AddressFormat=%0(%m\n)%0(%n\n)%0(%s\n)%0(поштански фах %p\n)%z%w%l + +[na] +AddressFormat=%0(%m\n)%0(%n\n)%0(P.O. Box %p\n)%l + +[nl] +AddressFormat=%n\n%0(%m\n)%0(Postbus %p\n)%0(%s\n)%z%w%l +CountryPosition=below + +[no] +AddressFormat=%0(%m\n)%0(%n\n)%0(Postboks %p\n)%0(%s\n)%z%w%w%L +CountryPosition=BELOW + +[rs] +AddressFormat=%0(%m\n)%0(%n\n)%0(%s\n)%0(поштански фах %p\n)%z%w%l +CountryPosition=BELOW + +[rs_sr] +AddressFormat=%0(%m\n)%0(%n\n)%0(%s\n)%0(poštanski fah %p\n)%z%w%l + +[se] +AddressFormat=%n\n%0(%m\n)%0(Box %p\n)%0(%s\n)%z%w%w%L +CountryPosition=below + +[us] +AddressFormat=%0(%n\n)%0(%m\n)%0(%s\n)%0(PO BOX %p\n)%0(%l%,%w%r)%w%z +CountryPosition=BELOW + +[at] +AddressFormat=%0(%n\n)%0(%m\n)%0(Postfach %p\n)%0(%s\n)%0(%z)%w%l +BusinessAddressFormat=%0(%m\n)%0(z.Hd. %n\n)%0(Postfach %p\n)%0(%s\n)%0(%z)%w%l +CountryPosition=below + +[au] +AddressFormat=%0(%n\n)%0(%m\n)%0(%s\n)%0(PO BOX %p\n)%0(%L%w%w%R%w%w)%z +CountryPosition=BELOW + +[ax] +AddressFormat=%0(%m\n)%0(%n\n)%0(PB %p\n)%0(%s\n)%z%w%L +CountryPosition=BELOW + +[ca] +AddressFormat=%0(%N\n)%0(%M\n)%0(%S\n)%0(PO BOX %p\n)%0(%L%w%R)%,%z +CountryPosition=BELOW + +[ch] +AddressFormat=%0(%m\n)%0(%n\n)%0(P.O. Box %p\n)%0(%s\n)%z%w%l +CountryPosition=BELOW + +[ch_de] +AddressFormat=%0(%m\n)%0(%n\n)%0(Postfach %p\n)%0(%s\n)%z%w%l + +[ch_fr] +AddressFormat=%0(%m\n)%0(%n\n)%0(Case postale %p\n)%0(%s\n)%z%w%l + +[ch_it] +AddressFormat=%0(%m\n)%0(%n\n)%0(Casella postale %p\n)%0(%s\n)%z%w%l + +[cz] +AddressFormat=%0(%m\n)%0(%n\n)%0(p. p. %p\n)%0(%s\n)%z%w%w%l +CountryPosition=below + +[de] +AddressFormat=%0(%m\n)%0(%n\n)%0(Postfach %p\n)%0(%s\n)%z%w%l +CountryPosition=BELOW + +[de_nds] +AddressFormat=%0(%n\n)%0(- %m -\n)%0(Postfach %p\n)%0(%s\n)%z%w%l + +[dk] +AddressFormat=%0(%n\n)%0(%m\n)%0(%s\n)%0(Postboks %p\n)%z%w%l +CountryPosition=below + +[fi] +AddressFormat=%0(%m\n)%0(%n\n)%0(PB %p\n)%0(%s\n)%z%w%L +CountryPosition=BELOW + +[fr] +AddressFormat=%0(%m\n)%0(%n\n)%0(%s\n)%0(BP %p\n)%z%w%L +CountryPosition=BELOW + +[gl] +AddressFormat=%0(%n\n)%0(%m\n)%0(%s\n)%0(Postboks %p\n)%z%w%l +CountryPosition=below + +[hu] +AddressFormat=%0(%n\n)%0(\n%l)%0(\n%s)%0(\nPF. %p)%0(\n%z)%0(\n%r) +BusinessAddressFormat=%0(%n\n)%m\n%z%w%l%0(\n%s)%0(\nPF. %p)%0(\n%r) +CountryPosition=below + +[il] +AddressFormat=%0(%n\n)%0(%m\n)%0(ת.ד. %p\n)%0(%s\n)%0(%l%w%z) +CountryPosition=BELOW + +[jp] +AddressFormat=%0(%z%w%r)%w%l%0(\n%s)%0(\n%m)%0(\n%n) +CountryPosition=ABOVE + +[kh] +AddressFormat=%0(%m\n)%0(%n\n)%0(%s\n)%0(P.O. Box %p\n)%z%w%L%0(\n%r) +CountryPosition=BELOW + +[me] +AddressFormat=%0(%m\n)%0(%n\n)%0(%s\n)%0(poštanski fah %p\n)%z%w%l +CountryPosition=BELOW + +[me_sr] +AddressFormat=%0(%m\n)%0(%n\n)%0(%s\n)%0(поштански фах %p\n)%z%w%l + +[na] +AddressFormat=%0(%m\n)%0(%n\n)%0(P.O. Box %p\n)%l + +[nl] +AddressFormat=%n\n%0(%m\n)%0(Postbus %p\n)%0(%s\n)%z%w%l +CountryPosition=below + +[no] +AddressFormat=%0(%m\n)%0(%n\n)%0(Postboks %p\n)%0(%s\n)%z%w%w%L +CountryPosition=BELOW + +[rs] +AddressFormat=%0(%m\n)%0(%n\n)%0(%s\n)%0(поштански фах %p\n)%z%w%l +CountryPosition=BELOW + +[rs_sr] +AddressFormat=%0(%m\n)%0(%n\n)%0(%s\n)%0(poštanski fah %p\n)%z%w%l + +[se] +AddressFormat=%n\n%0(%m\n)%0(Box %p\n)%0(%s\n)%z%w%w%L +CountryPosition=below + +[us] +AddressFormat=%0(%n\n)%0(%m\n)%0(%s\n)%0(PO BOX %p\n)%0(%l%,%w%r)%w%z +CountryPosition=BELOW + diff --git a/addressbook/gui/widgets/addresstypes.xml b/addressbook/gui/widgets/addresstypes.xml new file mode 100644 index 0000000000..cef8000cc4 --- /dev/null +++ b/addressbook/gui/widgets/addresstypes.xml @@ -0,0 +1,104 @@ +<?xml version="1.0"?> +<filterdescription> +<partset> + <part name="name"> + <title>Name</title> + <input type="optionlist" name="name-type"> + <option value="contains"> + <title>contains</title> + <code>(contains "full_name" ${name})</code> + </option> + <option value="not contains"> + <title>does not contain</title> + <code>(not (contains "full_name" ${name}))</code> + </option> + <option value="is"> + <title>is</title> + <code>(is "full_name" ${name})))</code> + </option> + <option value="is not"> + <title>is not</title> + <code>(not (is "full_name" ${name}))</code> + </option> + <option value="begin"> + <title>begins with</title> + <code>(beginswith "full_name" ${name})</code> + </option> + <option value="end"> + <title>ends in</title> + <code>(endswith "full_name" ${name})</code> + </option> + </input> + <input type="string" name="name"/> + </part> + <part name="email"> + <title>Email</title> + <input type="optionlist" name="email-type"> + <option value="contains"> + <title>contains</title> + <code>(contains "email" ${email})</code> + </option> + <option value="not contains"> + <title>does not contain</title> + <code>(not (contains "email" ${email}))</code> + </option> + <option value="is"> + <title>is</title> + <code>(is "email" ${email})</code> + </option> + <option value="is not"> + <title>is not</title> + <code>(not (is "email" ${email}))</code> + </option> + </input> + <input type="address" name="email"/> + </part> + <part name="category"> + <title>Category</title> + <input type="optionlist" name="category-type"> + <option value="contains"> + <title>contains</title> + <code>(contains "category_list" ${category})</code> + </option> + <option value="not contains"> + <title>does not contain</title> + <code>(not (contains "category_list" ${category}))</code> + </option> + <option value="is"> + <title>is</title> + <code>(is "category_list" ${category})</code> + </option> + <option value="is not"> + <title>is not</title> + <code>(not (is "category_list" ${category}))</code> + </option> + </input> + <input type="optionlist" name="category"> + <dynamic func="e_util_get_category_filter_options"/> + </input> + </part> + <part name="sexp"> + <title>Expression</title> + <input type="rawcode" name="rawcode"/> + </part> +</partset> + + <ruleset> + + <rule grouping="any" source="demand"> + <_title>Name contains</_title> + <sources/> + </rule> + + <rule grouping="any" source="demand"> + <_title>Email begins with</_title> + <sources/> + </rule> + + <rule grouping="any" source="demand"> + <_title>Any field contains</_title> + <sources/> + </rule> + + </ruleset> +</filterdescription> diff --git a/addressbook/gui/widgets/countrytransl.map b/addressbook/gui/widgets/countrytransl.map new file mode 100644 index 0000000000..1f6757f72f --- /dev/null +++ b/addressbook/gui/widgets/countrytransl.map @@ -0,0 +1,11370 @@ +Andorra ad +Андора ad +Андора ad +Andora ad +ອີນເດີຍ ad +Andora ad +Андорра ad +安道尔 ad +United Arab Emirates ae +Vereenigde Arabiese Emirate ae +الإمارات العربية المتحدة ae +Злучаныя Арабскія Эміраты ae +Обединени Арабски Емирства ae +Ujedinjeni arapski emirati ae +Emirats Àrabs Units ae +Spojené arabské emiráty ae +Forenende Arabiske Emirater ae +Vereinigte Arabische Emirate ae +Ενωμένα Αραβικά Εμιράτα ae +Emiratos árabes unidos ae +Araabia Ühendemiraadid ae +Arabiar Emirato Batuak ae +امارات متحده عربی ae +Yhdistyneet Arabiemiraatit ae +Émirats Arabes Unis ae +איחוד האמירויות הערביות ae +Ujedinjeni arapski emirati ae +Egyesült Arab Emirátusok ae +Emirati arabi uniti ae +アラブ首長国連邦 ae +아랍 에미레이트 연합 ae +ສະຫະລັດ ae +Jungtiniai Arabų Emiratai ae +Emirati Għarab Magħquda ae +De forente arabiske emirater ae +Verenigde Arabische Emiraten ae +Dei sameinte arabiske emirata ae +Di-Emirate tseo di Kopanego tsa Arab ae +Zjednoczone Emiraty Arabskie ae +Emiratos Árabes Unidos ae +Emirados Árabes ae +Emiratele Arabe Unite ae +Объединенные Арабские Эмираты ae +Spojené arabské emiráty ae +Združeni arabski Emirati ae +Förenade arabemiraten ae +³ì¸¢Â «ÃÒ ¿¡Î¸û ae +Birleşik Arap Emirlikleri ae +Об'єднані Арабські Емірати ae +Mashango o tangananaho a Emirates ae +阿拉伯联合酋长国 ae +阿拉伯聯合大公國 ae +Izindawo zezinduna zase-United Arab ae +Afghanistan af +Афганістан af +Афганистан af +Afganistan af +Afghanistán af +Afganisztán af +ລີທົ່ວເນີຍ af +Afeganistão af +Afganistan af +Afganistan af +Afganistan af +Афганістан af +阿富汗 af +Antigua and Barbuda ag +Antigue en Barbuda ag +أنتيغوا و باربودا ag +Antigua və Barbuda ag +Антыгуа і Барбуда ag +Антигуа и Барбадос ag +Antigua ha Barbuda ag +Antigua i Barbuda ag +Antigua i Barbuda ag +Antigua a Barbuda ag +Antigua og Barbuda ag +Antigua und Barbuda ag +Antigua και Barbuda ag +Antigvo kaj Barbudo ag +Antigua y Barbuda ag +Antigua ja Barbuda ag +Antigua eta Barbuda ag +آنتیگوا و باربودا ag +Antigua ja Barbados ag +Antigua og Barbuda ag +Antigua et Barbuda ag +Antiga e Barbuda ag +אנטיגואה וברבודה ag +Antigua i Barbuda ag +Antigua és Barbuda ag +Antigua dan Barbuda ag +Antigúa og Barbúda ag +Antigua e Barbuda ag +アンティグアバーブーダ ag +앤티가 바부다 ag +Antikva ir Barbuda ag +Antigva un Barbudas ag +Antigwa u Barbuda ag +Antigua og Barbuda ag +Antigua en Barbuda ag +Antigua og Barbuda ag +Antigua le Barbuda ag +Antigua e Barbuda ag +Antigua i Barbuda ag +Antigua e Barbuda ag +Antigua e Barbuda ag +Antigua şi Barbuda ag +Антигуа и Барбадос ag +Antigua a Barbuda ag +Antigva in Barbuda ag +Antigua i Barbuda ag +I-Antigua kanye ne Barbuda ag +Antigua och Barbuda ag +¬ýÊÌÅ¡ & À¡÷Ò¼¡ ag +Antigua ve Barbuda ag +Трінідад та Тобаго ag +Antigua và Barbuda ag +Antigua eyet Barbuda ag +Antigua ne Barbuda ag +安地瓜岛和巴布达岛 ag +安地瓜島和巴布達島 ag +Antigua kanye ne-Barbuda ag +Anguilla ai +Ангуила ai +ແພນວິນ ai +Angvila ai +Ангілья ai +安圭拉 ai +Albania al +Альбанія al +Албания al +Albanija al +Albanien al +Albánia al +ແອດແລນຕິກ al +Albânia al +Albánsko al +Albanija al +Albanien al +Албанія al +阿尔巴尼亚 al +Armenia am +Армэнія am +Армения am +Armenija am +Armenien am +Örményország am +ອາເຈນຕິນາ am +Armênia am +Arménsko am +Armenija am +Armenien am +Арменія am +亚美尼亚 am +Netherlands Antilles an +Холандски Антили an +Nizozemski Antili an +Nederlandske antiller an +Antillas holandesas an +Antilla Holandarrak an +Holland-Antillák an +ເນເທີແລນ an +Antilhas an +Holandské Antily an +Nizozemski Antili an +Nederländska Antillerna an +Голландські Антилли an +荷属安的列斯群岛 an +Angola ao +Ангола ao +Ангола ao +ບັນແກເລີຍ ao +Ангола ao +安哥拉 ao +Argentina ar +Argentinië ar +الأرجنتين ar +Аргентына ar +Аржентина ar +Arc'hantina ar +Argentinien ar +Αργεντινή ar +Argentino ar +Argentiina ar +آرژانتین ar +Agentiina ar +Argentine ar +Arxentina ar +ארגנטינה ar +Argentína ar +ArgentÃna ar +アルゼンチン ar +아르헨티나 ar +ອາເຈນຕິນາ ar +Argentīna ar +Arġentina ar +Argentinië ar +Argentyna ar +Аргентина ar +Argentína ar +I-Argentina ar +¬÷¦ºýÊÉ¡ ar +อาร์เจนตินา ar +Arjantin ar +Аргентина ar +Agenthina ar +Årdjintene ar +阿根廷 ar +阿根廷 ar +American Samoa as +Амэрыканскае Самоа as +Американска Самоа as +Američka Samoa as +Samoa (USA) as +Samoa americana as +Amerikako Samoa as +Amerikai Szamoa as +ອາເມລິກາເຫນືອ as +Samoa Americana as +Americká Samoa as +Ameriška Samoa as +Amerikanska Samoa as +Американське Самоа as +美属萨摩亚群岛 as +Austria at +Oostenryk at +النمسا at +Avstriya at +Аўстрыя at +Австрия at +Aostria at +Austrija at +Àustria at +Rakousko at +Østrig at +Österreich at +Αυστρία at +Aŭstrio at +اتریش at +Itävalta at +Eysturríki at +Autriche at +אוסטריה at +Austrija at +Ausztria at +AusturrÃki at +オーストリア at +오스트리아 at +ອອດສະເຕເລີຍ at +Austrija at +Austrija at +Awtrija at +Østerrike at +Oostenrijk at +Austerrike at +Áustria at +Áustria at +Австрия at +Rakúsko at +Avstrija at +Austrija at +I-Austria at +Österrike at +¬Íò¾¢Ã¢Â¡ at +ออสเตรีย at +Avusturya at +Австрія at +Ositiria at +A'o at +Ôtriche at +奥地利 at +奧地利 at +Australia au +Australië au +أستراليا au +Avustralya au +Аўстралія au +Австралия au +Aostralia au +Australija au +Austràlia au +Austrálie au +Australien au +Australien au +Αυστραλία au +Aŭstralio au +Austraalia au +استرالیا au +Australie au +אוסטרליה au +Australija au +Ausztrália au +ÃstralÃa au +オーストラリア au +오스트레일리아 au +ອອດສະເຕເລີຍ au +Australija au +Austrālija au +Awstralja au +Australië au +Austrália au +Austrália au +Австралия au +Austrália au +Avstralija au +Australija au +I-Australia au +Australien au +¬Íò¾¢§ÃĢ¡ au +ออสเตรเลีย au +Avusturalya au +Австралія au +Ositiralia au +U'c au +Ôstraleye au +澳大利亚 au +澳大利亞 au +Aruba aw +Аруба aw +ເກມໄັພ່ aw +Аруба aw +阿鲁巴岛 aw +Azerbaijan az +أذربيجان az +Azərbaycan az +Азэрбайджан az +Азарбайджан az +Azerbejdžan az +Azerbaitjan az +Ázerbajdžánský az +Azerbajdjan az +Aserbaidschan az +Αζερμπαϊτζάν az +Azerbajĝana az +Azerbaiján az +Aserbaidžaan az +آذربایجان az +Azerbaidzan az +Aserbadsjan az +אזרביג'ן az +Azerbejdžan az +Azerbajdzsán az +Azerbaigian az +アゼルバイジャン az +아제르바이잔 az +ອາເຊີໄບຈັນ az +Azerbaidžanas az +Azerbaidžāņu az +Ażerbajġan az +Aserbajdsjan az +Azerbeidjan az +Aserbajdsjan az +Azerbejdżan az +Azerbaijão az +Turco az +Azerbadjan az +Азербайджан az +Ázerbajdžánsky az +Azerbajdžan az +Azerbejdžan az +I-Azerbaijan az +«º÷¨Àº¡ý az +อาร์เซอร์ไบจัน az +Azerice az +Азербайджан az +Azerbaydjan az +阿塞拜疆 az +亞塞拜然 az +Bosnia and Herzegovina ba +Bosnië en Herzegovina ba +البوسنا و الهرسك ba +Босьнія і Герцагавіна ba +Боснена и Херцеговина ba +Bosna i Hercegovina ba +Bòsnia i Hercegovina ba +Bosna a Herzegovina ba +Bosnien-Herzegovina ba +Bosnien und Herzegowina ba +Βοσνία και Ερζεγοβίνη ba +Bosnio kaj Hercegovino ba +Bosnia y Herzegovina ba +Bosnia ja Hertsegovina ba +Bosnia eta Herzegovina ba +بوسنی و هرزگوین ba +Bosnia ja Herzegovina ba +Bosnia-Herzegovina ba +Bosnie herzégovine ba +בוסניה הרצגובינה ba +Bosna i Hercegovina ba +Bosznia-Hercegovina ba +Bosnia e Erzegovina ba +ボスニアヘルツェゴビナ ba +보스니아어와 헤르체고비나 ba +ບອສເນີຍ ແລະ ເຫີເຊີໂກວິນາ ba +Bosnija ir Hercegovina ba +Bosnija un Hercogovina ba +Bożnia u Ħerżegovina ba +Bosnia-Hercegovina ba +Bosnië en Herzegovina ba +Bosnia-Hercegovina ba +Bosnia le Herzegovina ba +Bośnia i Hercegowina ba +Bósnia e Herzegovina ba +Bósnia Herzegóvina ba +Bosnia şi Herţegovina ba +Босния и Герцеговина ba +Bosna a Hercegovina ba +Bosna in Hercegovina ba +I-Bosnia kanye ne Herzegovina ba +Bosnien och Herzegovina ba +¦À¡Íɢ¡ ba +บอสเนีย และ เฮอร์เซโกวินา ba +Bosna Hersek ba +Боснія та Герцеговина ba +Mubosinia na Muhezegovina ba +Bosneye ba +Bosnia ne Herzegovina ba +波斯尼亚和黑塞哥维那 ba +波士尼亞與赫塞哥維納 ba +Bosnia kanye ne-Herzegovina ba +Barbados bb +بربادوس bb +Барбадос bb +Барбадос bb +Μπαρμπάντος bb +Babadoso bb +باربادوس bb +Barbade bb +ברבדוס bb +バルバドス bb +바르바도스 bb +ບາລບາດອດສ bb +Barbadosas bb +Barbadosa bb +Барбадос bb +I-Barbados bb +À¡÷§À¼¡Í bb +บาร์บาดอส bb +Барбадос bb +Barbades bb +巴巴多斯 bb +巴貝多 bb +Bangladesh bd +بنغلاديش bd +Banqladeş bd +Банглядэш bd +Бангладеш bd +Bangladeš bd +Bangladéš bd +Bangladesch bd +Μπαγκλαντές bd +Bangladeŝo bd +بنگلادش bd +בנגלדש bd +Bangladeš bd +Banglades bd +バングラデシュ bd +방글라데시 bd +ບັງຄະລາເທດ bd +Bangladešas bd +Bangladeša bd +Bangladexx bd +Bangladesz bd +Banglade bd +Бангладеш bd +Bangladéš bd +Bangladeš bd +I-Bangladesh bd +Àí¸Ç¡§¾Í bd +บังคลาเทศ bd +Bangladeş bd +Бангладеш bd +孟加拉 bd +孟加拉 bd +Belgium be +België be +بلجيكا be +Belçika be +Бэльгія be +Белгия be +Belgia be +Belgija be +Bèlgica be +Belgie be +Belgien be +Belgien be +Βέλγιο be +Belgio be +Bélgica be +Belgia be +Belgika be +بلژیک be +Belgia be +Belgia be +Belgique be +Bélxica be +בלגיה be +Belgija be +Belgia be +BelgÃa be +Belgio be +ベルギー be +벨기에 be +ເບລຢ່ງມ be +Belgija be +Beļģija be +Belġju be +Belgia be +België be +Belgia be +Bèlgica be +Belgia be +Bélgica be +Bélgica be +Belgia be +Бельгия be +Belgicko be +Belgija be +Belgija be +I-Belgium be +Belgien be +¦Àøº¢Âõ be +เบลเยียม be +Belçika be +Бельгія be +Beljike be +比利时 be +比利時 be +Burkina Faso bf +Буркіна Фасо bf +Буркина Фаско bf +ຕຸລະກີ bf +Буркіна Фасо bf +布基纳法索 bf +Bulgaria bg +Bulgarye bg +بلغاريا bg +Bolgarıstan bg +Баўгарыя bg +България bg +Bugarska bg +Bulgària bg +Bulharsko bg +Bulgarien bg +Bulgarien bg +Βουλγαρία bg +Bulgario bg +Bulgaaria bg +بلغارستان bg +Bulgarie bg +בולגריה bg +Bugarska bg +Bulgária bg +BúlgarÃa bg +ブルガリア bg +불가리아 bg +ບັນແກເລີຍ bg +Bulgarija bg +Bulgārija bg +Bulgarija bg +Bulgarije bg +Bułgaria bg +Bulgária bg +Bulgária bg +Болгария bg +Bulharsko bg +Bolgarija bg +Bugarska bg +I-Bulgaria bg +Bulgarien bg +Àø§¸Ã¢Â¡ bg +บัลแกเรีย bg +Bulgaristan bg +Болгарія bg +Baligaria bg +Bulgåreye bg +保加利亚 bg +保加利亞 bg +Bahrain bh +البحرين bh +Бахрэйн bh +Бахрейн bh +Bahrein bh +Bahrajn bh +Μπαχρέιν bh +Bahrein bh +Bahrein bh +بحرین bh +בחריין bh +バーレーン bh +바레인 bh +ຖັກກ່ງວ bh +Bahreinas bh +Baħrain bh +Baghrein bh +Bahrajn bh +Bahamas bh +Bahrein bh +Бахрейн bh +Bahrajn bh +Bahrajn bh +I-Bahrain bh +Bahrein bh +À‹¨Ãý bh +Bahreyn bh +Бахрейн bh +巴林 bh +巴林 bh +Burundi bi +Бурундзі bi +Бурунди bi +ເຄອຣດ bi +Бурунді bi +布隆迪 bi +Benin bj +Бэнін bj +Бенин bj +ບອສເນີຍ bj +Бенін bj +贝宁 bj +Bermuda bm +Бэрмуды bm +Бермуда bm +ເຍລລະມັນ bm +Bermudy bm +Bermudi bm +Бермуди bm +百慕大 bm +Brunei Darussalam bn +Брунэй bn +Бруней bn +Brunei bn +Brunei Szultánság bn +ເບລາລັສເຊີຍ bn +Brunei bn +Brunei Darusalam bn +Бруней Даруссалам bn +Bolivia bo +Bolivië bo +بوليفيا bo +Boliviya bo +Балівія bo +Боливия bo +Bolivija bo +Bolívia bo +Bolívie bo +Bolivien bo +Βολιβία bo +Bolivio bo +Boliivia bo +بولیوی bo +Bolivie bo +בוליביה bo +Bolivija bo +Bolívia bo +BólivÃa bo +ボリビア bo +볼리비아 bo +ໂບລີເວີຍ bo +Bolivija bo +Bolīvija bo +Bolivja bo +Boliwia bo +Bolívia bo +Bolívia bo +Боливия bo +Bolívia bo +Bolivija bo +Bolivija bo +I-Bolivia bo +¦À¡Ä¢Å¢Â¡ bo +โบลิเวีย bo +Bolivya bo +Болівія bo +Boliveye bo +波利维亚 bo +玻利維亞 bo +Brazil br +Brazilië br +البرازيل br +Braziliya br +Бразылія br +Бразилия br +Brasil br +Brazílie br +Brasilien br +Brasilien br +Βραζιλία br +Brazilo br +Brasil br +Brasiilia br +Brasil br +برزیل br +Brasilia br +Brésil br +Brasil br +ברזיל br +Brazília br +BrasilÃa br +Brasile br +ブラジル br +브라질 br +ບາຊີລ br +Brazilija br +Brazīlija br +Brażil br +Brasil br +Brazilië br +Brasil br +Brasil br +Brazylia br +Brasil br +Brasil br +Brazilia br +Бразилия br +Brazília br +Brazilija br +I-Brazil br +Brasilien br +À¢§Ãº¢ø br +บราซิล br +Brezilya br +Бразилія br +Burazili br +Braezi br +巴西 br +巴西 br +Bahamas bs +Багамы bs +Бахами bs +Bahami bs +Bahamák bs +ປານາມາ bs +Bahamy bs +Bahami bs +Багами bs +巴哈马 bs +Bhutan bt +Бутан bt +Бутан bt +Butan bt +Bhután bt +Bhután bt +ຖັກກ່ງວ bt +Butan bt +Бутан bt +不丹 bt +Botswana bw +Батсвана bw +Боцвана bw +Bocvana bw +ບອດສເນີຍ bw +Botsvana bw +Ботсвана bw +博茨瓦纳 bw +Belarus by +روسيا البيضاء by +Беларусь by +Беларус by +Bjelorusija by +Bělorusko by +Hviderusland by +Weißrussland by +Bjelorusio by +Valgevene by +بلاروس by +Valkovenäjä by +Hvítarusland by +Bélarus by +בלרוס by +Bjelorusija by +Fehéroroszország by +HvÃta-Rússland by +Bielorussia by +ベラルーシ by +벨라루스 by +ເບລາລັສ by +Baltarusija by +Baltkrievu by +Hviterussland by +Wit-Rusland by +Kviterussland by +Białoruś by +Bielorússia by +Bielorusso by +Беларусь by +Bielorusko by +Belorusija by +I-Belarus by +Vitryssland by +¦ÀÄ¡åÍ by +เบลารัส by +Білорусія by +Belaruss by +白俄罗斯 by +白俄羅斯 by +Belize bz +Бэлізе bz +Белиз bz +ເບລຍ່ງມ bz +Беліз bz +伯利兹 bz +Default C +Verstek C +افتراضي C +Əsas C +Па ўмаўчаньні C +По подразбиране C +Dre ziouer C +Omissió C +Výchozí C +Standard C +Standard C +Προκαθορισμένο C +Apriora C +Predeterminado C +Vaikimisi C +Aurremugatua C +پیشفرض C +Oletus C +Forsettur C +Par défaut C +Por Omisión C +ברירת מחדל C +Uobičajeno C +Alapértelmezett C +Standar C +Sjálfgefið C +Predefinito C +標準 C +기본 C +ຄ່າປະລິຍາຍ C +Nutylima C +Noklusētais C +Normali C +Standard C +Standaard C +Standard C +Thuso ya Tshoganetso C +Omission C +Domyślnie C +Por Omissão C +Padrão C +Implicit C +По умолчанию C +Štandardný C +Privzeto C +Predefinisano C +Förval C +¦¸¡¼¡¿¢¨Ä C +ค่าปริยาย C +Öntanımlı C +Типовий C +Mặc định C +Prémetou C +Okwendalo C +默认 C +預設 C +Okwendalo C +Canada ca +Kanada ca +كندا ca +Kanada ca +Канада ca +Канада ca +Kanada ca +Kanada ca +Canadà ca +Kanada ca +Kanada ca +Καναδάς ca +Kanado ca +Canadá ca +Kanada ca +Kanada ca +کانادا ca +Kanada ca +Kanada ca +Canadá ca +קנדה ca +Kanada ca +Kanada ca +Kanada ca +Kanada ca +カナダ ca +캐나다 ca +ແຄນາດາ ca +Kanada ca +Kanāda ca +Kanada ca +Kanada ca +Canadá ca +Canadá ca +Канада ca +Kanada ca +Kanada ca +Kanada ca +I-Canada ca +Kanada ca +¸É¼¡ ca +แคนาดา ca +Kanada ca +Канада ca +加拿大 ca +加拿大 ca +Cocos (Keeling) Islands cc +Кокосови Острови cc +Kokosovo (Keeling) ostrvo cc +Islas Cocos (Keeling) cc +Koko Irlak cc +Kókusz-szigetek (Keeling) cc +Ilhas Cocos cc +Kokosove Ostrovy cc +Kokosovi (Keelingovi) otoki cc +Kokosöarna cc +Кокосові острови cc +Congo, the democratic republic of the cd +Дэмакратычная Рэспубліка Конга cd +Конго cd +Kongo, demokratska republika cd +Congo, den demokratiske republik cd +Congo, república democrática del cd +Kongo, errepublika demokratikoa cd +Kongói Demokratikus Köztársaság cd +República Democrática do Congo cd +Demokratická Republika Kongo cd +Kongo, demokratična republika cd +Demokratiska republiken Kongo cd +刚果民主共和国 cd +Central African Republic cf +ЦАР cf +Centralnoafrička Republika cf +Central-afrikanske Republik cf +República Centroafricana cf +Afrika Erdiko Errepublika cf +Közép-Afrikai Köztársaság cf +ໂດມິນິກັນ cf +República da África Central cf +Stredoafrická Republika cf +Centralnoafriška republika cf +Centralafrikanska Republiken cf +Центральноафриканська республіка cf +中非共和国 cf +Congo cg +Конга cg +Конго cg +Kongo cg +Kongo cg +Kongó cg +ຄອນໂໍຊລ cg +Kongo cg +Kongo cg +Kongo cg +Конго cg +刚果 cg +Switzerland ch +Switserland ch +سويسرا ch +İsveçrə ch +Швэйцарыя ch +Швейцария ch +Suis ch +Švicarska ch +Suïssa ch +Švýcarsko ch +Schweiz ch +Schweiz ch +Ελβετία ch +Svislando ch +Suiza ch +Šveits ch +Suitza ch +سوییس ch +Sveitsi ch +Suisse ch +Suíza ch +שוייץ ch +Švicarska ch +Svájc ch +Swiss ch +Sviss ch +Svizzera ch +スイス ch +스위스 ch +ສະວິສເຊີແລນ ch +Šveicarija ch +Šveice ch +Svizzera ch +Sveits ch +Zwitserland ch +Sveits ch +Suissa ch +Szwajcaria ch +Suíça ch +Suíça ch +Elveţia ch +Швейцария ch +Švajčiarsko ch +Švica ch +Švajcarska ch +I-Switzerland ch +Schweiz ch +ÍÅ¢ðº÷Ä¡óÐ ch +สวิสเซอร์แลนด์ ch +İsviçre ch +Швейцарія ch +Thuỵ Sĩ ch +Swisse ch +瑞士 ch +瑞士 ch +Cote d'ivoire ci +Бераг Слановай Косьці ci +Кот'Дивоар ci +Obala Slonovače ci +Elfenbenskysten ci +Costa de Marfil ci +Elefántcsontpart ci +ປ່ອຍຫມາກກະລອກ ci +Slonokoščena obala ci +Elfenbenskusten ci +Кот д'Івуар ci +Cook islands ck +Kukova ostrva ck +Cook-øerne ck +Islas Cook ck +Cook Irlak ck +Cook-szigetek ck +ຄຸກກີ້ ck +Ilhas Cook ck +Cookove ostrovy ck +Cookovi otoki ck +Cooköarna ck +Острови Кука ck +库克群岛 ck +Chile cl +Chilië cl +تشيلي cl +Şili cl +Чылі cl +Чили cl +Čile cl +Xile cl +Χιλή cl +Ĉilio cl +Tšiili cl +Txile cl +شیلی cl +Chili cl +צ'ילה cl +Čile cl +Chili cl +Cile cl +チリ cl +칠레 cl +ຊີລີ cl +Čilė cl +Čīle cl +Ċile cl +Chili cl +Cile cl +Чили cl +Čile cl +Čile cl +Čile cl +I-Chile cl +º¢Ä¢ cl +ชิลี cl +Şili cl +Чилі cl +Chi lê cl +Tchili cl +智利 cl +智利 cl +Cameroon cm +Камэрун cm +Камерун cm +Kamerun cm +Cameroun cm +Camerún cm +Kamerun cm +Kamerun cm +ຕາລາງງານ - K cm +Camarões cm +Komerun cm +Kamerun cm +Kamerun cm +Камерун cm +喀麦隆 cm +China cn +Sjina cn +الصين cn +Çin cn +Кітай cn +Китай cn +Sina cn +Kina cn +Xina cn +Čína cn +Kina cn +Κίνα cn +Ĉinujo cn +Hiina cn +Txina cn +چین cn +Kiina cn +Kina cn +Chine cn +סין cn +Kina cn +Kína cn +Cina cn +KÃna cn +Cina cn +中国 cn +중국 cn +ຈີນ cn +Kinija cn +Ķīna cn +Ċina cn +Kina cn +Kina cn +Xina cn +Chiny cn +Китай cn +Čína cn +Kitajska cn +Kina cn +I-China cn +Kina cn +º£É¡ cn +จีน cn +Çin cn +Китай cn +Trung Quốc cn +Chine cn +中国 cn +中國 cn +Colombia co +Colombië co +كولمبيا co +Калюмбія co +Колумбия co +Kolumbija co +Colòmbia co +Kolumbie co +Kolumbien co +Κολομβία co +Kolumbio co +Kolumbia co +Kolonbia co +کلمبیا co +Kolumbia co +Colombie co +קולומביה co +Kolumbija co +Kolumbia co +コロンビア co +콜롬비아 co +ໂຄລຳເບີຍ co +Kolumbija co +Kolumbija co +Kolumbja co +Columbia co +Kolumbia co +Colômbia co +Colômbia co +Columbia co +Колумбия co +Kolumbia co +Kolumbija co +I-Colombia co +¦¸¡ÄõÀ¢Â¡ co +โคลัมเบีย co +Kolombiya co +Колумбія co +Colombeye co +Columbia co +哥伦比亚 co +哥倫比亞 co +Costa Rica cr +كوستاريكا cr +Коста Рыка cr +Коста Рика cr +Kostarika cr +Kostarika cr +Κόστα Ρίκα cr +کاستاریکا cr +Kosta Rika cr +קוסטה ריקה cr +Costa rica cr +コスタリカ cr +코스타 리카 cr +ໂຄເອເທີຍ cr +Kosta Rika cr +Kostaryka cr +Коста-Рика cr +Kostarika cr +Kostarika cr +I-Costa Rica cr +§¸¡Š¼¡ ⸡ cr +Kosta Rika cr +Коста-Ріка cr +哥斯达黎加 cr +哥斯大黎加 cr +Cuba cu +Kuba cu +كوبا cu +Куба cu +Куба cu +Kuba cu +Kuba cu +Kuba cu +Κούβα cu +Kuuba cu +Kuba cu +کوبا cu +Kuuba cu +Kuba cu +קובה cu +Kuba cu +キューバ cu +쿠바 cu +ເກມໄພ່ cu +Kuba cu +Kuba cu +Kuba cu +Куба cu +Kuba cu +Kuba cu +I-Cuba cu +Kuba cu +¸¢ÔÀ¡ cu +Küba cu +Куба cu +古巴 cu +古巴 cu +Cape Verde cv +Капе Верде cv +Zelenortska ostrva cv +Kapverdiske øer cv +Cabo Verde cv +Cabo Verde cv +Zöldfoki-szigetek cv +ເກມໄພ່ cv +Cabo Verde cv +Kap Verde cv +佛得角 cv +Christmas Island cx +Božično ostrvo cx +Juleøen cx +Islas Christmas cx +Eguberri Irla cx +Karácsony-szigetek cx +ຄິດສະຕອລ cx +Ilhas do Natal cx +Vianočné Ostrovy cx +Božični otok cx +Julön cx +Острів Різдва cx +圣诞岛 cx +Cyprus cy +Кіпр cy +Кипър cy +Kipar cy +Cypern cy +Chipre cy +Txipre cy +Ciprus cy +ບີບອັດ cy +Chipre cy +Ciper cy +Cypern cy +Кипр cy +塞浦路斯 cy +Czechia cz +Czechië cz +التشيك cz +Çex Respublikası cz +Чэхія cz +Чехия cz +Tchekia cz +Češka cz +Txèquia cz +Česko cz +Tjekkiet cz +Tschechien cz +Τσεχία cz +Ĉeĥio cz +República Checa cz +Tšehhi cz +Txekia cz +چک cz +Tsekki cz +République tchèque cz +Chequia cz +צ'כיה cz +Češka cz +Csehország cz +Tékkland cz +Repubblica Ceca cz +チェコ cz +체코 cz +Čekija cz +Čehija cz +Cżekia cz +Tsjekkia cz +Tsjechië cz +Tsjekkia cz +Chèquia cz +Czechy cz +República Checa cz +República Tcheca cz +Cehia cz +Чехия cz +Česko cz +Češka cz +Češka cz +I-Czechia cz +Tjeckien cz +¦ºì¡ cz +Çek Cumhuriyeti cz +Чехія cz +Séc cz +Tchekeye cz +捷克 cz +捷克 cz +Germany de +Duitsland de +ألمانيا de +Almaniya de +Нямеччына de +Германия de +Alamagn de +Njemačka de +Alemanya de +Německo de +Tyskland de +Deutschland de +Γερμανία de +Germanio de +Alemania de +Saksamaa de +Alemania de + آلمان de +Saksa de +Týskland de +Allemagne de +Alemaña de +גרמניה de +Njemačka de +Németország de +Jerman de +Ãýskaland de +Germania de +ドイツ de +독일 de +ເຍລລະມັນນີ de +Vokietija de +Vācija de +Ġermanja de +Tyskland de +Duitsland de +Tyskland de +Alemanya de +Niemcy de +Alemanha de +Alemanha de +Germania de +Германия de +Nemecko de +Nemčija de +Nemačka de +I-Germany de +Tyskland de +§º÷ÁÉ¢ de +เยอรมันนี de +Almanya de +Німеччина de +Đức de +Almagne de +德国 de +德國 de +IJalimani de +Djibouti dj +جيبوتي dj +Джыбуці dj +Джибути dj +Đibuti dj +Džibuti dj +Dschibuti dj +Τζιμπουτί dj +جیبوتی dj +ג'יבוטי dj +Džibuti dj +Dzsibuti dj +ジブティ dj +지부티 dj +ພັດພາ dj +Džibuti dj +Dġibuti dj +Dżibuti dj +Djibuti dj +Djibuti dj +Джибути dj +Džibuty dj +Džibuti dj +I-Djibouti dj +Ê¢ƒ¢¦À¡Ê dj +Cibuti dj +Джібуті dj +吉布提 dj +吉布地 dj +Denmark dk +Denemarke dk +الدنمارك dk +Danimarka dk +Данія dk +Дания dk +Danmark dk +Danska dk +Dinamarca dk +Dánsko dk +Danmark dk +Dänemark dk +Δανία dk +Danlando dk +Dinamarca dk +Taani dk +Danimarka dk +دانمارک dk +Tanska dk +Danmark dk +Danemark dk +Dinamarca dk +דנמרק dk +Danska dk +Dánia dk +Danmörk dk +Danimarca dk +デンマーク dk +덴마크 dk +ເດນມາກ dk +Danija dk +Dānija dk +Danimarka dk +Danmark dk +Denemarken dk +Danmark dk +Dinamarca dk +Dania dk +Dinamarca dk +Dinamarca dk +Danemarca dk +Дания dk +Dánsko dk +Danska dk +Danska dk +I-Denmark dk +Danmark dk +¦¼ýÁ¡÷ì dk +เดนมาร์ก dk +Danimarka dk +Данія dk +Đan Mạch dk +Daenmåtche dk +丹麦 dk +丹麥 dk +Dominica dm +Дамініка dm +Доминика dm +Dominika dm +Dominika dm +ໂລມາເນີຍ dm +Dominicana dm +Dominikánsko dm +Dominikanska republika dm +Домініка dm +多米尼加 dm +Dominican Republic do +Dominikiese Republiek do +جمهورية الدومينيكان do +Dominik Respublikası do +Дамініканская Рэспубліка do +Доминиканска република do +Republik Dominikan do +Dominikanska Republika do +República Dominicana do +Dominikánská republika do +Dominikanske Republik do +Dominikanische Republik do +Δομινικανή Δημοκρατία do +Dominika Respubliko do +República Dominicana do +Dominikaani Vabariik do +Dominikar Errepublika do +جمهوری دامینیکن do +Dominikaaninen tasavalta do +République dominicaine do +República Dominicana do +הרפובליקה הדומיניקנית do +Dominikanska Republika do +Dominikai Köztársaság do +Republik Dominika do +DóminÃska Lýðveldið do +Repubblica Dominicana do +ドミニカ共和国 do +도미니카 공화국 do +ໂດມິນີກັນ do +Dominikos Respublika do +Dominikas Republika do +Repubblika Dominikana do +Den dominikanske republikk do +Dominicaanse Republiek do +Den dominikanske republikken do +Republica Dominicana do +Dominikana do +República Dominicana do +República Dominicana do +Republica Dominicană do +Доминиканская республика do +Dominikánska republika do +Dominikanska republika do +Dominikanska republika do +I-Dominican Republic do +Dominikanska republiken do +¦¼¡Á¢É¢ì¸ý ÌÊÂÃÍ do +โดมินิกัน do +Dominik Cumhuriyeti do +Домініканська республіка do +Muvhuso wa Dominican do +Cộng hoà Dominican do +Republike Dominikinne do +IRepublic yeDominican do +多米尼加共和国 do +多明尼加共和國 do +Algeria dz +Algerië dz +الجزائر dz +Альжыр dz +Алжир dz +Alžir dz +Algèria dz +Alžírsko dz +Algeriet dz +Algerien dz +Αλγερία dz +Algerio dz +Argelia dz +Alžeeria dz + الجزیره dz +Algérie dz +אלג'יריה dz +Alžir dz +Algéria dz +アルジェリア dz +알제리 dz +ບັນກາເລີຍ dz +Alžyras dz +Alġerija dz +Algerie dz +Algerije dz +Algerie dz +Algieria dz +Argélia dz +Argélia dz +Алжир dz +Alžírsko dz +Alžirija dz +I-Algeria dz +Algeriet dz +«øƒ¢Ã¢Â¡ dz +Алжир dz +Aldjereye dz +阿尔及利亚 dz +阿爾及利亞 dz +Equador ec +Ewenaar ec +الإكوادور ec +Ekvator ec +Эквадор ec +Еквадор ec +Ecuador ec +Ekvador ec +Ekvádor ec +Ecuador ec +Ισημερινός ec +Ekvadoro ec +Ecuador ec +Ekvador ec +Ekuador ec +اکوادور ec +Équateur ec +Ecuador ec +אקוודור ec +Ekvador ec +Ecuador ec +Ekvador ec +Ecuador ec +エクアドル ec +에콰도르 ec +ເອກໍດໍ ec +Ekvadoras ec +Ekvadora ec +Ekwador ec +Ecuador ec +Ecuador ec +Ekwador ec +Ecuador ec +Эквадор ec +Ekvádor ec +Ekvador ec +Ekvador ec +I-Equador ec +®ì¦Å§¼¡÷ ec +เอกวาดอร์ ec +Ekvator ec +Еквадор ec +Ecwåteur ec +厄瓜多尔 ec +厄瓜多 ec +Estonia ee +Estlandies ee +استونيا ee +Estoniya ee +Эстонія ee +Естония ee +Estonija ee +Estònia ee +Estonsko ee +Estland ee +Estland ee +Εσθονία ee +Estlando ee +Eesti ee +استونی ee +Eesti ee +Estonie ee +אסטוניה ee +Estonija ee +Észtország ee +Eistland ee +エストニア ee +에스토니아 ee +ເອໂທເນີຍ ee +Estija ee +Igaunija ee +Estonja ee +Estland ee +Estland ee +Estland ee +Estònia ee +Estónia ee +Estônia ee +Эстония ee +Estónsko ee +Estonija ee +Estonija ee +I-Estonia ee +Estland ee +±Í§¼¡É¢Â¡ ee +เอสโธเนีย ee +Estonya ee +Естонія ee +Estoneye ee +爱沙尼亚 ee +愛沙尼亞 ee +Egypt eg +Egipte eg +مصر eg +Misir eg +Эгіпэт eg +Египет eg +Egipat eg +Egipte eg +Egypten eg +Ägypten eg +Αίγυπτος eg +Egiptujo eg +Egipto eg +Egiptus eg +Egypto eg +مصر eg +Egypti eg +Egyptaland eg +Égypte eg +מצרים eg +Egipat eg +Egyiptom eg +Egyptaland eg +Egitto eg +エジプト eg +이집트 eg +ອີຢີບ eg +Egiptas eg +Ēģipte eg +Eġittu eg +Egypte eg +Egepeta eg +Egipt eg +Egipto eg +Egito eg +Egipt eg +Египет eg +Egipt eg +I-Egypt eg +Egypten eg +±¸¢ôÐ eg +อียิปต์ eg +Mısır eg +Єгипет eg +Edjipe eg +埃及 eg +埃及 eg +Igibhithe eg +Western Sahara eh +Западна Сахара eh +Zapadna Sahara eh +Vestsahara eh +Sahara occidental eh +Mendebaldeko Sahara eh +Nyugat-Szahara eh +ພື້ນທີ່ທຳງານ eh +Sahara eh +Západna Sahara eh +Zahodna Sahara eh +Västsahara eh +Західна Сахара eh +西撒哈拉 eh +Eritrea er +Эрытрэя er +Еритрея er +Eritreja er +ແກ້ໄຂແຟ້ມທຳງານ er +Eritreja er +Еритрея er +厄立特里亚 er +Spain es +Spanje es +أسبانيا es +İspaniya es +Гішпанія es +Испания es +Spagn es +Španija es +Espanya es +Španělsko es +Spanien es +Spanien es +Ισπανία es +Hispanio es +España es +Hispaania es +Espainia es +اسپانیا es +Espanja es +Spania es +Espagne es +España es +ספרד es +Španjolska es +Spanyolország es +Spanyol es +Spánn es +Spagna es +スペイン es +스페인 es +ສະເປັນ es +Ispanija es +Spānija es +Spanja es +Spania es +Spanje es +Spania es +Espanha es +Hiszpania es +Espanha es +Espanha es +Spania es +Испания es +Španielsko es +Španija es +Španija es +I-Spain es +Spanien es +ͦÀ¢ý es +สเปน es +İspanya es +Іспанія es +Tây Ban Nha es +Sipagne es +西班牙 es +西班牙 es +Ethiopia et +Этыёпія et +Етиопия et +Etiopija et +Ethiopien et +Etiopía et +Etiopia et +Etiópia et +ເອໂທເນີຍ et +Etiópia et +Etiópia et +Etiopija et +Etiopien et +Ефіопія et +埃塞俄比亚 et +Finland fi +فنلندا fi +Finlandiya fi +Фінляндыя fi +Финландия fi +Finska fi +Finlàndia fi +Finsko fi +Finnland fi +Φινλανδία fi +Finlando fi +Finlandia fi +Soome fi +Finlandia fi +فنلاند fi +Suomi fi +Finnland fi +Finlande fi +Finlandia fi +פינלנד fi +Finska fi +Finnország fi +Finlandia fi +Finnland fi +Finlandia fi +フィンランド fi +핀란드 fi +ຟີນແລນ fi +Suomija fi +Somija fi +Finlandja fi +Finlandia fi +Finlandia fi +Finlândia fi +Finlândia fi +Finlanda fi +Финляндия fi +Fínsko fi +Finska fi +Finska fi +I-Finland fi +À¢ýÄ¡óÐ fi +ฟินแลนด์ fi +Finlandiya fi +Фінляндія fi +Phần Lan fi +Finlande fi +芬兰 fi +芬蘭 fi +Fiji fj +Фіджы fj +Фиджи fj +Fidži fj +Fidzsi fj +ມີດີ fj +Ilhas Fiji fj +Fidži fj +Fidži fj +Фіджі fj +斐济 fj +Falkland Islands (Malvinas) fk +Фолклендски Острови fk +Foklandska ostrva (Malvini) fk +Falkland-øerne fk +Islas Falkland (Malvinas) fk +Falkland Irlak (Malvinak) fk +Falkland-szigetek fk +Ilhas Malvinas fk +Falklandské Ostrovy (Malviny) fk +Falklandski otoki (Malvini) fk +Falklandsöarna fk +福克兰岛 (马尔维纳斯) fk +Micronesia, Federated states of fm +Федэрацыя Мiкранэзіі fm +Микронезия fm +Mikronezija, Federalne države fm +Mikronesien, de forenede stater af fm +Micronesia, Estados federados de fm +Mikronesia, Estatu Federatuak fm +Mikronézia fm +Estados Federados da Micronésia fm +Spjoené štáty Mikronézie fm +Mikronezija, Združene države fm +Mikronesiska federationen fm +密克罗尼西亚联邦 fm +Faroe Islands fo +Фареорски Острови fo +Farska ostrva fo +Færøerne fo +islas Faroe fo +Faroe Irlak fo +Faroe-szigetek fo +ໄອແລນ fo +Ilhas Faroe fo +Ostrovy Faroe fo +Otoki Faroe fo +Färöarna fo +Фарерські острови fo +France fr +Frankryk fr +فرنسا fr +Fransa fr +Францыя fr +Франция fr +Frañs fr +Francuska fr +França fr +Francie fr +Frankrig fr +Frankreich fr +Γαλλία fr +Francio fr +Francia fr +Prantsusmaa fr +Frantzia fr +فرانسه fr +Ranska fr +Frakland fr +Francia fr +צרפת fr +Francuska fr +Franciaország fr +Prancis fr +Frakkland fr +Francia fr +フランス fr +프랑스 fr +ຝຣັ່ງ fr +Prancūzija fr +Francija fr +Franza fr +Frankrike fr +Frankrijk fr +Frankrike fr +Fora fr +França fr +Francja fr +França fr +França fr +Franţa fr +Франция fr +Francúzsko fr +Francija fr +Francuska fr +I-France fr +Frankrike fr +À¢Ã¡ýÍ fr +ฝรั่งเศส fr +Fransa fr +Франція fr +Fura fr +Pháp fr +Fransi fr +法国 fr +法國 fr +Gabon ga +Габон ga +Габон ga +Gabón ga +ແກລ່ງນ ga +Gabão ga +Габон ga +加蓬 ga +United Kingdom gb +Vereenigde Koninkryk gb +المملكة المتحدة gb +Birləşmiş Krallıq gb +Злучанае Каралеўства gb +Великобритания gb +Rouantelezh Unanet gb +Velika Britanija gb +Regne Unit gb +Spojené království gb +Storbritannien gb +Großbritannien gb +Ηνωμένο Βασίλειο gb +Britio gb +Reino Unido gb +Ühendatud Kuningriigid gb +Erreinu Batua gb +بریتانیا gb +Iso-Britannia gb +Stórabretland gb +Royaume Uni gb +Reino Unido gb +בריטניה gb +Ujedinjeno Kraljevstvo gb +Egyesült Királyság gb +Inggris gb +Stóra Bretland gb +Regno Unito gb +イギリス gb +영국 gb +ສະຫະລາດສະອານາຈັກ gb +Jungtinė Karalystė gb +Apvienotā Karaliste gb +Renju Unit gb +Storbritannia gb +Verenigd Koninkrijk gb +Storbritannia gb +Regne Unit gb +Wielka Brytania gb +Reino Unido gb +Reino Unido gb +Anglia gb +Великобритания gb +Anglicko gb +Združeno kraljestvo gb +Velika Britanija gb +I-United Kingdom gb +Storbritannien gb +³ì¸¢Â áÂõ gb +สหราชอาณาจักร gb +Birleşik Krallık gb +Великобританія gb +Anh gb +United Kingdom gb +联合王国 gb +聯合王國 gb +United Kingdom gb +Grenada gd +غرينادا gd +Qrenada gd +Грэнада gd +Гренада gd +Granada gd +Γρενάδα gd +Grenado gd +Granada gd +گرانادا gd +Grenade gd +Granada gd +גרנדה gd +Grænhöfðaeyjar gd +Granada gd +グラナダ gd +그러네이다 gd +ເກນາດາ gd +Grenāda gd +Granada gd +Granada gd +Granada gd +Гренада gd +I-Grenada gd +¸¢¦Ãɼ¡ gd +เกรนาดา gd +Гренада gd +格林纳达 gd +格瑞那達 gd +Georgia ge +Грузія ge +Грузия ge +Gruzija ge +Georgien ge +Grúzia ge +ເຊີເບີຍ ge +Geórgia ge +Gruzija ge +Georgien ge +Грузія ge +格鲁吉亚 ge +Ghana gh +غانا gh +Гана gh +Гана gh +Gana gh +Γκάνα gh +غنا gh +גאנה gh +ガーナ gh +ຈີນ gh +Gana gh +Gana gh +Gana gh +Гана gh +Gana gh +I-Ghana gh +¸¡É¡ gh +Гана gh +加纳 gh +迦納 gh +Gibraltar gi +Гибралтар gi +Gibraltár gi +ມອລຕາ gi +Гібралтар gi +直布罗陀 gi +Gambia gm +Гамбія gm +Гамбия gm +Gambija gm +ແກມມາ gm +Gâmbia gm +Gambija gm +Гамбія gm +冈比亚 gm +Guinea gn +Гвінэя gn +Гвинея gn +Gvineja gn +ເຖາວັນ gn +Guiné gn +Gvineja gn +Гвінея gn +几内亚 gn +Guadeloupe gp +Гвадалупа gp +Gvadalupe gp +Guadalupe gp +ເດີລຸກ gp +Guadalupe gp +Гваделупа gp +瓜德罗普岛 gp +Equatorial Guinea gq +Экватарыяльная Гвінэя gq +Екваториялна Гвинея gq +Ekvatorijalna Gvineja gq +Ækvatorial Guinea gq +Guinea equatorial gq +Ginea Ekuatoriala gq +Egyenlítői Guinea gq +ການສອນ gq +Guiné Equatorial gq +Rovníkova Guinea gq +Ekvatorialna Gvineja gq +Ekvatorialguinea gq +Екваторіальна Гвінея gq +赤道几内亚 gq +Greece gr +Griekeland gr +اليونان gr +Yunanıstan gr +Грэцыя gr +Гърция gr +Gres gr +Grčka gr +Grècia gr +Řecko gr +Grækenland gr +Griechenland gr +Ελλάδα gr +Grekujo gr +Grecia gr +Kreeka gr +Grezia gr +یونان gr +Kreikka gr +Grikkaland gr +Grèce gr +Grecia gr +יוון gr +Grčka gr +Görögország gr +Grikkland gr +Grecia gr +ギリシャ gr +그리스 gr +ກີຊ gr +Graikija gr +Grieķija gr +Greċja gr +Hellas gr +Griekenland gr +Hellas gr +Grèça gr +Grecja gr +Grécia gr +Grécia gr +Grecia gr +Греция gr +Grécko gr +Grčija gr +Grčka gr +I-Greece gr +Grekland gr +¸¢Ã£Í gr +กรีซ gr +Yunanistan gr +Греція gr +Hy Lạp gr +Grece gr +希腊 gr +希臘 gr +Guatemala gt +Gautemala gt +غواتيمالا gt +Quatemala gt +Гватэмала gt +Гватемала gt +Gvatemala gt +Γουατεμάλα gt +Gvatemalo gt +Guatemaala gt +گواتمالا gt +גואטמלה gt +Gvatemala gt +カタロニア gt +과테말라 gt +ກັວເຕມາລາ gt +Gvatemala gt +Gvatemala gt +Gwatemala gt +Gwatemala gt +Гватемала gt +Gvatemala gt +Gvatemala gt +I-Guatemala gt +ÌÅ¡ò¾Á¡Ä¡ gt +กัวเตมาลา gt +Гватемала gt +Gwatemala gt +瓜地马拉 gt +瓜地馬拉 gt +Guam gu +Гуам gu +ແກມມາ gu +Гуам gu +关岛 gu +Guinea-Bissau gw +Гвінэя-Бісаў gw +Гвинея-Бисау gw +Gvineja-Bisau gw +Ginea-Bissau gw +Bissau-Guinea gw +ລັດເຊີຍ gw +Guiné-Bissau gw +Гвінея-Біссау gw +几内亚比绍 gw +Guyana gy +Гвіяна gy +Гуана gy +Gvajana gy +ຈີນ gy +Guiana gy +Gvajana gy +Гаяна gy +圭亚那 gy +Hong Kong hk +Ганконг hk +Хонг Конг hk +Hongkong hk +ບໍ່ຮູ້ຈັກ hk +Гонконг hk +香港 hk +Honduras hn +هندوراس hn +Гандурас hn +Хондурас hn +Hondures hn +Ονδούρα hn +Honduraso hn +Honduuras hn +هندوراس hn +הונדורס hn +ホンデュラス hn +온두라스 hn +ຫອນດູລັດ hn +Hondūras hn +Hondurasa hn +Ħonduras hn +Hondures hn +Гондурас hn +I-Honduras hn +¬ñÎÃ¡Í hn +ฮอนดูรัส hn +Гондурас hn +洪都拉斯 hn +宏都拉斯 hn +Croatia hr +Kroatië hr +كرواتيا hr +Xırvatıstan hr +Харватыя hr +Хърватска hr +Kroatia hr +Hrvatska hr +Croàcia hr +Chorvatsko hr +Kroatien hr +Kroatien hr +Κροατία hr +Kroatio hr +Croacia hr +Horvaatia hr +Kroazia hr +کرواسی hr +Kroatia hr +Kroatia hr +Croatie hr +Croacia hr +קרואטיה hr +Hrvatska hr +Horvátország hr +Kroasia hr +KróatÃa hr +Croazia hr +クロアチア hr +크로아티아 hr +ໂຄເອເທີຍ hr +Kroatija hr +Horvātija hr +Kroazja hr +Kroatia hr +Kroatië hr +Kroatia hr +Croacia hr +Chorwacja hr +Croácia hr +Croácia hr +Croaţia hr +Хорватия hr +Chorvátsko hr +Hrvaška hr +Hrvatska hr +I-Croatia hr +Kroatien hr +̦á§Åº¢Â¡ hr +โครเอเธีย hr +Hırvatistan hr +Хорватія hr +Crowåceye hr +克罗地亚 hr +克羅埃西亞 hr +Haiti ht +Гаіці ht +Хаити ht +Haití ht +ວາດຮູບ - K ht +Гаїті ht +海地岛 ht +Hungary hu +Hongarye hu +هنغاريا hu +Macarıstan hu +Вугоршчына hu +Унгария hu +Hungaria hu +Mađarska hu +Hongria hu +Maďarsko hu +Ungarn hu +Ungarn hu +Ουγγαρία hu +Hungario hu +Hungría hu +Ungari hu +Hungaria hu +مجارستان hu +Unkari hu +Ungarn hu +Hongrie hu +Hungría hu +הונגריה hu +Mađjarska hu +Magyarország hu +Hungaria hu +Ungverjaland hu +Ungheria hu +ハンガリー hu +헝가리 hu +ຫັງກາລີ hu +Vengrija hu +Ungārija hu +Ungerija hu +Ungarn hu +Hongarije hu +Ungarn hu +Hongria hu +Węgry hu +Hungria hu +Hungria hu +Ungaria hu +Венгрия hu +Maďarsko hu +Madžarska hu +Mađarska hu +I-Hungary hu +Ungern hu +¬í§¸Ã¢ hu +ฮังการี hu +Macaristan hu +Угорщина hu +Hongreye hu +匈牙利 hu +匈牙利 hu +Indonesia id +Indonesië id +إندونيسيا id +İndoneziya id +Інданэзія id +Индонезия id +Indonezija id +Indonèsia id +Indonésie id +Indonesien id +Indonesien id +Ινδονησία id +Indonezio id +Indoneesia id +اندونزی id +Indonésie id +אינדונזיה id +Indonezija id +Indonézia id +IndónesÃa id +インドネシア id +인도네시아 id +ອີຍໂດນີເຊີຍ id +Indonezija id +Indonēzija id +Indoneżja id +Indonesië id +Indonezja id +Indonésia id +Indonésia id +Indonezia id +Индонезия id +Indonézia id +Indonezija id +I-Indonesia id +Indonesien id +󧾡ɣº¢Â¡ id +อินโดนีเซีย id +İndonezya id +Індонезія id +Indoneseye id +印度尼西亚 id +印尼 id +Ireland ie +Ierland ie +أيرلندا ie +İrlandiya ie +Ірляндыя ie +Ирландия ie +Iwerzhon ie +Irska ie +Irlanda ie +Irsko ie +Irland ie +Irland ie +Ιρλανδία ie +Islando ie +Irlanda ie +Island ie +Irlanda ie +ایرلند ie +Irlanti ie +Írland ie +Irlande ie +Irlanda ie +אירלנד ie +Irska ie +Írország ie +Irlandia ie +Ãrland ie +Irlanda ie +アイスランド ie +아일랜드 ie +ໄອແລນ ie +Airija ie +Īrija ie +Irlanda ie +Irland ie +Ierland ie +Irland ie +Irlanda ie +Irlandia ie +Irlanda ie +Irlanda ie +Irlanda ie +Ирландия ie +Írsko ie +Irska ie +Irska ie +I-Ireland ie +Irland ie +«Â÷Ä¡óÐ ie +ไอร์แลนด์ ie +İrlanda ie +Ірландія ie +Irlande ie +爱尔兰 ie +愛爾蘭 ie +Israel il +اسرائيل il +İzrail il +Ізраіль il +Израел il +Izrael il +Izrael il +Ισραήλ il +Israelo il +Iisrael il +اسراییل il +Ísrael il +Israël il +ישראל il +Izrael il +Izrael il +Ãsrael il +Israele il +イスラエル il +이스라엘 il +ອິດສະລະເອລ il +Izraelis il +Izraēla il +Iżrael il +Izrael il +Израиль il +Izrael il +Izrael il +Izrael il +I-Israel il +Í§Ãø il +อิสราเอล il +İsrail il +Ізраїль il +Israyel il +USirayeli il +以色列 il +以色列 il +India in +Indië in +الهند in +Hindistan in +Індыя in +Индия in +Indija in +Índia in +Indie in +Indien in +Indien in +Ινδία in +Hindujo in +هندوستان in +Intia in +Inde in +הודו in +Indija in +Indland in +インド in +인도 in +ອິນເດີຍ in +Indija in +Indija in +Indja in +Indie in +Índia in +Índia in +Индия in +Indija in +I-India in +Indien in +ó¾¢Â¡ in +อินเดีย in +Hindistan in +Індія in +Inde in +印度 in +印度 in +Endiya in +Iraq iq +Irak iq +العراق iq +İraq iq +Ірак iq +Ирак iq +Irak iq +Irák iq +Irak iq +Irak iq +Ιράκ iq +Irako iq +Irak iq +Iraak iq +عراق iq +Irak iq +Irak iq +Irak iq +עירק iq +Irak iq +Irak iq +Ãrak iq +Irak iq +イラク iq +이라크 iq +ອີລັກ iq +Irakas iq +Irāka iq +Irak iq +Irak iq +Irak iq +Irak iq +Iraque iq +Iraque iq +Irak iq +Ирак iq +Irák iq +Irak iq +I-Iraq iq +Irak iq +®Ã¡ì iq +อิรัค iq +Irak iq +Ірак iq +Irak iq +伊拉克 iq +伊拉克 iq +Iran ir +أيران ir +Іран ir +Иран ir +Írán ir +Ιράν ir +Iraan ir +ایران ir +אירן ir +Irán ir +イラン ir +이란 ir +ອີລັກ ir +Iranas ir +Irão ir +Irã ir +Иран ir +Irán ir +I-Iran ir +®Ã¡ý ir +İran ir +Іран ir +伊朗 ir +伊朗 ir +Iceland is +Ysland is +أيسلندا is +İslandiya is +Ісьляндыя is +Исландия is +Island is +Island is +Islàndia is +Island is +Island is +Island is +Ισλανδία is +Islando is +Islandia is +Island is +Islandia is +ایسلند is +Islanti is +Ísland is +Islande is +Islandia is +איסלנד is +Island is +Izland is +Islandia is +Ãsland is +Islanda is +アイスランド is +아이슬란드 is +ໄອຊແລນ is +Islandija is +Islande is +Islandja is +Island is +IJsland is +Island is +Islandia is +Islandia is +Islândia is +Islândia is +Islanda is +Исландия is +Island is +Islandija is +Island is +I-Iceland is +Island is +³ÍÄ¡óÐ is +ไอซ์แลนด์ is +İzlanda is +Ісландія is +Izlande is +冰岛 is +冰島 is +Icelandi is +Italy it +Italië it +ايطاليا it +İtalyia it +Італія it +Италия it +Italia it +Italija it +Itàlia it +Itálie it +Italien it +Italien it +Ιταλία it +Italio it +Italia it +Itaalia it +Italia it +ایتالیا it +Italia it +Italia it +Italie it +Italia it +איטליה it +Italija it +Olaszország it +Italia it +ÃtalÃa it +Italia it +イタリア it +이탈리아 it +ອີຕາລີ it +Italija it +Itālija it +Italja it +Italia it +Italië it +Italia it +Italia it +Włochy it +Itália it +Itália it +Italia it +Италия it +Taliansko it +Italija it +Italija it +I-Italy it +Italien it +ò¾¡Ä¢ it +อิตาลี it +İtalya it +Італія it +Itåleye it +Ithali it +意大利 it +義大利 it +Jamaica jm +Jamaika jm +جامايكا jm +Yamayka jm +Ямайка jm +Ямайка jm +Jamaika jm +Jamajka jm +Jamajka jm +Jamaika jm +Τζαμάικα jm +Ĵamaiko jm +Jamaika jm +Jamaika jm +جاماییکا jm +Jamaika jm +Jamaïque jm +Xamaica jm +ג'מייקה jm +Jamajka jm +Jamaika jm +Jamaika jm +Giamaica jm +ジャマイカ jm +자메이카 jm +ຈາໄມກາ jm +Jamaika jm +Jamaika jm +Ġamajka jm +Jamajka jm +Ямайка jm +Jamajka jm +Jamajka jm +Jamajka jm +I-Jamaica jm +º¦Áö측 jm +จาไมกา jm +Jamaika jm +Ямайка jm +Djamayike jm +牙买加 jm +牙買加 jm +Jordan jo +Jordaan jo +الأردن jo +İordaniya jo +Ярданія jo +Йордания jo +Jordania jo +Jordán jo +Jordanien jo +Ιορδανία jo +Jordanio jo +Jordania jo +اردن jo +Jordania jo +Jordanie jo +ירדן jo +Jordánia jo +JórdanÃa jo +Giordania jo +ヨルダン jo +요르단 jo +ຈໍແດນ jo +Jordanija jo +Jordāna jo +Ġordan jo +Jordanië jo +Jordania jo +Jordânia jo +Jordânia jo +Iordania jo +Иордания jo +Jordánsko jo +Jordanija jo +I-Jordan jo +Jordanien jo +§Â¡÷¾¡ý jo +จอร์แดน jo +Ürdün jo +Йорданія jo +Djordaneye jo +约旦 jo +約旦 jo +Ijolidani jo +Japan jp +اليابان jp +Yaponiya jp +Японія jp +Япония jp +Japó jp +Japonsko jp +Ιαπωνία jp +Japanio jp +Japón jp +Jaapan jp +Japonia jp +ژاپن jp +Japani jp +Japon jp +Xapón jp +יפן jp +Japán jp +Jepang jp +Giappone jp +日本 jp +일본 jp +ຍີ່ປຸ່ນ jp +Japonija jp +Japāna jp +Ġappun jp +Japon jp +Japonia jp +Japão jp +Japão jp +Japonia jp +Япония jp +Japonsko jp +Japonska jp +I-Japan jp +ºôÀ¡ý jp +ญี่ปุ่น jp +Japonya jp +Японія jp +Nhật bản jp +Djapon jp +日本 jp +日本 jp +Kenya ke +Кенія ke +Кения ke +Kenija ke +Kenia ke +ເວນດາ ke +Quênia ke +Keňa ke +Kenija ke +Кенія ke +肯尼亚 ke +Kyrgyzstan kg +Кыргызстан kg +Киргистан kg +Kirgistan kg +Kirgizistan kg +Kyrgyzstán kg +Kirgizisztán kg +ຄສິຕັລ kg +Kirgizstan kg +Kirgizistan kg +Киргизстан kg +吉尔吉斯坦 kg +Cambodia kh +Камбоджа kh +Камбоджа kh +Kambođa kh +Kambodzsa kh +ໂຄລຳເບີຍ kh +Cambodja kh +Kambodža kh +Kambodža kh +Kambodja kh +Камбоджа kh +柬埔寨 kh +Kiribati ki +Кiрыбацi ki +Кирибати ki +ແຟຄທັລ - K ki +Кірібаті ki +基里巴斯 ki +Comoros km +Каморы km +Коморски km +Komori km +Comorerne km +ສີ km +Komori km +Komorerna km +Комори km +科摩罗群岛 km +St. Kitts and Nevis kn +St. Kitts en Nevis kn +سانت كيتس و نيفيس kn +St. Kitts və Nevis kn +Св. Кристоф и Невис kn +S. Kitts ha Nevis kn +St. Kitts i Nevis kn +Sv. Kitts a Nevis kn +St. Kitts-Nevis kn +St. Kitts und Nevis kn +St. Kitts και Nevis kn +St. Kitts kaj Nevis kn +St. Kitts y Nevis kn +St. Kitts ja Nevis kn +St. Kitts eta Nevis kn +سن کیتس و نویس kn +St. Kitts ja Nevis kn +St Kitts et Nevis kn +Saint Kitts e Nevis kn +סנט קיטס ונביס kn +St. Kitts és Nevis kn +St. Kitts dan Nevis kn +Ss. Kitts e Nevis kn +セントキッツネヴィス kn +세인트 키츠 네비스 kn +Šv. Kitts ir Nevis kn +St. Kitts un Nevis kn +St. Kitts u Nevis kn +St. Kitts og Nevis kn +St. Kitts en Nevis kn +St. Kitts og Nevis kn +St. Kitts le Nevis kn +St. Kitts e Nevis kn +St. Kitts e Nevis kn +St Kitts e Nevis kn +Sf. Kitts şi Nevis kn +о. Св. Кристофа и Невиса kn +St. Kitts a Nevis kn +St. Kitts in Nevis kn +St. Kitts i Nevis kn +I-St. Kitts and Nevis kn +St. Kitts och Nevis kn +¦ºÂ¢ý𠸢ðÍ & ¦¿Å¢Í kn +St. Kitts ve Nevis kn +Федерація Сент-Кітс і Невіс kn +St. Kitts na Nevis kn +St. Kitts neNevis kn +圣基特和里维斯 kn +聖克理斯多福及尼維斯 kn +St. Kitts kanye no-Nevis kn +North Korea kp +Noord Korea kp +كوريا الشمالية kp +Şimali Koreya kp +Паўночная Карэя kp +Северна Корея kp +Norzh-Korea kp +Sjeverna Koreja kp +Corea del Nord kp +Severní Korea kp +Nordkorea kp +Nord-Korea kp +Βόρεια Κορέα kp +Nordkoreo kp +Corea del Norte kp +Põhja-Korea kp +Ipar Korea kp +کره شمالی kp +Pohjois-Korea kp +Norðurkorea kp +Corée du nord kp +Corea do Norte kp +צפון קוריאה kp +Sjeverna Koreja kp +Észak-Korea kp +Korea Utara kp +Kórea - Norðurkórea kp +Corea del Nord kp +北朝鮮 kp +조선민주주의 인민공화국 kp +ເກົາລີເຫນືອ kp +Šiaurės Korėja kp +ZiemeļKoreja kp +Korea ta' Fuq kp +Nord-Korea kp +Noord-Korea kp +Nord-Korea kp +Lebowa la Korea kp +Corea dèu Nord kp +Korea Północna kp +Coreia do Norte kp +Coréia do Norte kp +Coreea de Nord kp +Северная Корея kp +severná Kórea kp +Severna Koreja kp +Severna Koreja kp +I-North Korea kp +Nordkorea kp +ż ¦¸¡Ã¢Â¡ kp +เกาหลีเหนือ kp +Kuzey Kore kp +Північна Корея kp +Devhula ha Korea kp +Bắc Triều Tiên kp +Bijhe Coreye kp +Umntla Korea kp +朝鲜 kp +北韓 kp +Enyakatho ne-Korea kp +South Korea kr +Suid Korea kr +كوريا الجنوبية kr +Cənubi Koreya kr +Паўднёвая Карэя kr +Южна Корея kr +Su-Korea kr +Južna Koreja kr +Corea del Sud kr +Jižní Korea kr +Sydkorea kr +Süd-Korea kr +Νότια Κορέα kr +Sudkoreo kr +Corea del Sur kr +Lõuna-Korea kr +Hego Korea kr +کره جنوبی kr +Etelä-Korea kr +Suðurkorea kr +Corée du sud kr +Corea do Sur kr +דרום קוריאה kr +Južna Koreja kr +Dél-Korea kr +Korea Selatan kr +Kórea - Suðurkórea kr +Corea del Sud kr +韓国 kr +대한민국 kr +ເກົາລີໃຕ້ kr +Pietų Korėja kr +DievidKoreja kr +Korea t'Isfel kr +Sør-Korea kr +Zuid-Korea kr +Sør-Korea kr +Borwa bja Korea kr +Corea dèu Sud kr +Korea Południowa kr +Coreia do Sul kr +Coréia do Sul kr +Coreea de Sud kr +Южная Корея kr +Južná Kórea kr +Južna Koreja kr +Južna Koreja kr +I-South Korea kr +Sydkorea kr +¦¾ý ¦¸¡Ã¢Â¡ kr +เกาหลีใต้ kr +Güney Kore kr +Південна Корея kr +Korea tshipembe kr +Hàn Quốc kr +Nonne Coreye kr +Umzantsi Korea kr +韩国 kr +南韓 kr +Emzansi Korea kr +Kuwait kw +Kuwaït kw +الكويت kw +Кувэйт kw +Кувейт kw +Kuvajt kw +Kuvajt kw +Κουβέιτ kw +Kuveit kw +کویت kw +Kuvait kw +Kowait kw +כווית kw +Kuvajt kw +Kuvait kw +クェート kw +쿠웨이트 kw +ແຕ້ມຮູບ- K kw +Kuveitas kw +Koeweit kw +Koweit kw +Kuveit kw +Кувейт kw +Kuvajt kw +Kuvajt kw +I-Kuwait kw +̨Åò kw +KКувейт kw +科威特 kw +科威特 kw +Cayman Islands ky +Кайманови Острови ky +Kajmanska ostrva ky +Cayman-øerne ky +Islas Caimán ky +Kaiman Irlak ky +Kajmán-szigetek ky +ຄາຕາລັນ ky +Ilhas Cayman ky +Kajmanske Ostrovy ky +Kajmanski otoki ky +Caymanöarna ky +Кайманські острови ky +开曼群岛 ky +Kazakhstan kz +Казахстан kz +Казахстан kz +Kazahstan kz +Kazakhstán kz +Kazahsztán kz +ແກແລກຕິກ - K kz +Kazaquistão kz +Kazachstan kz +Kazahstan kz +Kazakstan kz +Казахстан kz +哈萨克斯坦 kz +Laos la +Лаос la +Лаос la +Laosz la +ລາວ la +老挝 la +Lebanon lb +Libanon lb +لبنان lb +Ліван lb +Ливан lb +Liban lb +Libanon lb +Libanon lb +Libanon lb +Λίβανος lb +Lebanono lb +Líbano lb +Liibanon lb +لبنان lb +Libanon lb +Libanon lb +Liban lb +לבנון lb +Libanon lb +Libanon lb +Libano lb +レバノン lb +레바논 lb +ເດນ່ງນ lb +Libanas lb +Libanu lb +Libanon lb +Libanon lb +Libanon lb +Liban lb +Líbano lb +Líbano lb +Liban lb +Ливан lb +Libanon lb +Libanon lb +I-Lebanon lb +Libanon lb +¦ÄÀÉ¡ý lb +Ліван lb +Liban lb +黎巴嫩 lb +黎巴嫩 lb +St. Lucia lc +سانت لوسيا lc +Св. Люсиа lc +S. Lucia lc +Svatá Lucie lc +Σάντα Λουτσία lc +St. Lucio lc +Santa Lucía lc +سن لوسیا lc +Sankta Lusia lc +Sainte Lucie lc +Santa Lucía lc +סנטה לוסיה lc +Santa Lucia lc +セントルキア lc +세인트 루시아 lc +ເຊັນລູເຊີຍ lc +Šv Liucija lc +Sv. Lūcija lc +St. Luċija lc +Santa Lúcia lc +Santa Lúcia lc +Sf. Lucia lc +о. Св. Люсии lc +Sv. Júlia lc +Sv. Lucija lc +I-St. Lucia lc +¦ºýð æº¢Â¡ lc +เซนต์ลูเซีย lc +Санта Лучія lc +圣路西亚 lc +聖露西亞 lc +Liechtenstein li +Ліхтэнштэйн li +Лихтенщайн li +Lihtenštajn li +Liechtestein li +ຟ້າແມບ li +列支敦士登 li +Sri Lanka lk +Шры-Ланка lk +Шри Ланка lk +Šri Lanka lk +ເຊີເບີຍ lk +Šri Lanka lk +斯里兰卡 lk +Liberia lr +Лібэрыя lr +Либеря lr +Liberija lr +Libéria lr +ລິຊາ lr +Libéria lr +Lýbia lr +Liberija lr +利比里亚 lr +Lesotho ls +Лесота ls +Лесото ls +Lesoto ls +Lesoto ls +ທົດສອບ ls +Lesoto ls +莱索托 ls +Lithuania lt +Lithuanië lt +ليتوانيا lt +Litvaniya lt +Літва lt +Литва lt +Litvanija lt +Lituània lt +Litva lt +Litauen lt +Litauen lt +Λιθουανία lt +Litovio lt +Lituania lt +Leedu lt +Lituania lt +لیتوانی lt +Liettua lt +Lituanie lt +ליטא lt +Litva lt +Litvánia lt +Litháenska lt +Lituania lt +リトアニア lt +리 투아니아 lt +ລິທົ່ວເນີຍ lt +Lietuva lt +Lietuva lt +Litwanja lt +Litauen lt +Litouwen lt +Litauen lt +Litwa lt +Lituânia lt +Lituânia lt +Lituania lt +Литва lt +Litva lt +Litva lt +Litvanija lt +I-Lithuania lt +Litauen lt +Ä¢òЧÅɢ¡ lt +ลิธัวเนีย lt +Litvanya lt +Литва lt +立陶宛 lt +立陶宛 lt +Luxembourg lu +Luxenburg lu +لوكسمبورغ lu +Lüksemburq lu +Люксэмбург lu +Люксембург lu +Luksemburg lu +Luxemburg lu +Lucembursko lu +Luxemburg lu +Λουξεμβούργο lu +Luksemburgo lu +Luxemburgo lu +Luksemburg lu +Luxemburg lu +لوگزامبورگ lu +Luxemburg lu +Luksemborg lu +לוקסמבורג lu +Luksemburg lu +Luxemburg lu +Lúxemborg lu +Lussemburgo lu +ルクセンブルグ lu +룩셈부르크 lu +ລັກແຊມເບີກ lu +Liuksemburgas lu +Luksemburga lu +Lussemburgu lu +Luxemburg lu +Luksemburg lu +Luxemburgo lu +Luxemburgo lu +Luxemburg lu +Люксембург lu +Luxemburg lu +Luksemburg lu +Luksemburg lu +I-Luxembourg lu +Luxemburg lu +Äìºõ§À¡÷ì lu +ลักเซมเบอร์ก lu +Lüksemburg lu +Люксембург lu +Lucsimbork lu +卢森堡 lu +盧森堡 lu +Latvia lv +لاتفيا lv +Latviya lv +Латвія lv +Латвия lv +Latvija lv +Lotyšsko lv +Letland lv +Lettland lv +Λιθουανία lv +Latvio lv +Letonia lv +Läti lv +لاتویا lv +Lettonie lv +לטביה lv +Latvija lv +Lettország lv +Léttland lv +Lettonia lv +ラトビア lv +라트비아 lv +ລັດເວີຍ lv +Latvija lv +Latvija lv +Latvja lv +Letland lv +Łotwa lv +Letónia lv +Латвия lv +Lotyšsko lv +Latvija lv +Latvija lv +I-Latvia lv +Lettland lv +ÄðŢ¡ lv +ลัธเวีย lv +Litvanya lv +Латвія lv +Lativia lv +拉脱维亚 lv +拉脫維亞 lv +Libya ly +Libië ly +ليبيا ly +Лівія ly +Либия ly +Libija ly +Líbia ly +Lýbie ly +Libyen ly +Libyen ly +Λιβύη ly +Libia ly +Liibüa ly +Libia ly +لیبی ly +Lybie ly +לוב ly +Líbia ly +Libia ly +リビア ly +ລິຊາ ly +Libija ly +Libië ly +Libia ly +Líbia ly +Líbia ly +Ливия ly +Lýbia ly +Libija ly +I-Libya ly +Libyen ly +Ä¢À¢Â¡ ly +Лівія ly +利比亚 ly +利比亞 ly +Morocco ma +Morokko ma +المغرب ma +Марока ma +Мароко ma +Maroko ma +Marroc ma +Maroko ma +Marokko ma +Marokko ma +Μαρόκο ma +Moroko ma +Marruecos ma +Maroko ma +Maroko ma +مراکش ma +Marokko ma +Marokko ma +Maroc ma +מרוקו ma +Maroko ma +Marokkó ma +Marocco ma +モロッコ ma +모로코 ma +ເມົາລິ ma +Marokas ma +Marokk ma +Marokko ma +Marokko ma +Marokko ma +Maroko ma +Marrocos ma +Marrocos ma +Maroc ma +Марокко ma +Maroko ma +Maroko ma +I-Morocco ma +Marocko ma +§Á¡Ã¡§¸¡ ma +Марокко ma +Marok ma +摩洛哥 ma +摩洛哥 ma +Monaco mc +Манака mc +Монако mc +Monako mc +Mónaco mc +ເມົາລິ mc +Mônaco mc +Monako mc +Monako mc +摩纳哥 mc +Moldova md +Малдова md +Молдова md +Moldavia md +Moldavia md +ສະໂລວັກ md +Moldávsko md +Moldavien md +摩尔多瓦 md +Madagascar mg +Мадагаскар mg +Мадагаскар mg +Madagaskar mg +Madagaszkár mg +ຄາສະບາລ - K mg +Madagaskar mg +Madagaskar mg +Madagaskar mg +马达加斯加 mg +Marshall Islands mh +Маршаллавы астравы mh +Маршалови Острови mh +Maršalova ostrva mh +Marshall-øerne mh +Islas Marshall mh +Marshall Irlak mh +Marshall-szigetek mh +ລາດສະອານາຈັກໄທຍ mh +Ilhas Marshall mh +Maršálove ostrovy mh +Marshallovi otoki mh +Marshallöarna mh +马绍尔群岛 mh +Macedonia mk +Makedoniese mk +مقدونيا mk +Makedonya mk +Македонія mk +Македония mk +Makedonia mk +Makedonija mk +Macedònia mk +Makedonie mk +Makedonien mk +Makedonien mk +Μακεδονία mk +Macedonio mk +Makedoonia mk +Mazedonia mk +مقدونیه mk +Makedonia mk +Macédoine mk +מקדוניה mk +Makedonija mk +Macedónia mk +Masedonia mk +MakedónÃa mk +マケドニア語 mk +마케도니아 mk +ມາເຊໂດເນີຍ mk +Makedonija mk +Maķedonija mk +Maċedonja mk +Makedonia mk +Macedonië mk +Makedonia mk +Macedònian mk +Macedónia mk +Macedônia mk +Македония mk +Macedónsky mk +Makedonija mk +Makedonija mk +I-Macedonia mk +Makedonien mk +Á¡º¢§¼¡É¢Â¡ mk +มาเซโดเนีย mk +Makedonya mk +Македонія mk +Masedonia mk +马其顿 mk +馬其頓 mk +Mali ml +Малі ml +Мали ml +ຈົດຫມາຍ ml +马里 ml +Myanmar mm +М'янма mm +Майнмар mm +Mjanmar mm +Burma mm +Birmania mm +ຕົວຮງກພີື້ນທີ່ທຳງານ - K mm +Mjanmar mm +缅甸 mm +Mongolia mn +Манголія mn +Монголия mn +Mongolija mn +Mongoliet mn +Mongólia mn +ລອກອິນ mn +Mongólia mn +Mongolsko mn +Mongolija mn +Mongoliet mn +蒙古 mn +Macau mo +Макао mo +Makau mo +Macao mo +Makaó mo +ມອລຕາ mo +Makao mo +Macao mo +澳门 mo +Martinique mq +Мартиника mq +Martinik mq +Martinica mq +ເມົາລິ mq +Martinik mq +马提尼克岛 mq +Mauritania mr +Маўрытанія mr +Мавритания mr +Mauritanija mr +Mauretanien mr +Mauritánia mr +ລິທົວເນີຍ mr +Mauritânia mr +Mavretanija mr +Mauretanien mr +毛里塔尼亚 mr +Montserrat ms +Монсерат ms +Monsera ms +ຈໍພາບ ms +蒙特塞拉特岛 ms +Malta mt +مالطة mt +Мальта mt +Малта mt +Μάλτα mt +Malto mt +مالت mt +Malte mt +מלטה mt +Málta mt +マルタ mt +왈타 mt +ມອລຕາ mt +Мальта mt +I-Malta mt +Á¡ø¼¡ mt +มอลตา mt +Мальта mt +Male mt +马耳他 mt +馬爾他 mt +Mauritius mu +Маўрыцы mu +Маурици mu +Mauricijus mu +Mauricio mu +ພາທິຊັ້ນ mu +Maurícius mu +Mavricij mu +毛里求斯 mu +Maldives mv +Мальдывы mv +Малдиви mv +Maldivi mv +Maldiverne mv +Maldivas mv +Maldív-szigetek mv +ມັລດິສ mv +Maldivas mv +Maldiv mv +Maldiverna mv +马尔代夫 mv +Malawi mw +Малаві mw +Малави mw +Malavi mw +ມອລຕາ mw +马拉维 mw +Mexico mx +Meksiko mx +المكسيك mx +Meksika mx +Мэксыка mx +Мексико mx +Mec'hiko mx +Meksiko mx +Mèxic mx +Mexiko mx +Mexiko mx +Μεξικό mx +Meksikujo mx +México mx +Mehhiko mx +Mexiko mx +مکزیک mx +Meksiko mx +Meksiko mx +Mexique mx +México mx +מקסיקו mx +Meksiko mx +Mexikó mx +Meksiko mx +MexÃkó mx +Messico mx +メキシコ mx +멕시코 mx +ເມັກຊີໂກ mx +Meksika mx +Meksika mx +Messiku mx +Mèxic mx +Meksyk mx +México mx +México mx +Mexic mx +Мексика mx +Mexiko mx +Mehika mx +Meksiko mx +I-Mexico mx +¦Á캢§¸¡ mx +เม็กซิโก mx +Meksika mx +Мексика mx +Mê hi cô mx +Mecsike mx +墨西哥 mx +墨西哥 mx +Malaysia my +Малайзыя my +Малайзия my +Malezija my +Malasia my +Malasia my +Malajzia my +ມອລຕາ my +Malásia my +Malajzia my +Malezija my +马来西亚 my +Mozambique mz +Мазамбік mz +Мозамбик mz +Mozambik mz +Mozambik mz +ຫນ່ວຍຄວາມຈຳ mz +Moçambique mz +Mozambik mz +Mozambik mz +Moçambique mz +莫桑比克 mz +Namibia na +Намібія na +Намибия na +Namibija na +Namíbia na +ຈາໄມກາ na +Namíbia na +Namíbia na +Namibija na +纳米比亚 na +New Caledonia nc +Нова Каледония nc +Nova Kaledonija nc +Ny Caledonien nc +Nueva Caledonia nc +Kaledonia Berria nc +Új-Kaledónia nc +ມາເຊໂດເນີຍ nc +Nova Caledônia nc +Nová Kaledónia nc +Nova Kaledonija nc +Nya Caledonien nc +新喀里多尼亚 nc +Niger ne +Нігер ne +Нигер ne +ຕົວຮງກພື້ນທີ່ທຳງານ ne +Nigéria ne +Nigéria ne +尼日尔 ne +Norfolk Island nf +Остров Норфолк nf +Norfolk ostrvo nf +Norfolk-øerne (Australien) nf +Isla Norfolk nf +Norfok Irla nf +Norfolk-szigetek nf +ໂປແລນ nf +Ilhas Norfolk nf +Ostrov Norfolk nf +Otok Norfolk nf +Norfolkön nf +诺福克岛 nf +Nigeria ng +Нігерыя ng +Нигерия ng +Nigerija ng +Nigéria ng +ບັນແກເລີຍ ng +Nigéria ng +Nigéria ng +Nigerija ng +尼日利亚 ng +Nicaragua ni +Nikaragua ni +نيكاراغوا ni +Нікарагуа ni +Никарагуа ni +Nikaragva ni +Nikaragua ni +Νικαράγουα ni +Nikaraagua ni +نیکاراگویه ni +Nikaragua ni +Nikaragua ni +ניקרגווה ni +ニカラグア ni +니카라과 ni +ປາລາກກວຍ ni +Nikaragua ni +Nikaragwa ni +Nikaragua ni +Nicarágua ni +Nicarágua ni +Никарагуа ni +Nikaragua ni +Nikaragva ni +I-Nicaragua ni +¿¢¸Ã¡Ì§Å ni +Nikaragua ni +Нікарагуа ni +尼加拉瓜 ni +尼加拉瓜 ni +Netherlands nl +Nederland nl +هولندا nl +Hollandiya nl +Галяндыя nl +Холандия nl +Izelvroioù nl +Nizozemska nl +Holanda nl +Nizozemí nl +Holland nl +Niederlande nl +Κάτω Χώρες nl +Nederlando nl +Países Bajos nl +Holland nl +Holanda nl +هلند nl +Alankomaat nl +Háland nl +Pays bas nl +Países Baixos nl +הולנד nl +Nizozemska nl +Hollandia nl +Belanda nl +Holland nl +Paesi Bassi nl +オランダ nl +네덜란드 nl +ເນເທີແລນ์ nl +Olandija nl +Nīderlande nl +Nederland nl +Nederland nl +Nederland nl +Holanda nl +Holandia nl +Países Baixos nl +Holanda nl +Olanda nl +Нидерланды nl +Holandsko nl +Nizozemska nl +Holandija nl +I-Netherlands nl +Nederländerna nl +¦¿¾÷Ä¡óÐ nl +เนเธอร์แลนด์ nl +Hollanda nl +Голландія nl +Hà Lan nl +荷兰 nl +荷蘭 nl +Norway no +Noorweë no +النرويج no +Norveç no +Нарвэгія no +Норвегия no +Norvegia no +Norveška no +Noruega no +Norsko no +Norge no +Norwegen no +Νορβηγία no +Norvegio no +Noruega no +Norra no +Norvegia no +نروژ no +Norja no +Norra no +Norvège no +Noruega no +נורבגיה no +Norveška no +Norvégia no +Norwegia no +Noregur no +Norvegia no +ノルウェー no +노르웨이 no +ນໍເວ no +Norvegija no +Norvēģija no +Norveġja no +Norge no +Noorwegen no +Noreg no +Noruega no +Norwegia no +Noruega no +Noruega no +Norvegia no +Норвегия no +Nórsko no +Norveška no +Norveška no +I-Norway no +Norge no +¿¡÷§Å no +นอร์เวย์ no +Norveç no +Норвегія no +Na uy no +挪威 no +挪威 no +Nepal np +Нэпал np +Непал np +Nepál np +ເວນດາ np +尼泊尔 np +Nauru nr +Науру nr +Науру nr +Naurú nr +ປາລາກກວຍ nr +瑙鲁 nr +Niue nu +Ниуе nu +ເນ໊ຕ nu +纽埃岛 nu +New Zealand nz +Nuwe Seeland nz +نيوزيلاندا nz +Yeni Zellandiya nz +Новая Зэляндыя nz +Нова Зеландия nz +Zeland nevez nz +Novi Zeland nz +Nova Zelanda nz +Nový Zéland nz +Neuseeland nz +Νέα Ζηλανδία nz +Novzelando nz +Nueva Zelanda nz +Uus-Meremaa nz +Zelanda Berria nz +زلاندنو nz +Uusi-Seelanti nz +Nýsæland nz +Nouvelle Zélande nz +Nova Celandia nz +ניו זילנד nz +Novi Zeland nz +Új-Zéland nz +Selandia Baru nz +Nýja Sjáland nz +Nuova Zelanda nz +ニュージーランド nz +뉴질랜드 nz +ນີວຊີແລນ nz +Naujoji Zelandija nz +JaunZēlande nz +Nieuw Zeeland nz +Navera Zelanda nz +Nowa Zelandia nz +Nova Zelândia nz +Nova Zelândia nz +Noua Zeelandă nz +Новая Зеландия nz +Nový Zéland nz +Nova Zelandija nz +Novi Zeland nz +I-New Zealand nz +Nya Zeeland nz +¿¢äº¢Ä¡óÐ nz +นิวซีแลนด์ nz +Yeni Zelanda nz +Нова Зеландія nz +Nouve Zelande nz +新西兰 nz +紐西蘭 nz +Oman om +عُمان om +Аман om +Оман om +Omán om +Ομάν om +Omano om +Omán om +Omaan om +عمان om +עומן om +Omán om +オマーン om +오만 om +ເຍີຍລະມັນ om +Omanas om +Omã om +Оман om +Omán om +I-Oman om +µÁý om +Umman om +Оман om + Oman om +阿曼 om +阿曼 om +Panama pa +بنما pa +Панама pa +Панама pa +Panamà pa +Παναμάς pa +Panamo pa +Panamá pa +پاناما pa +Panamá pa +פנמה pa +パナマ pa +파나마 pa +ປານາມາ pa +Panamá pa +Panamá pa +Панама pa +I-Panama pa +ÀÉ¡Á¡ pa +ปานามา pa +Панама pa +巴拿马 pa +巴拿馬 pa +Peru pe +البيرو pe +Пэру pe +Перу pe +Perou pe +Perú pe +Περού pe +Peruo pe +Perú pe +Peruu pe +پرو pe +Pérou pe +Perú pe +פרו pe +Perú pe +Perù pe +ペルー pe +페루 pe +ເປລູ pe +Perū pe +Pero pe +Perú pe +Перу pe +I-Peru pe +¦ÀÕ pe +เปรู pe +Перу pe +Perou pe +秘鲁 pe +秘魯 pe +French Polynesia pf +Француская Палінэзія pf +Френска Полинезия pf +Francuska Polinezija pf +Fransk Polynesien pf +Polinesia francesa pf +Polinesia Frantziarra pf +Francia-Polinézia pf +ຝຣັ່ງເສດ pf +Polinésia Francesa pf +Francúzska Polynézia pf +Francoska Polinezija pf +Franska Polynesien pf +法属波利尼西亚 pf +Papua New Guinea pg +Папуа–Новая Гвінэя pg +Папуа и Нова Гвинея pg +Papua Nova Gvineja pg +Papua Nueva Guinea pg +Papua Ginea Berria pg +Pápua Új-Guinea pg +ເທົາອ່ອນ pg +Nova Guiné Papua pg +Papua Nová Guinea pg +Papua Nova Gvineja pg +Papua Nya Guinea pg +巴布亚新几内亚 pg +Philippines ph +Філіпіны ph +Филипини ph +Filipini ph +Filippinerne ph +Filipinas ph +Filipinak ph +Fülöp-szigetek ph +ອາລະປະໂຫຍດ ph +Filipinas ph +Filipíny ph +Filipini ph +Filippinerna ph +菲律宾 ph +Pakistan pk +Пакістан pk +Пакистан pk +Pakisztán pk +ລງບ pk +Paquistão pk +巴基斯坦 pk +Poland pl +Poolland pl +بولندا pl +Polşa pl +Польшча pl +Полша pl +Polonia pl +Poljska pl +Polònia pl +Polsko pl +Polen pl +Polen pl +Πολωνία pl +Pollando pl +Polonia pl +Poola pl +Polonia pl +لهستان pl +Puola pl +Pólland pl +Pologne pl +Polonia pl +פולין pl +Poljska pl +Lengyelország pl +Polandia pl +Pólland pl +Polonia pl +ポーランド pl +폴란드 pl +ໂປແລນ pl +Lenkija pl +Polija pl +Polonja pl +Polen pl +Polen pl +Polen pl +Polònia pl +Polska pl +Polónia pl +Polônia pl +Polonia pl +Польша pl +Poľsko pl +Poljska pl +Poljska pl +I-Poland pl +Polen pl +§À¡Ä¡óÐ pl +โปแลนด์ pl +Polonya pl +Польща pl +Pholandi pl +Ba Lan pl +Pologne pl +波兰 pl +波蘭 pl +Saint Pierre and Miquelon pm +Sveti Pjer i Migelon pm +Saint Pierre og Miquelon pm +Saint Pierre y Miquelon pm +Saint Pierre eta Miquelon pm +Saint Pierre és Miquelon pm +Saint Pierre e Miquelon pm +Saint Pierre a Miquelon pm +Sveti Pierre in Miquelon pm +Saint Pierre och Miquelon pm +圣皮埃尔和密克隆岛 pm +Pitcairn pn +Pitkern pn +ລງບ pn +Puerto Rico pr +Пуерто Рико pr +Portoriko pr +ໂປຣໂຕຄອນ pr +Porto Rico pr +Portoriko pr +波多尼各 pr +Palestinian Territory ps +Palesteinse Gebied ps +السلطة الفلسطينية ps +Палестынская тэрыторыя ps +Палестина ps +Palestinska teritorija ps +Territori Palestí ps +Palestinské území ps +Palæstinensiske selvstyreområder ps +Palästinensisches Gebiet ps +Παλαιστίνη ps +Palestinaj teritorioj ps +Territorio palestino ps +Palestiina territoorium ps +Palestina ps +فلسطین ps +Palestiinalaisalue ps +Palestinensiska økið ps +Territoire palestinien ps +השטחים הפלסטיניים ps +Palestinski teritorij ps +Palesztin területek ps +Territori palestinesi ps +パレスチナ自治区 ps +팔레스타인 자치구 ps +ການພິມຜິດພາດ ps +Palestinos teritorija ps +Palestina ps +Palestinske territorier ps +Palestijns territorium ps +Palestinske territorium ps +Bohwa bja Palestina ps +Palestyna ps +Território Palestiniano ps +Território Palestino ps +Teritoriul Palestinian ps +Палестинские территории ps +Palestínske územia ps +Palestinski teritorij ps +I-Palestinian Territory ps +Palestina ps +À¡Äо£É ¬¨½Âõ ps +Filistin Bölgesi ps +Палестинська територія ps +Mukano wa maphalesitina ps +Palestene ps +Umhlaba wePalestina ps +巴勒斯坦地区 ps +巴勒斯坦領地 ps +Indawo yama-Phalesitina ps +Portugal pt +البرتغال pt +Portuqaliya pt +Партугалія pt +Португалия pt +Portugalsko pt +Πορτογαλία pt +Portugalo pt +پرتغال pt +Portugali pt +פורטוגל pt +Portugália pt +Portúgal pt +Portogallo pt +ポルトガル pt +포르투갈 pt +ໂປຣຕຸເກສ pt +Portugalija pt +Portugāle pt +Portugall pt +Portugalia pt +Portugalia pt +Португалия pt +Portugalsko pt +Portugalska pt +I-Portugal pt +§À¡÷òиø pt +โปรตุเกส pt +Portekiz pt +Португалія pt +BềEĐào Nha pt +葡萄牙 pt +葡萄牙 pt +Palau pw +Палау pw +Палау pw +ມອລຕາ pw +帕劳群岛 pw +Paraguay py +Paraguaai py +باراغواي py +Paraqvay py +Парагвай py +Парагвай py +Paragvaj py +Paraguai py +Παραγουάη py +Paragvajo py +Paraguai py +پاراگویه py +Paraguai py +פרגואי py +Paragvaj py +パラグアイ py +파라과이 py +ປາລາກກວຍ py +Paragvajus py +Paragvaja py +Paragwaj py +Paraguai py +Paragwaj py +Paraguai py +Paraguai py +Paraguai py +Парагвай py +Portugalsko py +Paragvaj py +Paragvaj py +I-Paraguay py +Àá̧Špy +ปารากวัย py +Парагвай py +Paragway py +巴拉圭 py +巴拉圭 py +Qatar qa +قطر qa +Катар qa +Катар qa +Katar qa +Katar qa +Katar qa +Κατάρ qa +Kataro qa +Katar qa +قطر qa +Katar qa +קטר qa +Katar qa +Katar qa +カタール qa +카타르 qa +ມອລຕາ qa +Katar qa +Катар qa +Katar qa +Katar qa +I-Qatar qa +¸¾¡÷ qa +Katar qa +Катар qa +卡塔尔 qa +卡達 qa +Romania ro +Romenië ro +رومانيا ro +Rumıniya ro +Румынія ro +Румъния ro +Roumania ro +Rumunija ro +Rumunsko ro +Rumænien ro +Rumänien ro +Ρουμανία ro +Rumanio ro +Rumanía ro +Rumeenia ro +Errumania ro +رومانی ro +Rumenia ro +Roumanie ro +Romanía ro +רומניה ro +Rumunjska ro +Románia ro +Rumania ro +RúmenÃa ro +ルーマニア ro +루마니아 ro +ໂລມາເນີຍ ro +Rumunija ro +Rumānija ro +Rumanija ro +Roemenië ro +Rumunia ro +Roménia ro +Romênia ro +Румыния ro +Rumunsko ro +Romunija ro +Rumunija ro +I-Romania ro +Rumänien ro +Õ§Áɢ¡ ro +โรมาเนีย ro +Romanya ro +Румунія ro +Ru ma ni ro +Roumaneye ro +罗马尼亚 ro +羅馬尼亞 ro +Russia ru +Rusland ru +روسيا ru +Rusiya ru +Расея ru +Русия ru +Rusia ru +Rusija ru +Rússia ru +Rusko ru +Rusland ru +Russland ru +Ρωσία ru +Ruslando ru +Rusia ru +Venemaa ru +Errusia ru +روسیه ru +Venäjä ru +Russland ru +Russie ru +Rusia ru +רוסיה ru +Rusija ru +Oroszország ru +Rusia ru +Rússland ru +ロシア ru +러시아 ru +ລັດເຊີຍ ru +Rusija ru +Krievija ru +Russja ru +Russland ru +Rusland ru +Russland ru +Rosja ru +Rússia ru +Rússia ru +Rusia ru +Россия ru +Rusko ru +Rusija ru +Rusija ru +I-Russia ru +Ryssland ru +ú¢Â¡ ru +รัสเซีย ru +Rusya ru +Росія ru +Rashia ru +Nga ru +Russeye ru +Rashiya ru +俄罗斯 ru +俄羅斯 ru +Rwanda rw +Руанда rw +Руанда rw +Ruanda rw +Ruanda rw +Ruanda rw +ແພນດ້າ rw +Ruanda rw +Ruanda rw +卢旺达 rw +Saudi Arabia sa +Saudi Arabië sa +السعودية sa +Саудаўская Арабія sa +Саудитска Арабия sa +Saudijska Arabija sa +Aràbia Saudí sa +Saúdská Arábie sa +Saudi Arabien sa +Saudi-Arabien sa +Σαουδική Αραβία sa +Saŭdi-Arabio sa +Arabia Saudí sa +Saudi Araabia sa +عربستان سعودی sa +Saudi-Arabia sa +Arabie Saoudite sa +ערב הסעודית sa +Saudijska Arabija sa +Szaúd-Arábia sa +Arabia saudita sa +サウジアラビア sa +사우디 아라비아 sa +ອາລະບິກ sa +Saudi Arabija sa +Għarabja Sawdita sa +Saudi-Arabia sa +Saudi-Arabië sa +Saudi-Arabia sa +Arabia Saudyjska sa +Arábia Saudita sa +Arábia Saudita sa +Arabia Saudită sa +Саудовская Аравия sa +Saudská arábia sa +Saudova Arabija sa +I-Saudi Arabia sa +Saudiarabien sa +º×¾¢ «§ÃÀ¢Â¡ sa +Suudi Arabistan sa +Саудівська Аравія sa +沙特阿拉伯 sa +沙烏地阿拉伯 sa +Solomon Islands sb +Саламонавы астравы sb +Соломонови Острови sb +Solomonska ostrva sb +Salomon-øerne sb +Islas Salomón sb +Solomon Irlak sb +Salamon-szigetek sb +ສະໂລວະເນີຍ sb +Ilhas Salomão sb +Šalamúnove ostrovy sb +Solomonovi otoki sb +Salomonöarna sb +所罗门群岛 sb +Seychelles sc +Сэйшэлы sc +Сейшелски острови sc +Sejšeli sc +Seychellerne sc +ເຊລ sc +Sejšeli sc +Seychellerna sc +塞舌尔 sc +Sudan sd +السودان sd +Судан sd +Судан sd +Sudán sd +Σουδάν sd +Sudano sd +Sudán sd +Sudaan sd +سودان sd +Sudania sd +Soudan sd +סודן sd +Szudán sd +Súdan sd +スーダン sd +수단 sd +ຊູດານ sd +Sudanas sd +Sudāna sd +Sudão sd +Sudão sd +Судан sd +Sudán sd +I-Sudan sd +ݼ¡ý sd +ซูดาน sd +Судан sd +Sudani sd +Soudan sd +苏丹 sd +蘇丹 sd +Sweden se +Swede se +السويد se +İsveç se +Швэцыя se +Швеция se +Sveden se +Švedska se +Suècia se +Švédsko se +Sverige se +Schweden se +Σουηδία se +Svedio se +Suecia se +Rootsi se +Suedia se +سوید se +Ruotsi se +Svøriki se +Suède se +Suecia se +שבדיה se +Švedska se +Svédország se +Swedia se +SvÃþjóð se +Svezia se +スウェーデン se +스웨덴 se +ສະວີເດນ se +Švedija se +Zviedrija se +Svezja se +Sverige se +Zweden se +Sverige se +Suècia se +Szwecja se +Suécia se +Suécia se +Suedia se +Швеция se +Švédsko se +Švedska se +Švedska se +I-Sweden se +Sverige se +ÍÅ£¼ý se +สวีเดน se +İsveç se +Швеція se +Swidene se +Thuỵ Điển se +瑞典 se +瑞典 se +Singapore sg +Сынгапур sg +Сингапур sg +Singapur sg +Singapur sg +Szingapúr sg +ໂຊນາ sg +Singapura sg +Singapur sg +Singapur sg +新加坡 sg +Saint Helena sh +Свети Елена sh +Sveta Helena sh +St. Helena sh +Santa Helena sh +Szent Heléna sh +ຫົວເລື່ອງ sh +Santa Helena sh +Svätá Helena sh +Sveta Helena sh +圣赫勒拿岛 sh +Slovenia si +Slovenië si +سلوفينيا si +Sloveniya si +Славенія si +Словения si +Slovenija si +Eslovenia si +Slovinsko si +Slovenien si +Slowenien si +Σλοβενία si +Slovenio si +Eslovenia si +Sloveenia si +Eslovenia si +اسلوانی si +Slovénie si +Eslovenia si +סלובניה si +Slovenija si +Szlovénia si +SlóvenÃa si +スロベニア si +슬로베니아 si +ສະໂລວະເນີຍ si +Slovėnija si +Slovēnija si +Slovenja si +Slovenië si +Eslovenia si +Słowenia si +Eslovénia si +Eslovênia si +Словения si +Slovinsko si +Slovenija si +Slovenija si +I-Slovenia si +Slovenien si +ͧġŢɢ¡ si +สโลเวเนีย si +Slovenya si +Словенія si +斯洛文尼亚 si +斯洛維尼亞 si +Slovakia sk +Slovakië sk +سلوفاكيا sk +Slovakiya sk +Славакія sk +Словакия sk +Slovačka sk +Eslovaquia sk +Slovensko sk +Slovakiet sk +Slowakien sk +Σλοβακία sk +Slovakujo sk +Eslovaquia sk +Slovakkia sk +Eslovakia sk +اسلواکی sk +Slovaquie sk +סלובקיה sk +Slovačka sk +Szlovákia sk +SlóvakÃa sk +Slovacchia sk +スロバキア sk +슬로바키아 sk +ສະໂລວັກ sk +Slovakija sk +Slovākija sk +Slovakja sk +Slovakije sk +Słowacja sk +Eslováquia sk +Eslováquia sk +Slovacia sk +Словакия sk +Slovensko sk +Slovaška sk +I-Slovakia sk +Slovakien sk +ͧġš츢 sk +สโลวัค sk +Slovakya sk +Словакія sk +斯洛伐克 sk +斯洛伐克 sk +San Marino sm +Сан-Марына sm +Сан Марино sm +ໂຊນາ sm +圣马力诺 sm +Senegal sn +Сэнэгал sn +Сенегал sn +Szenegál sn +ທົ່ວໄປ sn +塞内加尔 sn +Somalia so +Somalië so +صومال so +Самалі so +Сомалия so +Somalija so +Somàlia so +Somálsko so +Σομαλία so +Somalio so +Somaalia so +سومالی so +Somalie so +סומליה so +Somalija so +Szomália so +ソマリア so +소말리아 so +ໂລມາເນີຍ so +Somalis so +Somalija so +Somalie so +Somália so +Somália so +Сомали so +Somálsko so +Somalija so +I-Somalia so +§º¡Á¡Ä¢Â¡ so +Somali so +Сомалі so +Somaleye so +索马里 so +索馬利亞 so +Suriname sr +Сурынам sr +Суринам sr +Surinam sr +ເຊີເບີຍ sr +Surinam sr +Surinam sr +Surinam sr +Sao Tome and Principe st +Сан Томе и Приницпе st +Sao Tome i Principe st +Sao Tomé og Principe st +Sao Tome y Príncipe st +Sao Tome eta Principe st +Sao Tome és Principe st +ບໍລິການ st +São Tome e Príncipe st +Sao Tome a Principe st +Sao Tome in Principe st +São Tomé och Príncipe st +El Salvador sv +السلفادور sv +Сальвадор sv +Ел Салвадор sv +Salvador sv +Salvador sv +Ελ Σαλβαντόρ sv +Elsalvadoro sv +Salvador sv +السالوادور sv +Salvador sv +O Salvador sv +אל סלבדור sv +Salvador sv +エルサルバドル sv +엘살바도르 sv +ເອລຊັນວາດດໍ sv +Salvadoras sv +Salvadora sv +Salwador sv +Salvador sv +Сальвадор sv +Salvádor sv +Salvador sv +I-El Salvador sv +±ø º¡øÅ§¼¡÷ sv +เอลซัลวาดอร์ sv +Ель-Сальвадор sv +萨尔瓦多 sv +薩爾瓦多 sv +Syria sy +Sirië sy +سوريا sy +Сырыя sy +Сирия sy +Sirija sy +Síria sy +Sýrie sy +Syrien sy +Syrien sy +Συρία sy +Sirio sy +Siria sy +Süüria sy +Siria sy +سوریه sy +Syyria sy +Syrie sy +סוריה sy +Sirija sy +Szíria sy +Siria sy +シリア sy +시리아 sy +ເຊີເບີຍ sy +Sirija sy +Siria sy +Syrië sy +Síria sy +Síria sy +Siria sy +Сирия sy +Sýria sy +Sirija sy +I-Syria sy +Syrien sy +º¢Ã¢Â¡ sy +Suriye sy +Сирія sy +叙利亚 sy +敘利亞 sy +Swaziland sz +Свазылэнд sz +Свазиленд sz +Svazilend sz +Swazilandia sz +Swazilandia sz +Szváziföld sz +ລາດສະນາຈັກໄທຍ sz +Suécia sz +Swazijsko sz +Svazi sz +斯威士兰 sz +Turks and Caicos Islands tc +Turks i Kaikos ostrva tc +Turks- og Caicosøerne tc +Islas Turcos y Caicos tc +Turks eta Caicos Irlak tc +Turks- és Caicos-szigetek tc +Ilhas Caicos e Turca tc +Turks a Caicos ostrovy tc +Otoka Turks in Caicos tc +Turks- och Caicosöarna tc +特克斯和凯科斯群岛 tc +Chad td +Чад td +Чад td +Čad td +Tchad td +Txad td +Csád td +ເກມໄພ່ td +Čad td +Čad td +Tchad td +乍得 td +Togo tg +Тога tg +Того tg +ຂອງເລ່ນສະນຸກ tg +多哥 tg +Thailand th +تايلاند th +Tayland th +Тайлянд th +Тайланд th +Tajland th +Tailàndia th +Thajsko th +Ταϊλάνδη th +Tajlando th +Tailandia th +Tai th +Thailandia th +تایلند th +Thaimaa th +Tailand th +Thaïlande th +Tailandia th +תאילנד th +Tajland th +Thaiföld th +Tæland th +Tailandia th +タイ th +태국 (타이) th +ລາດສະນາຈັກໄທຍ th +Tailandas th +Taivāna th +Tajlandja th +Tailandia th +Tajlandia th +Tailândia th +Tailândia th +Tailanda th +Таиланд th +Thajsko th +Tajska th +Tajland th +I-Thailand th +¾¡öÄ¡óÐ th +ราชอาณาจักรไทย th +Tayland th +Таїланд th +Thái Lan th +Taylande th +泰国 th +泰國 th +Tajikistan tj +Таджыкістан tj +Таджикистан tj +Tadžikistan tj +Tajikistán tj +Tadzsikisztán tj +ໃຕ້ຫວັນ tj +Tajiquistão tj +Tadžikistan tj +Tadžikistan tj +Tadzjikistan tj +塔吉克斯坦 tj +Tokelau tk +Токелао tk +ເບລາລັສ tk +Turkmenistan tm +Туркмэністан tm +Туркменистан tm +Turkmenistán tm +Türkmenisztán tm +ຕຸລະກີ tm +Turquia tm +土库曼斯坦 tm +Tunisia tn +Tunisië tn +تونس tn +Туніс tn +Тунис tn +Tunis tn +Tuníssia tn +Tunisko tn +Tunesien tn +Tunesien tn +Τυνησία tn +Tunisio tn +Túnez tn +Tuneesia tn +تونس tn +Tunesia tn +Tunisie tn +תוניסיה tn +Tunis tn +Tunézia tn +チュニジア tn +튀니지 tn +ລັດເຊີຍ tn +Tunisas tn +Tuneżija tn +Tunisie tn +Tunezja tn +Tunísia tn +Tunísia tn +Тунис tn +Tunisko tn +Tunizija tn +I-Tunisia tn +Tunisien tn +ÐÉ¢º¢Â¡ tn +Tunus tn +Туніс tn +突尼斯 tn +突尼西亞 tn +Tonga to +Тонга to +Тонга to +ໂຊນາ to +汤加 to +East Timor tp +Источен Тимур tp +Istočni Timor tp +Østtimor tp +Timor oriental tp +Ekialdeko Timor tp +Kelet-Timor tp +ວັນແລະເວລາ tp +Timor Leste tp +Východný Timor tp +Vzhodni Timor tp +Östtimor tp +东帝汶 tp +Turkey tr +Turkeye tr +تركيا tr +Türkiyə tr +Турцыя tr +Турция tr +Turkia tr +Turska tr +Turquia tr +Turecko tr +Tyrkiet tr +Türkei tr +Τουρκία tr +Turkujo tr +Turquía tr +Türgi tr +Turkia tr +ترکیه tr +Turkki tr +Turkaland tr +Turquie tr +Turquía tr +טורקיה tr +Turska tr +Törökország tr +Turki tr +Tyrkland tr +Turchia tr +トルコ tr +터키 tr +ຕຸລະກີ tr +Turkija tr +Turcija tr +Turkija tr +Tyrkia tr +Turkije tr +Tyrkia tr +Turquia tr +Turcja tr +Turquia tr +Turquia tr +Turcia tr +Турция tr +Turecko tr +Turčija tr +Turska tr +I-Turkey tr +Turkiet tr +ÐÕ츢 tr +ตุรกี tr +Türkiye tr +Туреччина tr +ThềENhĩ Kì tr +土耳其 tr +土耳其 tr +Trinidad and Tobago tt +Trinidad en Tobago tt +ترينيداد و توباغو tt +Trinidad və Tabaqo tt +Трынідад і Табага tt +Тринидад и Тобаго tt +Trinidad ha Tobago tt +Trinidad i Tobago tt +Trinidad i Tobago tt +Trinidad a Tobago tt +Trinidad og Tobago tt +Trinidad und Tobago tt +Τρίνινταντ και Τομπάγκο tt +Trinidado kaj Tobago tt +Trinidad y Tobago tt +Trinidad ja Tobago tt +Trinidad eta Tobago tt +ترینیداد و تُباگو tt +Trinidad ja Tobago tt +Trinidad og Tobago tt +Trinidad et Tobago tt +Trindade e Tobago tt +טרינידד וטובגו tt +Trinidad i Tobago tt +Trinidad és Tobago tt +Trinidad dan Tobago tt +Trinidad og Tobago tt +Trinidad e Tobago tt +トリニダードトバコ tt +트리니다드토바고 tt +ຕີນິແດດແລະໂທບາໂກ tt +Trinidadas ir Tobagas tt +Trinidada un Tobago tt +Trinidad u Tobago tt +Trinidad og Tobago tt +Trinidad en Tobago tt +Trinidad og Tobago tt +Trinidad le Tobago tt +Trinidad e Tobago tt +Trinidad i Tobago tt +Trinidade e Tobago tt +Trinidad e Tobago tt +Trinidad şi Tobago tt +Тринидад и Тобаго tt +Trinidad a Tobago tt +Trinidad in Tabago tt +Trinidad i Tobago tt +I-Trinidad kanye neTobago tt +Trinidad och Tobago tt +ðâɢ¼¡ð & ¦¼¡À¡§¸¡ tt +ตรีนิแดดและโทบาโก tt +Trinidad veTabago tt +Республіка Трінідад та Тобаго tt +Trinidad na Tobago tt +Trinidad và Tobago tt +Trinidad ne Tobago tt +特里尼达和多巴哥 tt +千里達及托貝哥 tt +Trinidad knaye ne-Tobago tt +Tuvalu tv +Тувалу tv +Тували tv +ຊູລູ tv +图瓦卢 tv +Taiwan tw +تايوان tw +Tayvan tw +Тайвань tw +Тайван tw +Tajvan tw +Ταϊβάν tw +Tajvano tw +Taiwán tw +Taivan tw +تایوان tw +Taivan tw +Taïwan tw +Taiwán tw +טיוואן tw +Tajvan tw +Tajvan tw +台湾 tw +대만 tw +ໃຕ້ຫວັນ tw +Taivanis tw +Taivāna tw +Tajwan tw +Tajwan tw +Formosa tw +Тайвань tw +Tajvan tw +Tajvan tw +I-Taiwan tw +¾¡öÅ¡ý tw +ได้หวัน tw +Tayvan tw +Тайвань tw +Đài Loan tw +中国台湾 tw +台灣 tw +Tanzania, United Republic of tz +Злучаная Рэспубліка Танзанія tz +Танзания tz +Tanzanija, Ujedinjena Republika tz +Tanzania tz +Tanzania, Republica de tz +Tanazia, Errepublika Batua tz +Tanzánia tz +ໂດມິນິກັນ tz +República da Tanzânia tz +Tanzánia, Spojená republika tz +Tanzanija, Združena republika tz +Förenade republiken Tanzania tz +坦桑尼亚 tz +Ukraine ua +Ukraïne ua +أوكرانيا ua +Ukrayna ua +Украіна ua +Украйна ua +Ukraina ua +Ukrajina ua +Ucraïna ua +Ukrajina ua +Ουκρανία ua +Ukrainio ua +Ucrania ua +Ukraina ua +Ukrania ua +اکراین ua +Ukraina ua +Ukraina ua +Ucraína ua +אוקראינה ua +Ukrajina ua +Ukrajna ua +Ukraina ua +ÃkraÃna ua +Ucraina ua +ウクライナ ua +우크라이나 ua +ຍູເຄຣນ ua +Ukraina ua +Ukraina ua +Ukranja ua +Ukraina ua +Oekraïne ua +Ukraina ua +Ucraina ua +Ukraina ua +Ucrânia ua +Ucrânia ua +Ucraina ua +Украина ua +Ukrajina ua +Ukrajina ua +Ukrajna ua +I-Ukraine ua +Ukraina ua +¯ì¦Ãöý ua +ยูเครน ua +Ukrayna ua +Україна ua +Ukraina ua +Ucrinne ua +乌克兰 ua +烏克蘭 ua +Uganda ug +Уганда ug +Уганда ug +ແພນດ້າ ug +乌干达 ug +United States of America us +Vereenigde State van Amerika us +الولايات المتحدة الأمريكية us +Amerika Birləşmiş Ştatları us +Злучаныя Штаты Амэрыкі us +САЩ us +Stadoù-Unanet Amerika us +Sjedinjene Američke Države us +Estats Units d'Amèrica us +Spojené státy americké us +USA us +USA us +Ην. Πολιτείες της Αμερικής us +Usono us +Estados Unidos de América us +Ameerika Ühendriigid us +Amerikako Estatu Batuak us +ایالات متحدهی آمریکا us +Yhdysvallat us +Sambandsríki Amerika (USA) us +États Unis d'Amérique us +Estados Unidos de América us +ארצות הברית us +Sjedinjene Američke Države us +Amerikai Egyesült Államok us +Amerika Serikat us +BandarÃki Norður AmerÃku us +Stati Uniti d'America us +アメリカ us +미 합중국 us +ສະຫະລັດອາເມລິກາ us +Jungtinės Amerikos Valstijos us +Amerikas Savienotās Valstis us +Stati Uniti us +USA us +Verenigde Staten van Amerika us +USA us +Estats Units d'Amèrica us +Stany Zjednoczone Ameryki us +Estados Unidos da América us +Estados Unidos us +Statele Unite ale Americii us +Соединенные Штаты Америки us +USA us +Združene države Amerike us +Sjedinjene američke države us +I-United States of America us +Amerikas förenta stater us +³ì¸¢Â «¦ÁÃ¢ì¸ ¿¡Î¸û us +สหรัฐอเมริกา us +Amerika Birleşik Devletleri us +США us +mashango o tangananaho a America us +Mĩ us +United States ye Melika us +美利坚合众国 us +美利堅合眾國 us +Uruguay uy +الأوروغواي uy +Uruqvay uy +Уругвай uy +Уругвай uy +Urugvaj uy +Uruguai uy +Ουρουγουάη uy +Urugvajo uy +Uruguai uy +اروگویه uy +Uruguai uy +אורוגואי uy +Urugvaj uy +ウルグアイ uy +우루과이 uy +ອຸລຸກກວຍ uy +Urugvajus uy +Urugvaja uy +Urugwaj uy +Uruguai uy +Urugwaj uy +Uruguai uy +Uruguai uy +Uruguai uy +Уругвай uy +Uruguaj uy +Urugvaj uy +Urugvaj uy +I-Uruguay uy +¯Õ̧Šuy +อุรุกวัย uy +Уругвай uy +Ourougway uy +乌拉圭 uy +烏拉圭 uy +Uzbekistan uz +Узбэкістан uz +Узбекистан uz +Uzbekistán uz +Üzbegisztán uz +ເດນ່ງນ uz +Uzbequistão uz +乌兹别克斯坦 uz +Vatican City va +Ватыкан va +Ватикана va +Vatikan va +Vatikanstaten va +Vaticano va +Batikano Hiria va +Vatikán va +ລັດເວີຍ va +Cidade do Vaticano va +Vatikán va +Vatikan va +Vatikanstaten va +梵蒂冈 va +St. Vincent and the Grenadines vc +St. Vincent en die Grenadene vc +سانت فينسنت و الغرينادين vc +St. Vincent və Grenadines vc +Сент-Винсент и Гренадине vc +S. Visant hag ar Grenadinez vc +Sveti Vincent i Grenadini vc +St. Vincent i les Granadines vc +St. Vincent a Grenadiny vc +St. Vincent og Grenadinerne vc +St. Vincent und Grenadinen vc +St. Vincent kaj la Grenadinoj vc +San Vicente y las Granadinas vc +St. Vincent ja Grenadines vc +St. Vincent eta Grenadines vc +سن وینسن و گرادینس vc +St. Vincent ja Grenadiinit vc +Sankta Vinsent og Grenadinoyggjar vc +St Vincent et les Grenadines vc +San Vicente e as Granadinas vc +סנט וינסנט והגרנדינים vc +St. Vincent és Grenadines vc +St. Vincent dan the Grenadines vc +St. Vincent og Grenadines vc +S. Vincent e the Grenadines vc +セントヴィンセントグレナディン vc +세인트 빈센트 그레나딘 vc +ເຊີນວິນແຊນ ແລະເກນາດີນ vc +Šv. Vincentas ir Grenadinai vc +Sv. Vincents un Grenadīnes vc +St. Vinċenz u l-Grenadini vc +St. Vincent og Grenadinene vc +St. Vincent en de Grenadines vc +St. Vincent og Grenadinane vc +St. Vincent le Grenadines vc +St. Vincent e les Granadines vc +St. Vincent i Grenadyny vc +São Vicente e Grenadinas vc +São Vicente e Grenadines vc +Sf. Vincent şi Grenadines vc +Сент-Винсент и Гренадины vc +St. Vincent a Grenadines vc +Sv. Vincent in Grenadini vc +St. Vincent i Grenadine vc +I-St. Vincent and the Grenadines vc +St. Vincent och Grenadinerna vc +¦ºÂ¢ýð Å¢ý¦ºýð & ¸¢¦ÃÉËý¸û vc +เซนต์วินเซนต์ และ เกรนาดีน vc +St. Vincent ve Grenadines vc +Сент-Вінсент і Гренадіни vc +St. Vincent na Grenadines vc +St. Vincent và Grenadines vc +St. Vincent ne Grenadines vc +圣文森特和格林那达 vc +聖文森及格納那丁 vc +I-St. Vincent kanye ne-Grenadines vc +Venezuela ve +فنزويلا ve +Вэнэсуэла ve +Венецуела ve +Venecuela ve +Βενεζουέλα ve +Venezuelo ve +Venetsueela ve +ونزویلا ve +Venesuela ve +Vénézuela ve +ונצואלה ve +Venecuela ve +ベネズェラ ve +베네수엘라 ve +ເວເນຊຸເອລາ ve +Venesuela ve +Venecuēla ve +Veneżwela ve +Wenezuela ve +Венесуэла ve +Venecuela ve +I-Venezuela ve +¦ÅÉ¢ÍÅÄ¡ ve +เวเนซูเอลา ve +Венесуела ve +委内瑞拉 ve +委內瑞拉 ve +Virgin Islands, British vg +Вирджински Острови, Британски vg +Djevičanska ostrva, Britanska vg +Britiske jomfruøer vg +Islas Vírgenes Británicas vg +Irla Birjinak, Britaniar vg +Virgin-szigetek (brit) vg +Ilhas Virgens, Inglaterra vg +Panenské Ostrovy, Britské vg +Deviški otoki, Britanski vg +Brittiska Jungfruöarna vg +维尔京群岛,英国 vg +Virgin Islands, U.S. vi +Вирджински Острови, Американски vi +Djevičanska ostrva, Američka vi +Jomfruøerne vi +Islas Vírgenes Americanas vi +Irla Birjinak, EE.BB. vi +Virgin-szigetek (USA) vi +Ilhas Virgens, EUA vi +Panenské Ostrovy, Americké vi +Deviški otoki, ZDA vi +Amerikanska Jungfruöarna vi +维尔京群岛,美国 vi +Vietnam vn +Viëtnam vn +فييتنام vn +Vyetnam vn +Віетнам vn +Виетнам vn +Vijetnam vn +Βιετνάμ vn +Vjetnamo vn +ویتنام vn +וייטנאם vn +Vijetnam vn +VÃetnam vn +ベトナム vn +베트남 vn +ຫວງດນາມ vn +Vietnamas vn +Vjetnama vn +Vjetnam vn +Viëtnam vn +Wietnam vn +Vietname vn +Vietnã vn +Вьетнам vn +I-Vietnam vn +เวียตนาม vn +В'єтнам vn +越南 vn +越南 vn +Vanuatu vu +Вануату vu +Ванути vu +ຈີນ vu +瓦努阿图 vu +Wallis and Futuna wf +Valis i Futuna wf +Wallis- og Futuna-øerne wf +Wallis y Futuna wf +Wallis eta Futuna wf +Wallis és Futuna wf +ປັກອິນພາບ wf +Wallis e Futuna wf +Wallis a Futuna wf +Wallis in Futuna wf +Wallis och Futuna wf +Samoa ws +Самоа ws +Самоя ws +Szamoa ws +ໂຊນາ ws +萨摩亚群岛 ws +Yemen ye +اليمن ye +Емен ye +Йемен ye +Jemen ye +Iemen ye +Jemen ye +Jemen ye +Υεμένη ye +Jemeno ye +Jeemen ye +یمن ye +Jemen ye +Jemen ye +תימן ye +Jemen ye +Jemen ye +イエメン ye +예멘 ye +ເດມອນ ye +Jemenas ye +Jemen ye +Jemen ye +Jemen ye +Jemen ye +Jemen ye +Iémen ye +Йемен ye +Jemen ye +Jemen ye +I-Yemen ye +Jemen ye +§ÂÁý ye +Ємен ye +也门 ye +葉門 ye +Yugoslavia yu +Югаславія yu +Югославия yu +Jugoslavija yu +Jugoslavien (Serbien/Montenegro) yu +Jugoszlávia yu +ໂບລິເວີຍ yu +Iugoslávia yu +Juhoslávia yu +Jugoslavija yu +Jugoslavien yu +南斯拉夫 yu +South Africa za +Suid Afrika za +جنوب أفريقيا za +Cənubi Afrika za +Паўднёвая Афрыка za +Южна Африка za +Suafrika za +Južna Afrika za +Sudàfrica za +Jižní Afrika za +Sydafrikanske republik za +Südafrika za +Νότια Αφρική za +Sudafriko za +Sudáfrica za +Lõuna Aafrika za +Hego Afrika za +آفریقای جنوبی za +Etelä-Afrikka za +Suðurafrika za +Afrique du sud za +África do Sur za +דרום אפריקה za +Južna Afrika za +Dél-Afrika za +Afrika Selatan za +Suður AfrÃka za +Sud Africa za +南アフリカ za +남 아프리카 공화국 za +ແອບພິກາໃຕ້ za +Pietų Afrika za +Dienvid Āfrika za +Afrika t'Isfel za +Sør-Afrika za +Zuid-Afrika za +Sør-Afrika za +Afrika Borwa za +Sudafrica za +Afryka Południowa za +Africa do Sul za +África do Sul za +Africa de Sud za +Южная Африка za +Južná Afrika za +Južna Afrika za +Južna Afrika za +I-South Africa za +Sydafrika za +¦¾ý ¬ôâ측 za +แอฟริกาใต้ za +Güney Afrika za +Південна Африка za +Afurika tshipembe za +Nam Phi za +Mzantsi Afrika za +南非 za +南非 za +Emzantsi Afrika za +Zambia zm +Замбія zm +Замбия zm +ຈາໄມກາ້ zm +Zâmbia zm +Zambija zm +赞比亚 zm +Zimbabwe zw +Зымбабвэ zw +Зимбабве zw +Zimbabve zw +ລິຊາ zw +Zimbabve zw +津巴布韦 zw +Andorra ad +Андора ad +Андора ad +Andora ad +ອີນເດີຍ ad +Andora ad +Андорра ad +安道尔 ad +United Arab Emirates ae +Vereenigde Arabiese Emirate ae +الإمارات العربية المتحدة ae +Злучаныя Арабскія Эміраты ae +Обединени Арабски Емирства ae +Ujedinjeni arapski emirati ae +Emirats Àrabs Units ae +Spojené arabské emiráty ae +Forenende Arabiske Emirater ae +Vereinigte Arabische Emirate ae +Ενωμένα Αραβικά Εμιράτα ae +Emiratos árabes unidos ae +Araabia Ühendemiraadid ae +Arabiar Emirato Batuak ae +امارات متحده عربی ae +Yhdistyneet Arabiemiraatit ae +Émirats Arabes Unis ae +איחוד האמירויות הערביות ae +Ujedinjeni arapski emirati ae +Egyesült Arab Emirátusok ae +Emirati arabi uniti ae +アラブ首長国連邦 ae +아랍 에미레이트 연합 ae +ສະຫະລັດ ae +Jungtiniai Arabų Emiratai ae +Emirati Għarab Magħquda ae +De forente arabiske emirater ae +Verenigde Arabische Emiraten ae +Dei sameinte arabiske emirata ae +Di-Emirate tseo di Kopanego tsa Arab ae +Zjednoczone Emiraty Arabskie ae +Emiratos Árabes Unidos ae +Emirados Árabes ae +Emiratele Arabe Unite ae +Объединенные Арабские Эмираты ae +Spojené arabské emiráty ae +Združeni arabski Emirati ae +Förenade arabemiraten ae +³ì¸¢Â «ÃÒ ¿¡Î¸û ae +Birleşik Arap Emirlikleri ae +Об'єднані Арабські Емірати ae +Mashango o tangananaho a Emirates ae +阿拉伯联合酋长国 ae +阿拉伯聯合大公國 ae +Izindawo zezinduna zase-United Arab ae +Afghanistan af +Афганістан af +Афганистан af +Afganistan af +Afghanistán af +Afganisztán af +ລີທົ່ວເນີຍ af +Afeganistão af +Afganistan af +Afganistan af +Afganistan af +Афганістан af +阿富汗 af +Antigua and Barbuda ag +Antigue en Barbuda ag +أنتيغوا و باربودا ag +Antigua və Barbuda ag +Антыгуа і Барбуда ag +Антигуа и Барбадос ag +Antigua ha Barbuda ag +Antigua i Barbuda ag +Antigua i Barbuda ag +Antigua a Barbuda ag +Antigua og Barbuda ag +Antigua und Barbuda ag +Antigua και Barbuda ag +Antigvo kaj Barbudo ag +Antigua y Barbuda ag +Antigua ja Barbuda ag +Antigua eta Barbuda ag +آنتیگوا و باربودا ag +Antigua ja Barbados ag +Antigua og Barbuda ag +Antigua et Barbuda ag +Antiga e Barbuda ag +אנטיגואה וברבודה ag +Antigua i Barbuda ag +Antigua és Barbuda ag +Antigua dan Barbuda ag +Antigúa og Barbúda ag +Antigua e Barbuda ag +アンティグアバーブーダ ag +앤티가 바부다 ag +Antikva ir Barbuda ag +Antigva un Barbudas ag +Antigwa u Barbuda ag +Antigua og Barbuda ag +Antigua en Barbuda ag +Antigua og Barbuda ag +Antigua le Barbuda ag +Antigua e Barbuda ag +Antigua i Barbuda ag +Antigua e Barbuda ag +Antigua e Barbuda ag +Antigua şi Barbuda ag +Антигуа и Барбадос ag +Antigua a Barbuda ag +Antigva in Barbuda ag +Antigua i Barbuda ag +I-Antigua kanye ne Barbuda ag +Antigua och Barbuda ag +¬ýÊÌÅ¡ & À¡÷Ò¼¡ ag +Antigua ve Barbuda ag +Трінідад та Тобаго ag +Antigua và Barbuda ag +Antigua eyet Barbuda ag +Antigua ne Barbuda ag +安地瓜岛和巴布达岛 ag +安地瓜島和巴布達島 ag +Antigua kanye ne-Barbuda ag +Anguilla ai +Ангуила ai +ແພນວິນ ai +Angvila ai +Ангілья ai +安圭拉 ai +Albania al +Альбанія al +Албания al +Albanija al +Albanien al +Albánia al +ແອດແລນຕິກ al +Albânia al +Albánsko al +Albanija al +Albanien al +Албанія al +阿尔巴尼亚 al +Armenia am +Армэнія am +Армения am +Armenija am +Armenien am +Örményország am +ອາເຈນຕິນາ am +Armênia am +Arménsko am +Armenija am +Armenien am +Арменія am +亚美尼亚 am +Netherlands Antilles an +Холандски Антили an +Nizozemski Antili an +Nederlandske antiller an +Antillas holandesas an +Antilla Holandarrak an +Holland-Antillák an +ເນເທີແລນ an +Antilhas an +Holandské Antily an +Nizozemski Antili an +Nederländska Antillerna an +Голландські Антилли an +荷属安的列斯群岛 an +Angola ao +Ангола ao +Ангола ao +ບັນແກເລີຍ ao +Ангола ao +安哥拉 ao +Argentina ar +Argentinië ar +الأرجنتين ar +Аргентына ar +Аржентина ar +Arc'hantina ar +Argentinien ar +Αργεντινή ar +Argentino ar +Argentiina ar +آرژانتین ar +Agentiina ar +Argentine ar +Arxentina ar +ארגנטינה ar +Argentína ar +ArgentÃna ar +アルゼンチン ar +아르헨티나 ar +ອາເຈນຕິນາ ar +Argentīna ar +Arġentina ar +Argentinië ar +Argentyna ar +Аргентина ar +Argentína ar +I-Argentina ar +¬÷¦ºýÊÉ¡ ar +อาร์เจนตินา ar +Arjantin ar +Аргентина ar +Agenthina ar +Årdjintene ar +阿根廷 ar +阿根廷 ar +American Samoa as +Амэрыканскае Самоа as +Американска Самоа as +Američka Samoa as +Samoa (USA) as +Samoa americana as +Amerikako Samoa as +Amerikai Szamoa as +ອາເມລິກາເຫນືອ as +Samoa Americana as +Americká Samoa as +Ameriška Samoa as +Amerikanska Samoa as +Американське Самоа as +美属萨摩亚群岛 as +Austria at +Oostenryk at +النمسا at +Avstriya at +Аўстрыя at +Австрия at +Aostria at +Austrija at +Àustria at +Rakousko at +Østrig at +Österreich at +Αυστρία at +Aŭstrio at +اتریش at +Itävalta at +Eysturríki at +Autriche at +אוסטריה at +Austrija at +Ausztria at +AusturrÃki at +オーストリア at +오스트리아 at +ອອດສະເຕເລີຍ at +Austrija at +Austrija at +Awtrija at +Østerrike at +Oostenrijk at +Austerrike at +Áustria at +Áustria at +Австрия at +Rakúsko at +Avstrija at +Austrija at +I-Austria at +Österrike at +¬Íò¾¢Ã¢Â¡ at +ออสเตรีย at +Avusturya at +Австрія at +Ositiria at +A'o at +Ôtriche at +奥地利 at +奧地利 at +Australia au +Australië au +أستراليا au +Avustralya au +Аўстралія au +Австралия au +Aostralia au +Australija au +Austràlia au +Austrálie au +Australien au +Australien au +Αυστραλία au +Aŭstralio au +Austraalia au +استرالیا au +Australie au +אוסטרליה au +Australija au +Ausztrália au +ÃstralÃa au +オーストラリア au +오스트레일리아 au +ອອດສະເຕເລີຍ au +Australija au +Austrālija au +Awstralja au +Australië au +Austrália au +Austrália au +Австралия au +Austrália au +Avstralija au +Australija au +I-Australia au +Australien au +¬Íò¾¢§ÃĢ¡ au +ออสเตรเลีย au +Avusturalya au +Австралія au +Ositiralia au +U'c au +Ôstraleye au +澳大利亚 au +澳大利亞 au +Aruba aw +Аруба aw +ເກມໄັພ່ aw +Аруба aw +阿鲁巴岛 aw +Azerbaijan az +أذربيجان az +Azərbaycan az +Азэрбайджан az +Азарбайджан az +Azerbejdžan az +Azerbaitjan az +Ázerbajdžánský az +Azerbajdjan az +Aserbaidschan az +Αζερμπαϊτζάν az +Azerbajĝana az +Azerbaiján az +Aserbaidžaan az +آذربایجان az +Azerbaidzan az +Aserbadsjan az +אזרביג'ן az +Azerbejdžan az +Azerbajdzsán az +Azerbaigian az +アゼルバイジャン az +아제르바이잔 az +ອາເຊີໄບຈັນ az +Azerbaidžanas az +Azerbaidžāņu az +Ażerbajġan az +Aserbajdsjan az +Azerbeidjan az +Aserbajdsjan az +Azerbejdżan az +Azerbaijão az +Turco az +Azerbadjan az +Азербайджан az +Ázerbajdžánsky az +Azerbajdžan az +Azerbejdžan az +I-Azerbaijan az +«º÷¨Àº¡ý az +อาร์เซอร์ไบจัน az +Azerice az +Азербайджан az +Azerbaydjan az +阿塞拜疆 az +亞塞拜然 az +Bosnia and Herzegovina ba +Bosnië en Herzegovina ba +البوسنا و الهرسك ba +Босьнія і Герцагавіна ba +Боснена и Херцеговина ba +Bosna i Hercegovina ba +Bòsnia i Hercegovina ba +Bosna a Herzegovina ba +Bosnien-Herzegovina ba +Bosnien und Herzegowina ba +Βοσνία και Ερζεγοβίνη ba +Bosnio kaj Hercegovino ba +Bosnia y Herzegovina ba +Bosnia ja Hertsegovina ba +Bosnia eta Herzegovina ba +بوسنی و هرزگوین ba +Bosnia ja Herzegovina ba +Bosnia-Herzegovina ba +Bosnie herzégovine ba +בוסניה הרצגובינה ba +Bosna i Hercegovina ba +Bosznia-Hercegovina ba +Bosnia e Erzegovina ba +ボスニアヘルツェゴビナ ba +보스니아어와 헤르체고비나 ba +ບອສເນີຍ ແລະ ເຫີເຊີໂກວິນາ ba +Bosnija ir Hercegovina ba +Bosnija un Hercogovina ba +Bożnia u Ħerżegovina ba +Bosnia-Hercegovina ba +Bosnië en Herzegovina ba +Bosnia-Hercegovina ba +Bosnia le Herzegovina ba +Bośnia i Hercegowina ba +Bósnia e Herzegovina ba +Bósnia Herzegóvina ba +Bosnia şi Herţegovina ba +Босния и Герцеговина ba +Bosna a Hercegovina ba +Bosna in Hercegovina ba +I-Bosnia kanye ne Herzegovina ba +Bosnien och Herzegovina ba +¦À¡Íɢ¡ ba +บอสเนีย และ เฮอร์เซโกวินา ba +Bosna Hersek ba +Боснія та Герцеговина ba +Mubosinia na Muhezegovina ba +Bosneye ba +Bosnia ne Herzegovina ba +波斯尼亚和黑塞哥维那 ba +波士尼亞與赫塞哥維納 ba +Bosnia kanye ne-Herzegovina ba +Barbados bb +بربادوس bb +Барбадос bb +Барбадос bb +Μπαρμπάντος bb +Babadoso bb +باربادوس bb +Barbade bb +ברבדוס bb +バルバドス bb +바르바도스 bb +ບາລບາດອດສ bb +Barbadosas bb +Barbadosa bb +Барбадос bb +I-Barbados bb +À¡÷§À¼¡Í bb +บาร์บาดอส bb +Барбадос bb +Barbades bb +巴巴多斯 bb +巴貝多 bb +Bangladesh bd +بنغلاديش bd +Banqladeş bd +Банглядэш bd +Бангладеш bd +Bangladeš bd +Bangladéš bd +Bangladesch bd +Μπαγκλαντές bd +Bangladeŝo bd +بنگلادش bd +בנגלדש bd +Bangladeš bd +Banglades bd +バングラデシュ bd +방글라데시 bd +ບັງຄະລາເທດ bd +Bangladešas bd +Bangladeša bd +Bangladexx bd +Bangladesz bd +Banglade bd +Бангладеш bd +Bangladéš bd +Bangladeš bd +I-Bangladesh bd +Àí¸Ç¡§¾Í bd +บังคลาเทศ bd +Bangladeş bd +Бангладеш bd +孟加拉 bd +孟加拉 bd +Belgium be +België be +بلجيكا be +Belçika be +Бэльгія be +Белгия be +Belgia be +Belgija be +Bèlgica be +Belgie be +Belgien be +Belgien be +Βέλγιο be +Belgio be +Bélgica be +Belgia be +Belgika be +بلژیک be +Belgia be +Belgia be +Belgique be +Bélxica be +בלגיה be +Belgija be +Belgia be +BelgÃa be +Belgio be +ベルギー be +벨기에 be +ເບລຢ່ງມ be +Belgija be +Beļģija be +Belġju be +Belgia be +België be +Belgia be +Bèlgica be +Belgia be +Bélgica be +Bélgica be +Belgia be +Бельгия be +Belgicko be +Belgija be +Belgija be +I-Belgium be +Belgien be +¦Àøº¢Âõ be +เบลเยียม be +Belçika be +Бельгія be +Beljike be +比利时 be +比利時 be +Burkina Faso bf +Буркіна Фасо bf +Буркина Фаско bf +ຕຸລະກີ bf +Буркіна Фасо bf +布基纳法索 bf +Bulgaria bg +Bulgarye bg +بلغاريا bg +Bolgarıstan bg +Баўгарыя bg +България bg +Bugarska bg +Bulgària bg +Bulharsko bg +Bulgarien bg +Bulgarien bg +Βουλγαρία bg +Bulgario bg +Bulgaaria bg +بلغارستان bg +Bulgarie bg +בולגריה bg +Bugarska bg +Bulgária bg +BúlgarÃa bg +ブルガリア bg +불가리아 bg +ບັນແກເລີຍ bg +Bulgarija bg +Bulgārija bg +Bulgarija bg +Bulgarije bg +Bułgaria bg +Bulgária bg +Bulgária bg +Болгария bg +Bulharsko bg +Bolgarija bg +Bugarska bg +I-Bulgaria bg +Bulgarien bg +Àø§¸Ã¢Â¡ bg +บัลแกเรีย bg +Bulgaristan bg +Болгарія bg +Baligaria bg +Bulgåreye bg +保加利亚 bg +保加利亞 bg +Bahrain bh +البحرين bh +Бахрэйн bh +Бахрейн bh +Bahrein bh +Bahrajn bh +Μπαχρέιν bh +Bahrein bh +Bahrein bh +بحرین bh +בחריין bh +バーレーン bh +바레인 bh +ຖັກກ່ງວ bh +Bahreinas bh +Baħrain bh +Baghrein bh +Bahrajn bh +Bahamas bh +Bahrein bh +Бахрейн bh +Bahrajn bh +Bahrajn bh +I-Bahrain bh +Bahrein bh +À‹¨Ãý bh +Bahreyn bh +Бахрейн bh +巴林 bh +巴林 bh +Burundi bi +Бурундзі bi +Бурунди bi +ເຄອຣດ bi +Бурунді bi +布隆迪 bi +Benin bj +Бэнін bj +Бенин bj +ບອສເນີຍ bj +Бенін bj +贝宁 bj +Bermuda bm +Бэрмуды bm +Бермуда bm +ເຍລລະມັນ bm +Bermudy bm +Bermudi bm +Бермуди bm +百慕大 bm +Brunei Darussalam bn +Брунэй bn +Бруней bn +Brunei bn +Brunei Szultánság bn +ເບລາລັສເຊີຍ bn +Brunei bn +Brunei Darusalam bn +Бруней Даруссалам bn +Bolivia bo +Bolivië bo +بوليفيا bo +Boliviya bo +Балівія bo +Боливия bo +Bolivija bo +Bolívia bo +Bolívie bo +Bolivien bo +Βολιβία bo +Bolivio bo +Boliivia bo +بولیوی bo +Bolivie bo +בוליביה bo +Bolivija bo +Bolívia bo +BólivÃa bo +ボリビア bo +볼리비아 bo +ໂບລີເວີຍ bo +Bolivija bo +Bolīvija bo +Bolivja bo +Boliwia bo +Bolívia bo +Bolívia bo +Боливия bo +Bolívia bo +Bolivija bo +Bolivija bo +I-Bolivia bo +¦À¡Ä¢Å¢Â¡ bo +โบลิเวีย bo +Bolivya bo +Болівія bo +Boliveye bo +波利维亚 bo +玻利維亞 bo +Brazil br +Brazilië br +البرازيل br +Braziliya br +Бразылія br +Бразилия br +Brasil br +Brazílie br +Brasilien br +Brasilien br +Βραζιλία br +Brazilo br +Brasil br +Brasiilia br +Brasil br +برزیل br +Brasilia br +Brésil br +Brasil br +ברזיל br +Brazília br +BrasilÃa br +Brasile br +ブラジル br +브라질 br +ບາຊີລ br +Brazilija br +Brazīlija br +Brażil br +Brasil br +Brazilië br +Brasil br +Brasil br +Brazylia br +Brasil br +Brasil br +Brazilia br +Бразилия br +Brazília br +Brazilija br +I-Brazil br +Brasilien br +À¢§Ãº¢ø br +บราซิล br +Brezilya br +Бразилія br +Burazili br +Braezi br +巴西 br +巴西 br +Bahamas bs +Багамы bs +Бахами bs +Bahami bs +Bahamák bs +ປານາມາ bs +Bahamy bs +Bahami bs +Багами bs +巴哈马 bs +Bhutan bt +Бутан bt +Бутан bt +Butan bt +Bhután bt +Bhután bt +ຖັກກ່ງວ bt +Butan bt +Бутан bt +不丹 bt +Botswana bw +Батсвана bw +Боцвана bw +Bocvana bw +ບອດສເນີຍ bw +Botsvana bw +Ботсвана bw +博茨瓦纳 bw +Belarus by +روسيا البيضاء by +Беларусь by +Беларус by +Bjelorusija by +Bělorusko by +Hviderusland by +Weißrussland by +Bjelorusio by +Valgevene by +بلاروس by +Valkovenäjä by +Hvítarusland by +Bélarus by +בלרוס by +Bjelorusija by +Fehéroroszország by +HvÃta-Rússland by +Bielorussia by +ベラルーシ by +벨라루스 by +ເບລາລັສ by +Baltarusija by +Baltkrievu by +Hviterussland by +Wit-Rusland by +Kviterussland by +Białoruś by +Bielorússia by +Bielorusso by +Беларусь by +Bielorusko by +Belorusija by +I-Belarus by +Vitryssland by +¦ÀÄ¡åÍ by +เบลารัส by +Білорусія by +Belaruss by +白俄罗斯 by +白俄羅斯 by +Belize bz +Бэлізе bz +Белиз bz +ເບລຍ່ງມ bz +Беліз bz +伯利兹 bz +Default C +Verstek C +افتراضي C +Əsas C +Па ўмаўчаньні C +По подразбиране C +Dre ziouer C +Omissió C +Výchozí C +Standard C +Standard C +Προκαθορισμένο C +Apriora C +Predeterminado C +Vaikimisi C +Aurremugatua C +پیشفرض C +Oletus C +Forsettur C +Par défaut C +Por Omisión C +ברירת מחדל C +Uobičajeno C +Alapértelmezett C +Standar C +Sjálfgefið C +Predefinito C +標準 C +기본 C +ຄ່າປະລິຍາຍ C +Nutylima C +Noklusētais C +Normali C +Standard C +Standaard C +Standard C +Thuso ya Tshoganetso C +Omission C +Domyślnie C +Por Omissão C +Padrão C +Implicit C +По умолчанию C +Štandardný C +Privzeto C +Predefinisano C +Förval C +¦¸¡¼¡¿¢¨Ä C +ค่าปริยาย C +Öntanımlı C +Типовий C +Mặc định C +Prémetou C +Okwendalo C +默认 C +預設 C +Okwendalo C +Canada ca +Kanada ca +كندا ca +Kanada ca +Канада ca +Канада ca +Kanada ca +Kanada ca +Canadà ca +Kanada ca +Kanada ca +Καναδάς ca +Kanado ca +Canadá ca +Kanada ca +Kanada ca +کانادا ca +Kanada ca +Kanada ca +Canadá ca +קנדה ca +Kanada ca +Kanada ca +Kanada ca +Kanada ca +カナダ ca +캐나다 ca +ແຄນາດາ ca +Kanada ca +Kanāda ca +Kanada ca +Kanada ca +Canadá ca +Canadá ca +Канада ca +Kanada ca +Kanada ca +Kanada ca +I-Canada ca +Kanada ca +¸É¼¡ ca +แคนาดา ca +Kanada ca +Канада ca +加拿大 ca +加拿大 ca +Cocos (Keeling) Islands cc +Кокосови Острови cc +Kokosovo (Keeling) ostrvo cc +Islas Cocos (Keeling) cc +Koko Irlak cc +Kókusz-szigetek (Keeling) cc +Ilhas Cocos cc +Kokosove Ostrovy cc +Kokosovi (Keelingovi) otoki cc +Kokosöarna cc +Кокосові острови cc +Congo, the democratic republic of the cd +Дэмакратычная Рэспубліка Конга cd +Конго cd +Kongo, demokratska republika cd +Congo, den demokratiske republik cd +Congo, república democrática del cd +Kongo, errepublika demokratikoa cd +Kongói Demokratikus Köztársaság cd +República Democrática do Congo cd +Demokratická Republika Kongo cd +Kongo, demokratična republika cd +Demokratiska republiken Kongo cd +刚果民主共和国 cd +Central African Republic cf +ЦАР cf +Centralnoafrička Republika cf +Central-afrikanske Republik cf +República Centroafricana cf +Afrika Erdiko Errepublika cf +Közép-Afrikai Köztársaság cf +ໂດມິນິກັນ cf +República da África Central cf +Stredoafrická Republika cf +Centralnoafriška republika cf +Centralafrikanska Republiken cf +Центральноафриканська республіка cf +中非共和国 cf +Congo cg +Конга cg +Конго cg +Kongo cg +Kongo cg +Kongó cg +ຄອນໂໍຊລ cg +Kongo cg +Kongo cg +Kongo cg +Конго cg +刚果 cg +Switzerland ch +Switserland ch +سويسرا ch +İsveçrə ch +Швэйцарыя ch +Швейцария ch +Suis ch +Švicarska ch +Suïssa ch +Švýcarsko ch +Schweiz ch +Schweiz ch +Ελβετία ch +Svislando ch +Suiza ch +Šveits ch +Suitza ch +سوییس ch +Sveitsi ch +Suisse ch +Suíza ch +שוייץ ch +Švicarska ch +Svájc ch +Swiss ch +Sviss ch +Svizzera ch +スイス ch +스위스 ch +ສະວິສເຊີແລນ ch +Šveicarija ch +Šveice ch +Svizzera ch +Sveits ch +Zwitserland ch +Sveits ch +Suissa ch +Szwajcaria ch +Suíça ch +Suíça ch +Elveţia ch +Швейцария ch +Švajčiarsko ch +Švica ch +Švajcarska ch +I-Switzerland ch +Schweiz ch +ÍÅ¢ðº÷Ä¡óÐ ch +สวิสเซอร์แลนด์ ch +İsviçre ch +Швейцарія ch +Thuỵ Sĩ ch +Swisse ch +瑞士 ch +瑞士 ch +Cote d'ivoire ci +Бераг Слановай Косьці ci +Кот'Дивоар ci +Obala Slonovače ci +Elfenbenskysten ci +Costa de Marfil ci +Elefántcsontpart ci +ປ່ອຍຫມາກກະລອກ ci +Slonokoščena obala ci +Elfenbenskusten ci +Кот д'Івуар ci +Cook islands ck +Kukova ostrva ck +Cook-øerne ck +Islas Cook ck +Cook Irlak ck +Cook-szigetek ck +ຄຸກກີ້ ck +Ilhas Cook ck +Cookove ostrovy ck +Cookovi otoki ck +Cooköarna ck +Острови Кука ck +库克群岛 ck +Chile cl +Chilië cl +تشيلي cl +Şili cl +Чылі cl +Чили cl +Čile cl +Xile cl +Χιλή cl +Ĉilio cl +Tšiili cl +Txile cl +شیلی cl +Chili cl +צ'ילה cl +Čile cl +Chili cl +Cile cl +チリ cl +칠레 cl +ຊີລີ cl +Čilė cl +Čīle cl +Ċile cl +Chili cl +Cile cl +Чили cl +Čile cl +Čile cl +Čile cl +I-Chile cl +º¢Ä¢ cl +ชิลี cl +Şili cl +Чилі cl +Chi lê cl +Tchili cl +智利 cl +智利 cl +Cameroon cm +Камэрун cm +Камерун cm +Kamerun cm +Cameroun cm +Camerún cm +Kamerun cm +Kamerun cm +ຕາລາງງານ - K cm +Camarões cm +Komerun cm +Kamerun cm +Kamerun cm +Камерун cm +喀麦隆 cm +China cn +Sjina cn +الصين cn +Çin cn +Кітай cn +Китай cn +Sina cn +Kina cn +Xina cn +Čína cn +Kina cn +Κίνα cn +Ĉinujo cn +Hiina cn +Txina cn +چین cn +Kiina cn +Kina cn +Chine cn +סין cn +Kina cn +Kína cn +Cina cn +KÃna cn +Cina cn +中国 cn +중국 cn +ຈີນ cn +Kinija cn +Ķīna cn +Ċina cn +Kina cn +Kina cn +Xina cn +Chiny cn +Китай cn +Čína cn +Kitajska cn +Kina cn +I-China cn +Kina cn +º£É¡ cn +จีน cn +Çin cn +Китай cn +Trung Quốc cn +Chine cn +中国 cn +中國 cn +Colombia co +Colombië co +كولمبيا co +Калюмбія co +Колумбия co +Kolumbija co +Colòmbia co +Kolumbie co +Kolumbien co +Κολομβία co +Kolumbio co +Kolumbia co +Kolonbia co +کلمبیا co +Kolumbia co +Colombie co +קולומביה co +Kolumbija co +Kolumbia co +コロンビア co +콜롬비아 co +ໂຄລຳເບີຍ co +Kolumbija co +Kolumbija co +Kolumbja co +Columbia co +Kolumbia co +Colômbia co +Colômbia co +Columbia co +Колумбия co +Kolumbia co +Kolumbija co +I-Colombia co +¦¸¡ÄõÀ¢Â¡ co +โคลัมเบีย co +Kolombiya co +Колумбія co +Colombeye co +Columbia co +哥伦比亚 co +哥倫比亞 co +Costa Rica cr +كوستاريكا cr +Коста Рыка cr +Коста Рика cr +Kostarika cr +Kostarika cr +Κόστα Ρίκα cr +کاستاریکا cr +Kosta Rika cr +קוסטה ריקה cr +Costa rica cr +コスタリカ cr +코스타 리카 cr +ໂຄເອເທີຍ cr +Kosta Rika cr +Kostaryka cr +Коста-Рика cr +Kostarika cr +Kostarika cr +I-Costa Rica cr +§¸¡Š¼¡ ⸡ cr +Kosta Rika cr +Коста-Ріка cr +哥斯达黎加 cr +哥斯大黎加 cr +Cuba cu +Kuba cu +كوبا cu +Куба cu +Куба cu +Kuba cu +Kuba cu +Kuba cu +Κούβα cu +Kuuba cu +Kuba cu +کوبا cu +Kuuba cu +Kuba cu +קובה cu +Kuba cu +キューバ cu +쿠바 cu +ເກມໄພ່ cu +Kuba cu +Kuba cu +Kuba cu +Куба cu +Kuba cu +Kuba cu +I-Cuba cu +Kuba cu +¸¢ÔÀ¡ cu +Küba cu +Куба cu +古巴 cu +古巴 cu +Cape Verde cv +Капе Верде cv +Zelenortska ostrva cv +Kapverdiske øer cv +Cabo Verde cv +Cabo Verde cv +Zöldfoki-szigetek cv +ເກມໄພ່ cv +Cabo Verde cv +Kap Verde cv +佛得角 cv +Christmas Island cx +Božično ostrvo cx +Juleøen cx +Islas Christmas cx +Eguberri Irla cx +Karácsony-szigetek cx +ຄິດສະຕອລ cx +Ilhas do Natal cx +Vianočné Ostrovy cx +Božični otok cx +Julön cx +Острів Різдва cx +圣诞岛 cx +Cyprus cy +Кіпр cy +Кипър cy +Kipar cy +Cypern cy +Chipre cy +Txipre cy +Ciprus cy +ບີບອັດ cy +Chipre cy +Ciper cy +Cypern cy +Кипр cy +塞浦路斯 cy +Czechia cz +Czechië cz +التشيك cz +Çex Respublikası cz +Чэхія cz +Чехия cz +Tchekia cz +Češka cz +Txèquia cz +Česko cz +Tjekkiet cz +Tschechien cz +Τσεχία cz +Ĉeĥio cz +República Checa cz +Tšehhi cz +Txekia cz +چک cz +Tsekki cz +République tchèque cz +Chequia cz +צ'כיה cz +Češka cz +Csehország cz +Tékkland cz +Repubblica Ceca cz +チェコ cz +체코 cz +Čekija cz +Čehija cz +Cżekia cz +Tsjekkia cz +Tsjechië cz +Tsjekkia cz +Chèquia cz +Czechy cz +República Checa cz +República Tcheca cz +Cehia cz +Чехия cz +Česko cz +Češka cz +Češka cz +I-Czechia cz +Tjeckien cz +¦ºì¡ cz +Çek Cumhuriyeti cz +Чехія cz +Séc cz +Tchekeye cz +捷克 cz +捷克 cz +Germany de +Duitsland de +ألمانيا de +Almaniya de +Нямеччына de +Германия de +Alamagn de +Njemačka de +Alemanya de +Německo de +Tyskland de +Deutschland de +Γερμανία de +Germanio de +Alemania de +Saksamaa de +Alemania de + آلمان de +Saksa de +Týskland de +Allemagne de +Alemaña de +גרמניה de +Njemačka de +Németország de +Jerman de +Ãýskaland de +Germania de +ドイツ de +독일 de +ເຍລລະມັນນີ de +Vokietija de +Vācija de +Ġermanja de +Tyskland de +Duitsland de +Tyskland de +Alemanya de +Niemcy de +Alemanha de +Alemanha de +Germania de +Германия de +Nemecko de +Nemčija de +Nemačka de +I-Germany de +Tyskland de +§º÷ÁÉ¢ de +เยอรมันนี de +Almanya de +Німеччина de +Đức de +Almagne de +德国 de +德國 de +IJalimani de +Djibouti dj +جيبوتي dj +Джыбуці dj +Джибути dj +Đibuti dj +Džibuti dj +Dschibuti dj +Τζιμπουτί dj +جیبوتی dj +ג'יבוטי dj +Džibuti dj +Dzsibuti dj +ジブティ dj +지부티 dj +ພັດພາ dj +Džibuti dj +Dġibuti dj +Dżibuti dj +Djibuti dj +Djibuti dj +Джибути dj +Džibuty dj +Džibuti dj +I-Djibouti dj +Ê¢ƒ¢¦À¡Ê dj +Cibuti dj +Джібуті dj +吉布提 dj +吉布地 dj +Denmark dk +Denemarke dk +الدنمارك dk +Danimarka dk +Данія dk +Дания dk +Danmark dk +Danska dk +Dinamarca dk +Dánsko dk +Danmark dk +Dänemark dk +Δανία dk +Danlando dk +Dinamarca dk +Taani dk +Danimarka dk +دانمارک dk +Tanska dk +Danmark dk +Danemark dk +Dinamarca dk +דנמרק dk +Danska dk +Dánia dk +Danmörk dk +Danimarca dk +デンマーク dk +덴마크 dk +ເດນມາກ dk +Danija dk +Dānija dk +Danimarka dk +Danmark dk +Denemarken dk +Danmark dk +Dinamarca dk +Dania dk +Dinamarca dk +Dinamarca dk +Danemarca dk +Дания dk +Dánsko dk +Danska dk +Danska dk +I-Denmark dk +Danmark dk +¦¼ýÁ¡÷ì dk +เดนมาร์ก dk +Danimarka dk +Данія dk +Đan Mạch dk +Daenmåtche dk +丹麦 dk +丹麥 dk +Dominica dm +Дамініка dm +Доминика dm +Dominika dm +Dominika dm +ໂລມາເນີຍ dm +Dominicana dm +Dominikánsko dm +Dominikanska republika dm +Домініка dm +多米尼加 dm +Dominican Republic do +Dominikiese Republiek do +جمهورية الدومينيكان do +Dominik Respublikası do +Дамініканская Рэспубліка do +Доминиканска република do +Republik Dominikan do +Dominikanska Republika do +República Dominicana do +Dominikánská republika do +Dominikanske Republik do +Dominikanische Republik do +Δομινικανή Δημοκρατία do +Dominika Respubliko do +República Dominicana do +Dominikaani Vabariik do +Dominikar Errepublika do +جمهوری دامینیکن do +Dominikaaninen tasavalta do +République dominicaine do +República Dominicana do +הרפובליקה הדומיניקנית do +Dominikanska Republika do +Dominikai Köztársaság do +Republik Dominika do +DóminÃska Lýðveldið do +Repubblica Dominicana do +ドミニカ共和国 do +도미니카 공화국 do +ໂດມິນີກັນ do +Dominikos Respublika do +Dominikas Republika do +Repubblika Dominikana do +Den dominikanske republikk do +Dominicaanse Republiek do +Den dominikanske republikken do +Republica Dominicana do +Dominikana do +República Dominicana do +República Dominicana do +Republica Dominicană do +Доминиканская республика do +Dominikánska republika do +Dominikanska republika do +Dominikanska republika do +I-Dominican Republic do +Dominikanska republiken do +¦¼¡Á¢É¢ì¸ý ÌÊÂÃÍ do +โดมินิกัน do +Dominik Cumhuriyeti do +Домініканська республіка do +Muvhuso wa Dominican do +Cộng hoà Dominican do +Republike Dominikinne do +IRepublic yeDominican do +多米尼加共和国 do +多明尼加共和國 do +Algeria dz +Algerië dz +الجزائر dz +Альжыр dz +Алжир dz +Alžir dz +Algèria dz +Alžírsko dz +Algeriet dz +Algerien dz +Αλγερία dz +Algerio dz +Argelia dz +Alžeeria dz + الجزیره dz +Algérie dz +אלג'יריה dz +Alžir dz +Algéria dz +アルジェリア dz +알제리 dz +ບັນກາເລີຍ dz +Alžyras dz +Alġerija dz +Algerie dz +Algerije dz +Algerie dz +Algieria dz +Argélia dz +Argélia dz +Алжир dz +Alžírsko dz +Alžirija dz +I-Algeria dz +Algeriet dz +«øƒ¢Ã¢Â¡ dz +Алжир dz +Aldjereye dz +阿尔及利亚 dz +阿爾及利亞 dz +Equador ec +Ewenaar ec +الإكوادور ec +Ekvator ec +Эквадор ec +Еквадор ec +Ecuador ec +Ekvador ec +Ekvádor ec +Ecuador ec +Ισημερινός ec +Ekvadoro ec +Ecuador ec +Ekvador ec +Ekuador ec +اکوادور ec +Équateur ec +Ecuador ec +אקוודור ec +Ekvador ec +Ecuador ec +Ekvador ec +Ecuador ec +エクアドル ec +에콰도르 ec +ເອກໍດໍ ec +Ekvadoras ec +Ekvadora ec +Ekwador ec +Ecuador ec +Ecuador ec +Ekwador ec +Ecuador ec +Эквадор ec +Ekvádor ec +Ekvador ec +Ekvador ec +I-Equador ec +®ì¦Å§¼¡÷ ec +เอกวาดอร์ ec +Ekvator ec +Еквадор ec +Ecwåteur ec +厄瓜多尔 ec +厄瓜多 ec +Estonia ee +Estlandies ee +استونيا ee +Estoniya ee +Эстонія ee +Естония ee +Estonija ee +Estònia ee +Estonsko ee +Estland ee +Estland ee +Εσθονία ee +Estlando ee +Eesti ee +استونی ee +Eesti ee +Estonie ee +אסטוניה ee +Estonija ee +Észtország ee +Eistland ee +エストニア ee +에스토니아 ee +ເອໂທເນີຍ ee +Estija ee +Igaunija ee +Estonja ee +Estland ee +Estland ee +Estland ee +Estònia ee +Estónia ee +Estônia ee +Эстония ee +Estónsko ee +Estonija ee +Estonija ee +I-Estonia ee +Estland ee +±Í§¼¡É¢Â¡ ee +เอสโธเนีย ee +Estonya ee +Естонія ee +Estoneye ee +爱沙尼亚 ee +愛沙尼亞 ee +Egypt eg +Egipte eg +مصر eg +Misir eg +Эгіпэт eg +Египет eg +Egipat eg +Egipte eg +Egypten eg +Ägypten eg +Αίγυπτος eg +Egiptujo eg +Egipto eg +Egiptus eg +Egypto eg +مصر eg +Egypti eg +Egyptaland eg +Égypte eg +מצרים eg +Egipat eg +Egyiptom eg +Egyptaland eg +Egitto eg +エジプト eg +이집트 eg +ອີຢີບ eg +Egiptas eg +Ēģipte eg +Eġittu eg +Egypte eg +Egepeta eg +Egipt eg +Egipto eg +Egito eg +Egipt eg +Египет eg +Egipt eg +I-Egypt eg +Egypten eg +±¸¢ôÐ eg +อียิปต์ eg +Mısır eg +Єгипет eg +Edjipe eg +埃及 eg +埃及 eg +Igibhithe eg +Western Sahara eh +Западна Сахара eh +Zapadna Sahara eh +Vestsahara eh +Sahara occidental eh +Mendebaldeko Sahara eh +Nyugat-Szahara eh +ພື້ນທີ່ທຳງານ eh +Sahara eh +Západna Sahara eh +Zahodna Sahara eh +Västsahara eh +Західна Сахара eh +西撒哈拉 eh +Eritrea er +Эрытрэя er +Еритрея er +Eritreja er +ແກ້ໄຂແຟ້ມທຳງານ er +Eritreja er +Еритрея er +厄立特里亚 er +Spain es +Spanje es +أسبانيا es +İspaniya es +Гішпанія es +Испания es +Spagn es +Španija es +Espanya es +Španělsko es +Spanien es +Spanien es +Ισπανία es +Hispanio es +España es +Hispaania es +Espainia es +اسپانیا es +Espanja es +Spania es +Espagne es +España es +ספרד es +Španjolska es +Spanyolország es +Spanyol es +Spánn es +Spagna es +スペイン es +스페인 es +ສະເປັນ es +Ispanija es +Spānija es +Spanja es +Spania es +Spanje es +Spania es +Espanha es +Hiszpania es +Espanha es +Espanha es +Spania es +Испания es +Španielsko es +Španija es +Španija es +I-Spain es +Spanien es +ͦÀ¢ý es +สเปน es +İspanya es +Іспанія es +Tây Ban Nha es +Sipagne es +西班牙 es +西班牙 es +Ethiopia et +Этыёпія et +Етиопия et +Etiopija et +Ethiopien et +Etiopía et +Etiopia et +Etiópia et +ເອໂທເນີຍ et +Etiópia et +Etiópia et +Etiopija et +Etiopien et +Ефіопія et +埃塞俄比亚 et +Finland fi +فنلندا fi +Finlandiya fi +Фінляндыя fi +Финландия fi +Finska fi +Finlàndia fi +Finsko fi +Finnland fi +Φινλανδία fi +Finlando fi +Finlandia fi +Soome fi +Finlandia fi +فنلاند fi +Suomi fi +Finnland fi +Finlande fi +Finlandia fi +פינלנד fi +Finska fi +Finnország fi +Finlandia fi +Finnland fi +Finlandia fi +フィンランド fi +핀란드 fi +ຟີນແລນ fi +Suomija fi +Somija fi +Finlandja fi +Finlandia fi +Finlandia fi +Finlândia fi +Finlândia fi +Finlanda fi +Финляндия fi +Fínsko fi +Finska fi +Finska fi +I-Finland fi +À¢ýÄ¡óÐ fi +ฟินแลนด์ fi +Finlandiya fi +Фінляндія fi +Phần Lan fi +Finlande fi +芬兰 fi +芬蘭 fi +Fiji fj +Фіджы fj +Фиджи fj +Fidži fj +Fidzsi fj +ມີດີ fj +Ilhas Fiji fj +Fidži fj +Fidži fj +Фіджі fj +斐济 fj +Falkland Islands (Malvinas) fk +Фолклендски Острови fk +Foklandska ostrva (Malvini) fk +Falkland-øerne fk +Islas Falkland (Malvinas) fk +Falkland Irlak (Malvinak) fk +Falkland-szigetek fk +Ilhas Malvinas fk +Falklandské Ostrovy (Malviny) fk +Falklandski otoki (Malvini) fk +Falklandsöarna fk +福克兰岛 (马尔维纳斯) fk +Micronesia, Federated states of fm +Федэрацыя Мiкранэзіі fm +Микронезия fm +Mikronezija, Federalne države fm +Mikronesien, de forenede stater af fm +Micronesia, Estados federados de fm +Mikronesia, Estatu Federatuak fm +Mikronézia fm +Estados Federados da Micronésia fm +Spjoené štáty Mikronézie fm +Mikronezija, Združene države fm +Mikronesiska federationen fm +密克罗尼西亚联邦 fm +Faroe Islands fo +Фареорски Острови fo +Farska ostrva fo +Færøerne fo +islas Faroe fo +Faroe Irlak fo +Faroe-szigetek fo +ໄອແລນ fo +Ilhas Faroe fo +Ostrovy Faroe fo +Otoki Faroe fo +Färöarna fo +Фарерські острови fo +France fr +Frankryk fr +فرنسا fr +Fransa fr +Францыя fr +Франция fr +Frañs fr +Francuska fr +França fr +Francie fr +Frankrig fr +Frankreich fr +Γαλλία fr +Francio fr +Francia fr +Prantsusmaa fr +Frantzia fr +فرانسه fr +Ranska fr +Frakland fr +Francia fr +צרפת fr +Francuska fr +Franciaország fr +Prancis fr +Frakkland fr +Francia fr +フランス fr +프랑스 fr +ຝຣັ່ງ fr +Prancūzija fr +Francija fr +Franza fr +Frankrike fr +Frankrijk fr +Frankrike fr +Fora fr +França fr +Francja fr +França fr +França fr +Franţa fr +Франция fr +Francúzsko fr +Francija fr +Francuska fr +I-France fr +Frankrike fr +À¢Ã¡ýÍ fr +ฝรั่งเศส fr +Fransa fr +Франція fr +Fura fr +Pháp fr +Fransi fr +法国 fr +法國 fr +Gabon ga +Габон ga +Габон ga +Gabón ga +ແກລ່ງນ ga +Gabão ga +Габон ga +加蓬 ga +United Kingdom gb +Vereenigde Koninkryk gb +المملكة المتحدة gb +Birləşmiş Krallıq gb +Злучанае Каралеўства gb +Великобритания gb +Rouantelezh Unanet gb +Velika Britanija gb +Regne Unit gb +Spojené království gb +Storbritannien gb +Großbritannien gb +Ηνωμένο Βασίλειο gb +Britio gb +Reino Unido gb +Ühendatud Kuningriigid gb +Erreinu Batua gb +بریتانیا gb +Iso-Britannia gb +Stórabretland gb +Royaume Uni gb +Reino Unido gb +בריטניה gb +Ujedinjeno Kraljevstvo gb +Egyesült Királyság gb +Inggris gb +Stóra Bretland gb +Regno Unito gb +イギリス gb +영국 gb +ສະຫະລາດສະອານາຈັກ gb +Jungtinė Karalystė gb +Apvienotā Karaliste gb +Renju Unit gb +Storbritannia gb +Verenigd Koninkrijk gb +Storbritannia gb +Regne Unit gb +Wielka Brytania gb +Reino Unido gb +Reino Unido gb +Anglia gb +Великобритания gb +Anglicko gb +Združeno kraljestvo gb +Velika Britanija gb +I-United Kingdom gb +Storbritannien gb +³ì¸¢Â áÂõ gb +สหราชอาณาจักร gb +Birleşik Krallık gb +Великобританія gb +Anh gb +United Kingdom gb +联合王国 gb +聯合王國 gb +United Kingdom gb +Grenada gd +غرينادا gd +Qrenada gd +Грэнада gd +Гренада gd +Granada gd +Γρενάδα gd +Grenado gd +Granada gd +گرانادا gd +Grenade gd +Granada gd +גרנדה gd +Grænhöfðaeyjar gd +Granada gd +グラナダ gd +그러네이다 gd +ເກນາດາ gd +Grenāda gd +Granada gd +Granada gd +Granada gd +Гренада gd +I-Grenada gd +¸¢¦Ãɼ¡ gd +เกรนาดา gd +Гренада gd +格林纳达 gd +格瑞那達 gd +Georgia ge +Грузія ge +Грузия ge +Gruzija ge +Georgien ge +Grúzia ge +ເຊີເບີຍ ge +Geórgia ge +Gruzija ge +Georgien ge +Грузія ge +格鲁吉亚 ge +Ghana gh +غانا gh +Гана gh +Гана gh +Gana gh +Γκάνα gh +غنا gh +גאנה gh +ガーナ gh +ຈີນ gh +Gana gh +Gana gh +Gana gh +Гана gh +Gana gh +I-Ghana gh +¸¡É¡ gh +Гана gh +加纳 gh +迦納 gh +Gibraltar gi +Гибралтар gi +Gibraltár gi +ມອລຕາ gi +Гібралтар gi +直布罗陀 gi +Gambia gm +Гамбія gm +Гамбия gm +Gambija gm +ແກມມາ gm +Gâmbia gm +Gambija gm +Гамбія gm +冈比亚 gm +Guinea gn +Гвінэя gn +Гвинея gn +Gvineja gn +ເຖາວັນ gn +Guiné gn +Gvineja gn +Гвінея gn +几内亚 gn +Guadeloupe gp +Гвадалупа gp +Gvadalupe gp +Guadalupe gp +ເດີລຸກ gp +Guadalupe gp +Гваделупа gp +瓜德罗普岛 gp +Equatorial Guinea gq +Экватарыяльная Гвінэя gq +Екваториялна Гвинея gq +Ekvatorijalna Gvineja gq +Ækvatorial Guinea gq +Guinea equatorial gq +Ginea Ekuatoriala gq +Egyenlítői Guinea gq +ການສອນ gq +Guiné Equatorial gq +Rovníkova Guinea gq +Ekvatorialna Gvineja gq +Ekvatorialguinea gq +Екваторіальна Гвінея gq +赤道几内亚 gq +Greece gr +Griekeland gr +اليونان gr +Yunanıstan gr +Грэцыя gr +Гърция gr +Gres gr +Grčka gr +Grècia gr +Řecko gr +Grækenland gr +Griechenland gr +Ελλάδα gr +Grekujo gr +Grecia gr +Kreeka gr +Grezia gr +یونان gr +Kreikka gr +Grikkaland gr +Grèce gr +Grecia gr +יוון gr +Grčka gr +Görögország gr +Grikkland gr +Grecia gr +ギリシャ gr +그리스 gr +ກີຊ gr +Graikija gr +Grieķija gr +Greċja gr +Hellas gr +Griekenland gr +Hellas gr +Grèça gr +Grecja gr +Grécia gr +Grécia gr +Grecia gr +Греция gr +Grécko gr +Grčija gr +Grčka gr +I-Greece gr +Grekland gr +¸¢Ã£Í gr +กรีซ gr +Yunanistan gr +Греція gr +Hy Lạp gr +Grece gr +希腊 gr +希臘 gr +Guatemala gt +Gautemala gt +غواتيمالا gt +Quatemala gt +Гватэмала gt +Гватемала gt +Gvatemala gt +Γουατεμάλα gt +Gvatemalo gt +Guatemaala gt +گواتمالا gt +גואטמלה gt +Gvatemala gt +カタロニア gt +과테말라 gt +ກັວເຕມາລາ gt +Gvatemala gt +Gvatemala gt +Gwatemala gt +Gwatemala gt +Гватемала gt +Gvatemala gt +Gvatemala gt +I-Guatemala gt +ÌÅ¡ò¾Á¡Ä¡ gt +กัวเตมาลา gt +Гватемала gt +Gwatemala gt +瓜地马拉 gt +瓜地馬拉 gt +Guam gu +Гуам gu +ແກມມາ gu +Гуам gu +关岛 gu +Guinea-Bissau gw +Гвінэя-Бісаў gw +Гвинея-Бисау gw +Gvineja-Bisau gw +Ginea-Bissau gw +Bissau-Guinea gw +ລັດເຊີຍ gw +Guiné-Bissau gw +Гвінея-Біссау gw +几内亚比绍 gw +Guyana gy +Гвіяна gy +Гуана gy +Gvajana gy +ຈີນ gy +Guiana gy +Gvajana gy +Гаяна gy +圭亚那 gy +Hong Kong hk +Ганконг hk +Хонг Конг hk +Hongkong hk +ບໍ່ຮູ້ຈັກ hk +Гонконг hk +香港 hk +Honduras hn +هندوراس hn +Гандурас hn +Хондурас hn +Hondures hn +Ονδούρα hn +Honduraso hn +Honduuras hn +هندوراس hn +הונדורס hn +ホンデュラス hn +온두라스 hn +ຫອນດູລັດ hn +Hondūras hn +Hondurasa hn +Ħonduras hn +Hondures hn +Гондурас hn +I-Honduras hn +¬ñÎÃ¡Í hn +ฮอนดูรัส hn +Гондурас hn +洪都拉斯 hn +宏都拉斯 hn +Croatia hr +Kroatië hr +كرواتيا hr +Xırvatıstan hr +Харватыя hr +Хърватска hr +Kroatia hr +Hrvatska hr +Croàcia hr +Chorvatsko hr +Kroatien hr +Kroatien hr +Κροατία hr +Kroatio hr +Croacia hr +Horvaatia hr +Kroazia hr +کرواسی hr +Kroatia hr +Kroatia hr +Croatie hr +Croacia hr +קרואטיה hr +Hrvatska hr +Horvátország hr +Kroasia hr +KróatÃa hr +Croazia hr +クロアチア hr +크로아티아 hr +ໂຄເອເທີຍ hr +Kroatija hr +Horvātija hr +Kroazja hr +Kroatia hr +Kroatië hr +Kroatia hr +Croacia hr +Chorwacja hr +Croácia hr +Croácia hr +Croaţia hr +Хорватия hr +Chorvátsko hr +Hrvaška hr +Hrvatska hr +I-Croatia hr +Kroatien hr +̦á§Åº¢Â¡ hr +โครเอเธีย hr +Hırvatistan hr +Хорватія hr +Crowåceye hr +克罗地亚 hr +克羅埃西亞 hr +Haiti ht +Гаіці ht +Хаити ht +Haití ht +ວາດຮູບ - K ht +Гаїті ht +海地岛 ht +Hungary hu +Hongarye hu +هنغاريا hu +Macarıstan hu +Вугоршчына hu +Унгария hu +Hungaria hu +Mađarska hu +Hongria hu +Maďarsko hu +Ungarn hu +Ungarn hu +Ουγγαρία hu +Hungario hu +Hungría hu +Ungari hu +Hungaria hu +مجارستان hu +Unkari hu +Ungarn hu +Hongrie hu +Hungría hu +הונגריה hu +Mađjarska hu +Magyarország hu +Hungaria hu +Ungverjaland hu +Ungheria hu +ハンガリー hu +헝가리 hu +ຫັງກາລີ hu +Vengrija hu +Ungārija hu +Ungerija hu +Ungarn hu +Hongarije hu +Ungarn hu +Hongria hu +Węgry hu +Hungria hu +Hungria hu +Ungaria hu +Венгрия hu +Maďarsko hu +Madžarska hu +Mađarska hu +I-Hungary hu +Ungern hu +¬í§¸Ã¢ hu +ฮังการี hu +Macaristan hu +Угорщина hu +Hongreye hu +匈牙利 hu +匈牙利 hu +Indonesia id +Indonesië id +إندونيسيا id +İndoneziya id +Інданэзія id +Индонезия id +Indonezija id +Indonèsia id +Indonésie id +Indonesien id +Indonesien id +Ινδονησία id +Indonezio id +Indoneesia id +اندونزی id +Indonésie id +אינדונזיה id +Indonezija id +Indonézia id +IndónesÃa id +インドネシア id +인도네시아 id +ອີຍໂດນີເຊີຍ id +Indonezija id +Indonēzija id +Indoneżja id +Indonesië id +Indonezja id +Indonésia id +Indonésia id +Indonezia id +Индонезия id +Indonézia id +Indonezija id +I-Indonesia id +Indonesien id +󧾡ɣº¢Â¡ id +อินโดนีเซีย id +İndonezya id +Індонезія id +Indoneseye id +印度尼西亚 id +印尼 id +Ireland ie +Ierland ie +أيرلندا ie +İrlandiya ie +Ірляндыя ie +Ирландия ie +Iwerzhon ie +Irska ie +Irlanda ie +Irsko ie +Irland ie +Irland ie +Ιρλανδία ie +Islando ie +Irlanda ie +Island ie +Irlanda ie +ایرلند ie +Irlanti ie +Írland ie +Irlande ie +Irlanda ie +אירלנד ie +Irska ie +Írország ie +Irlandia ie +Ãrland ie +Irlanda ie +アイスランド ie +아일랜드 ie +ໄອແລນ ie +Airija ie +Īrija ie +Irlanda ie +Irland ie +Ierland ie +Irland ie +Irlanda ie +Irlandia ie +Irlanda ie +Irlanda ie +Irlanda ie +Ирландия ie +Írsko ie +Irska ie +Irska ie +I-Ireland ie +Irland ie +«Â÷Ä¡óÐ ie +ไอร์แลนด์ ie +İrlanda ie +Ірландія ie +Irlande ie +爱尔兰 ie +愛爾蘭 ie +Israel il +اسرائيل il +İzrail il +Ізраіль il +Израел il +Izrael il +Izrael il +Ισραήλ il +Israelo il +Iisrael il +اسراییل il +Ísrael il +Israël il +ישראל il +Izrael il +Izrael il +Ãsrael il +Israele il +イスラエル il +이스라엘 il +ອິດສະລະເອລ il +Izraelis il +Izraēla il +Iżrael il +Izrael il +Израиль il +Izrael il +Izrael il +Izrael il +I-Israel il +Í§Ãø il +อิสราเอล il +İsrail il +Ізраїль il +Israyel il +USirayeli il +以色列 il +以色列 il +India in +Indië in +الهند in +Hindistan in +Індыя in +Индия in +Indija in +Índia in +Indie in +Indien in +Indien in +Ινδία in +Hindujo in +هندوستان in +Intia in +Inde in +הודו in +Indija in +Indland in +インド in +인도 in +ອິນເດີຍ in +Indija in +Indija in +Indja in +Indie in +Índia in +Índia in +Индия in +Indija in +I-India in +Indien in +ó¾¢Â¡ in +อินเดีย in +Hindistan in +Індія in +Inde in +印度 in +印度 in +Endiya in +Iraq iq +Irak iq +العراق iq +İraq iq +Ірак iq +Ирак iq +Irak iq +Irák iq +Irak iq +Irak iq +Ιράκ iq +Irako iq +Irak iq +Iraak iq +عراق iq +Irak iq +Irak iq +Irak iq +עירק iq +Irak iq +Irak iq +Ãrak iq +Irak iq +イラク iq +이라크 iq +ອີລັກ iq +Irakas iq +Irāka iq +Irak iq +Irak iq +Irak iq +Irak iq +Iraque iq +Iraque iq +Irak iq +Ирак iq +Irák iq +Irak iq +I-Iraq iq +Irak iq +®Ã¡ì iq +อิรัค iq +Irak iq +Ірак iq +Irak iq +伊拉克 iq +伊拉克 iq +Iran ir +أيران ir +Іран ir +Иран ir +Írán ir +Ιράν ir +Iraan ir +ایران ir +אירן ir +Irán ir +イラン ir +이란 ir +ອີລັກ ir +Iranas ir +Irão ir +Irã ir +Иран ir +Irán ir +I-Iran ir +®Ã¡ý ir +İran ir +Іран ir +伊朗 ir +伊朗 ir +Iceland is +Ysland is +أيسلندا is +İslandiya is +Ісьляндыя is +Исландия is +Island is +Island is +Islàndia is +Island is +Island is +Island is +Ισλανδία is +Islando is +Islandia is +Island is +Islandia is +ایسلند is +Islanti is +Ísland is +Islande is +Islandia is +איסלנד is +Island is +Izland is +Islandia is +Ãsland is +Islanda is +アイスランド is +아이슬란드 is +ໄອຊແລນ is +Islandija is +Islande is +Islandja is +Island is +IJsland is +Island is +Islandia is +Islandia is +Islândia is +Islândia is +Islanda is +Исландия is +Island is +Islandija is +Island is +I-Iceland is +Island is +³ÍÄ¡óÐ is +ไอซ์แลนด์ is +İzlanda is +Ісландія is +Izlande is +冰岛 is +冰島 is +Icelandi is +Italy it +Italië it +ايطاليا it +İtalyia it +Італія it +Италия it +Italia it +Italija it +Itàlia it +Itálie it +Italien it +Italien it +Ιταλία it +Italio it +Italia it +Itaalia it +Italia it +ایتالیا it +Italia it +Italia it +Italie it +Italia it +איטליה it +Italija it +Olaszország it +Italia it +ÃtalÃa it +Italia it +イタリア it +이탈리아 it +ອີຕາລີ it +Italija it +Itālija it +Italja it +Italia it +Italië it +Italia it +Italia it +Włochy it +Itália it +Itália it +Italia it +Италия it +Taliansko it +Italija it +Italija it +I-Italy it +Italien it +ò¾¡Ä¢ it +อิตาลี it +İtalya it +Італія it +Itåleye it +Ithali it +意大利 it +義大利 it +Jamaica jm +Jamaika jm +جامايكا jm +Yamayka jm +Ямайка jm +Ямайка jm +Jamaika jm +Jamajka jm +Jamajka jm +Jamaika jm +Τζαμάικα jm +Ĵamaiko jm +Jamaika jm +Jamaika jm +جاماییکا jm +Jamaika jm +Jamaïque jm +Xamaica jm +ג'מייקה jm +Jamajka jm +Jamaika jm +Jamaika jm +Giamaica jm +ジャマイカ jm +자메이카 jm +ຈາໄມກາ jm +Jamaika jm +Jamaika jm +Ġamajka jm +Jamajka jm +Ямайка jm +Jamajka jm +Jamajka jm +Jamajka jm +I-Jamaica jm +º¦Áö측 jm +จาไมกา jm +Jamaika jm +Ямайка jm +Djamayike jm +牙买加 jm +牙買加 jm +Jordan jo +Jordaan jo +الأردن jo +İordaniya jo +Ярданія jo +Йордания jo +Jordania jo +Jordán jo +Jordanien jo +Ιορδανία jo +Jordanio jo +Jordania jo +اردن jo +Jordania jo +Jordanie jo +ירדן jo +Jordánia jo +JórdanÃa jo +Giordania jo +ヨルダン jo +요르단 jo +ຈໍແດນ jo +Jordanija jo +Jordāna jo +Ġordan jo +Jordanië jo +Jordania jo +Jordânia jo +Jordânia jo +Iordania jo +Иордания jo +Jordánsko jo +Jordanija jo +I-Jordan jo +Jordanien jo +§Â¡÷¾¡ý jo +จอร์แดน jo +Ürdün jo +Йорданія jo +Djordaneye jo +约旦 jo +約旦 jo +Ijolidani jo +Japan jp +اليابان jp +Yaponiya jp +Японія jp +Япония jp +Japó jp +Japonsko jp +Ιαπωνία jp +Japanio jp +Japón jp +Jaapan jp +Japonia jp +ژاپن jp +Japani jp +Japon jp +Xapón jp +יפן jp +Japán jp +Jepang jp +Giappone jp +日本 jp +일본 jp +ຍີ່ປຸ່ນ jp +Japonija jp +Japāna jp +Ġappun jp +Japon jp +Japonia jp +Japão jp +Japão jp +Japonia jp +Япония jp +Japonsko jp +Japonska jp +I-Japan jp +ºôÀ¡ý jp +ญี่ปุ่น jp +Japonya jp +Японія jp +Nhật bản jp +Djapon jp +日本 jp +日本 jp +Kenya ke +Кенія ke +Кения ke +Kenija ke +Kenia ke +ເວນດາ ke +Quênia ke +Keňa ke +Kenija ke +Кенія ke +肯尼亚 ke +Kyrgyzstan kg +Кыргызстан kg +Киргистан kg +Kirgistan kg +Kirgizistan kg +Kyrgyzstán kg +Kirgizisztán kg +ຄສິຕັລ kg +Kirgizstan kg +Kirgizistan kg +Киргизстан kg +吉尔吉斯坦 kg +Cambodia kh +Камбоджа kh +Камбоджа kh +Kambođa kh +Kambodzsa kh +ໂຄລຳເບີຍ kh +Cambodja kh +Kambodža kh +Kambodža kh +Kambodja kh +Камбоджа kh +柬埔寨 kh +Kiribati ki +Кiрыбацi ki +Кирибати ki +ແຟຄທັລ - K ki +Кірібаті ki +基里巴斯 ki +Comoros km +Каморы km +Коморски km +Komori km +Comorerne km +ສີ km +Komori km +Komorerna km +Комори km +科摩罗群岛 km +St. Kitts and Nevis kn +St. Kitts en Nevis kn +سانت كيتس و نيفيس kn +St. Kitts və Nevis kn +Св. Кристоф и Невис kn +S. Kitts ha Nevis kn +St. Kitts i Nevis kn +Sv. Kitts a Nevis kn +St. Kitts-Nevis kn +St. Kitts und Nevis kn +St. Kitts και Nevis kn +St. Kitts kaj Nevis kn +St. Kitts y Nevis kn +St. Kitts ja Nevis kn +St. Kitts eta Nevis kn +سن کیتس و نویس kn +St. Kitts ja Nevis kn +St Kitts et Nevis kn +Saint Kitts e Nevis kn +סנט קיטס ונביס kn +St. Kitts és Nevis kn +St. Kitts dan Nevis kn +Ss. Kitts e Nevis kn +セントキッツネヴィス kn +세인트 키츠 네비스 kn +Šv. Kitts ir Nevis kn +St. Kitts un Nevis kn +St. Kitts u Nevis kn +St. Kitts og Nevis kn +St. Kitts en Nevis kn +St. Kitts og Nevis kn +St. Kitts le Nevis kn +St. Kitts e Nevis kn +St. Kitts e Nevis kn +St Kitts e Nevis kn +Sf. Kitts şi Nevis kn +о. Св. Кристофа и Невиса kn +St. Kitts a Nevis kn +St. Kitts in Nevis kn +St. Kitts i Nevis kn +I-St. Kitts and Nevis kn +St. Kitts och Nevis kn +¦ºÂ¢ý𠸢ðÍ & ¦¿Å¢Í kn +St. Kitts ve Nevis kn +Федерація Сент-Кітс і Невіс kn +St. Kitts na Nevis kn +St. Kitts neNevis kn +圣基特和里维斯 kn +聖克理斯多福及尼維斯 kn +St. Kitts kanye no-Nevis kn +North Korea kp +Noord Korea kp +كوريا الشمالية kp +Şimali Koreya kp +Паўночная Карэя kp +Северна Корея kp +Norzh-Korea kp +Sjeverna Koreja kp +Corea del Nord kp +Severní Korea kp +Nordkorea kp +Nord-Korea kp +Βόρεια Κορέα kp +Nordkoreo kp +Corea del Norte kp +Põhja-Korea kp +Ipar Korea kp +کره شمالی kp +Pohjois-Korea kp +Norðurkorea kp +Corée du nord kp +Corea do Norte kp +צפון קוריאה kp +Sjeverna Koreja kp +Észak-Korea kp +Korea Utara kp +Kórea - Norðurkórea kp +Corea del Nord kp +北朝鮮 kp +조선민주주의 인민공화국 kp +ເກົາລີເຫນືອ kp +Šiaurės Korėja kp +ZiemeļKoreja kp +Korea ta' Fuq kp +Nord-Korea kp +Noord-Korea kp +Nord-Korea kp +Lebowa la Korea kp +Corea dèu Nord kp +Korea Północna kp +Coreia do Norte kp +Coréia do Norte kp +Coreea de Nord kp +Северная Корея kp +severná Kórea kp +Severna Koreja kp +Severna Koreja kp +I-North Korea kp +Nordkorea kp +ż ¦¸¡Ã¢Â¡ kp +เกาหลีเหนือ kp +Kuzey Kore kp +Північна Корея kp +Devhula ha Korea kp +Bắc Triều Tiên kp +Bijhe Coreye kp +Umntla Korea kp +朝鲜 kp +北韓 kp +Enyakatho ne-Korea kp +South Korea kr +Suid Korea kr +كوريا الجنوبية kr +Cənubi Koreya kr +Паўднёвая Карэя kr +Южна Корея kr +Su-Korea kr +Južna Koreja kr +Corea del Sud kr +Jižní Korea kr +Sydkorea kr +Süd-Korea kr +Νότια Κορέα kr +Sudkoreo kr +Corea del Sur kr +Lõuna-Korea kr +Hego Korea kr +کره جنوبی kr +Etelä-Korea kr +Suðurkorea kr +Corée du sud kr +Corea do Sur kr +דרום קוריאה kr +Južna Koreja kr +Dél-Korea kr +Korea Selatan kr +Kórea - Suðurkórea kr +Corea del Sud kr +韓国 kr +대한민국 kr +ເກົາລີໃຕ້ kr +Pietų Korėja kr +DievidKoreja kr +Korea t'Isfel kr +Sør-Korea kr +Zuid-Korea kr +Sør-Korea kr +Borwa bja Korea kr +Corea dèu Sud kr +Korea Południowa kr +Coreia do Sul kr +Coréia do Sul kr +Coreea de Sud kr +Южная Корея kr +Južná Kórea kr +Južna Koreja kr +Južna Koreja kr +I-South Korea kr +Sydkorea kr +¦¾ý ¦¸¡Ã¢Â¡ kr +เกาหลีใต้ kr +Güney Kore kr +Південна Корея kr +Korea tshipembe kr +Hàn Quốc kr +Nonne Coreye kr +Umzantsi Korea kr +韩国 kr +南韓 kr +Emzansi Korea kr +Kuwait kw +Kuwaït kw +الكويت kw +Кувэйт kw +Кувейт kw +Kuvajt kw +Kuvajt kw +Κουβέιτ kw +Kuveit kw +کویت kw +Kuvait kw +Kowait kw +כווית kw +Kuvajt kw +Kuvait kw +クェート kw +쿠웨이트 kw +ແຕ້ມຮູບ- K kw +Kuveitas kw +Koeweit kw +Koweit kw +Kuveit kw +Кувейт kw +Kuvajt kw +Kuvajt kw +I-Kuwait kw +̨Åò kw +KКувейт kw +科威特 kw +科威特 kw +Cayman Islands ky +Кайманови Острови ky +Kajmanska ostrva ky +Cayman-øerne ky +Islas Caimán ky +Kaiman Irlak ky +Kajmán-szigetek ky +ຄາຕາລັນ ky +Ilhas Cayman ky +Kajmanske Ostrovy ky +Kajmanski otoki ky +Caymanöarna ky +Кайманські острови ky +开曼群岛 ky +Kazakhstan kz +Казахстан kz +Казахстан kz +Kazahstan kz +Kazakhstán kz +Kazahsztán kz +ແກແລກຕິກ - K kz +Kazaquistão kz +Kazachstan kz +Kazahstan kz +Kazakstan kz +Казахстан kz +哈萨克斯坦 kz +Laos la +Лаос la +Лаос la +Laosz la +ລາວ la +老挝 la +Lebanon lb +Libanon lb +لبنان lb +Ліван lb +Ливан lb +Liban lb +Libanon lb +Libanon lb +Libanon lb +Λίβανος lb +Lebanono lb +Líbano lb +Liibanon lb +لبنان lb +Libanon lb +Libanon lb +Liban lb +לבנון lb +Libanon lb +Libanon lb +Libano lb +レバノン lb +레바논 lb +ເດນ່ງນ lb +Libanas lb +Libanu lb +Libanon lb +Libanon lb +Libanon lb +Liban lb +Líbano lb +Líbano lb +Liban lb +Ливан lb +Libanon lb +Libanon lb +I-Lebanon lb +Libanon lb +¦ÄÀÉ¡ý lb +Ліван lb +Liban lb +黎巴嫩 lb +黎巴嫩 lb +St. Lucia lc +سانت لوسيا lc +Св. Люсиа lc +S. Lucia lc +Svatá Lucie lc +Σάντα Λουτσία lc +St. Lucio lc +Santa Lucía lc +سن لوسیا lc +Sankta Lusia lc +Sainte Lucie lc +Santa Lucía lc +סנטה לוסיה lc +Santa Lucia lc +セントルキア lc +세인트 루시아 lc +ເຊັນລູເຊີຍ lc +Šv Liucija lc +Sv. Lūcija lc +St. Luċija lc +Santa Lúcia lc +Santa Lúcia lc +Sf. Lucia lc +о. Св. Люсии lc +Sv. Júlia lc +Sv. Lucija lc +I-St. Lucia lc +¦ºýð æº¢Â¡ lc +เซนต์ลูเซีย lc +Санта Лучія lc +圣路西亚 lc +聖露西亞 lc +Liechtenstein li +Ліхтэнштэйн li +Лихтенщайн li +Lihtenštajn li +Liechtestein li +ຟ້າແມບ li +列支敦士登 li +Sri Lanka lk +Шры-Ланка lk +Шри Ланка lk +Šri Lanka lk +ເຊີເບີຍ lk +Šri Lanka lk +斯里兰卡 lk +Liberia lr +Лібэрыя lr +Либеря lr +Liberija lr +Libéria lr +ລິຊາ lr +Libéria lr +Lýbia lr +Liberija lr +利比里亚 lr +Lesotho ls +Лесота ls +Лесото ls +Lesoto ls +Lesoto ls +ທົດສອບ ls +Lesoto ls +莱索托 ls +Lithuania lt +Lithuanië lt +ليتوانيا lt +Litvaniya lt +Літва lt +Литва lt +Litvanija lt +Lituània lt +Litva lt +Litauen lt +Litauen lt +Λιθουανία lt +Litovio lt +Lituania lt +Leedu lt +Lituania lt +لیتوانی lt +Liettua lt +Lituanie lt +ליטא lt +Litva lt +Litvánia lt +Litháenska lt +Lituania lt +リトアニア lt +리 투아니아 lt +ລິທົ່ວເນີຍ lt +Lietuva lt +Lietuva lt +Litwanja lt +Litauen lt +Litouwen lt +Litauen lt +Litwa lt +Lituânia lt +Lituânia lt +Lituania lt +Литва lt +Litva lt +Litva lt +Litvanija lt +I-Lithuania lt +Litauen lt +Ä¢òЧÅɢ¡ lt +ลิธัวเนีย lt +Litvanya lt +Литва lt +立陶宛 lt +立陶宛 lt +Luxembourg lu +Luxenburg lu +لوكسمبورغ lu +Lüksemburq lu +Люксэмбург lu +Люксембург lu +Luksemburg lu +Luxemburg lu +Lucembursko lu +Luxemburg lu +Λουξεμβούργο lu +Luksemburgo lu +Luxemburgo lu +Luksemburg lu +Luxemburg lu +لوگزامبورگ lu +Luxemburg lu +Luksemborg lu +לוקסמבורג lu +Luksemburg lu +Luxemburg lu +Lúxemborg lu +Lussemburgo lu +ルクセンブルグ lu +룩셈부르크 lu +ລັກແຊມເບີກ lu +Liuksemburgas lu +Luksemburga lu +Lussemburgu lu +Luxemburg lu +Luksemburg lu +Luxemburgo lu +Luxemburgo lu +Luxemburg lu +Люксембург lu +Luxemburg lu +Luksemburg lu +Luksemburg lu +I-Luxembourg lu +Luxemburg lu +Äìºõ§À¡÷ì lu +ลักเซมเบอร์ก lu +Lüksemburg lu +Люксембург lu +Lucsimbork lu +卢森堡 lu +盧森堡 lu +Latvia lv +لاتفيا lv +Latviya lv +Латвія lv +Латвия lv +Latvija lv +Lotyšsko lv +Letland lv +Lettland lv +Λιθουανία lv +Latvio lv +Letonia lv +Läti lv +لاتویا lv +Lettonie lv +לטביה lv +Latvija lv +Lettország lv +Léttland lv +Lettonia lv +ラトビア lv +라트비아 lv +ລັດເວີຍ lv +Latvija lv +Latvija lv +Latvja lv +Letland lv +Łotwa lv +Letónia lv +Латвия lv +Lotyšsko lv +Latvija lv +Latvija lv +I-Latvia lv +Lettland lv +ÄðŢ¡ lv +ลัธเวีย lv +Litvanya lv +Латвія lv +Lativia lv +拉脱维亚 lv +拉脫維亞 lv +Libya ly +Libië ly +ليبيا ly +Лівія ly +Либия ly +Libija ly +Líbia ly +Lýbie ly +Libyen ly +Libyen ly +Λιβύη ly +Libia ly +Liibüa ly +Libia ly +لیبی ly +Lybie ly +לוב ly +Líbia ly +Libia ly +リビア ly +ລິຊາ ly +Libija ly +Libië ly +Libia ly +Líbia ly +Líbia ly +Ливия ly +Lýbia ly +Libija ly +I-Libya ly +Libyen ly +Ä¢À¢Â¡ ly +Лівія ly +利比亚 ly +利比亞 ly +Morocco ma +Morokko ma +المغرب ma +Марока ma +Мароко ma +Maroko ma +Marroc ma +Maroko ma +Marokko ma +Marokko ma +Μαρόκο ma +Moroko ma +Marruecos ma +Maroko ma +Maroko ma +مراکش ma +Marokko ma +Marokko ma +Maroc ma +מרוקו ma +Maroko ma +Marokkó ma +Marocco ma +モロッコ ma +모로코 ma +ເມົາລິ ma +Marokas ma +Marokk ma +Marokko ma +Marokko ma +Marokko ma +Maroko ma +Marrocos ma +Marrocos ma +Maroc ma +Марокко ma +Maroko ma +Maroko ma +I-Morocco ma +Marocko ma +§Á¡Ã¡§¸¡ ma +Марокко ma +Marok ma +摩洛哥 ma +摩洛哥 ma +Monaco mc +Манака mc +Монако mc +Monako mc +Mónaco mc +ເມົາລິ mc +Mônaco mc +Monako mc +Monako mc +摩纳哥 mc +Moldova md +Малдова md +Молдова md +Moldavia md +Moldavia md +ສະໂລວັກ md +Moldávsko md +Moldavien md +摩尔多瓦 md +Madagascar mg +Мадагаскар mg +Мадагаскар mg +Madagaskar mg +Madagaszkár mg +ຄາສະບາລ - K mg +Madagaskar mg +Madagaskar mg +Madagaskar mg +马达加斯加 mg +Marshall Islands mh +Маршаллавы астравы mh +Маршалови Острови mh +Maršalova ostrva mh +Marshall-øerne mh +Islas Marshall mh +Marshall Irlak mh +Marshall-szigetek mh +ລາດສະອານາຈັກໄທຍ mh +Ilhas Marshall mh +Maršálove ostrovy mh +Marshallovi otoki mh +Marshallöarna mh +马绍尔群岛 mh +Macedonia mk +Makedoniese mk +مقدونيا mk +Makedonya mk +Македонія mk +Македония mk +Makedonia mk +Makedonija mk +Macedònia mk +Makedonie mk +Makedonien mk +Makedonien mk +Μακεδονία mk +Macedonio mk +Makedoonia mk +Mazedonia mk +مقدونیه mk +Makedonia mk +Macédoine mk +מקדוניה mk +Makedonija mk +Macedónia mk +Masedonia mk +MakedónÃa mk +マケドニア語 mk +마케도니아 mk +ມາເຊໂດເນີຍ mk +Makedonija mk +Maķedonija mk +Maċedonja mk +Makedonia mk +Macedonië mk +Makedonia mk +Macedònian mk +Macedónia mk +Macedônia mk +Македония mk +Macedónsky mk +Makedonija mk +Makedonija mk +I-Macedonia mk +Makedonien mk +Á¡º¢§¼¡É¢Â¡ mk +มาเซโดเนีย mk +Makedonya mk +Македонія mk +Masedonia mk +马其顿 mk +馬其頓 mk +Mali ml +Малі ml +Мали ml +ຈົດຫມາຍ ml +马里 ml +Myanmar mm +М'янма mm +Майнмар mm +Mjanmar mm +Burma mm +Birmania mm +ຕົວຮງກພີື້ນທີ່ທຳງານ - K mm +Mjanmar mm +缅甸 mm +Mongolia mn +Манголія mn +Монголия mn +Mongolija mn +Mongoliet mn +Mongólia mn +ລອກອິນ mn +Mongólia mn +Mongolsko mn +Mongolija mn +Mongoliet mn +蒙古 mn +Macau mo +Макао mo +Makau mo +Macao mo +Makaó mo +ມອລຕາ mo +Makao mo +Macao mo +澳门 mo +Martinique mq +Мартиника mq +Martinik mq +Martinica mq +ເມົາລິ mq +Martinik mq +马提尼克岛 mq +Mauritania mr +Маўрытанія mr +Мавритания mr +Mauritanija mr +Mauretanien mr +Mauritánia mr +ລິທົວເນີຍ mr +Mauritânia mr +Mavretanija mr +Mauretanien mr +毛里塔尼亚 mr +Montserrat ms +Монсерат ms +Monsera ms +ຈໍພາບ ms +蒙特塞拉特岛 ms +Malta mt +مالطة mt +Мальта mt +Малта mt +Μάλτα mt +Malto mt +مالت mt +Malte mt +מלטה mt +Málta mt +マルタ mt +왈타 mt +ມອລຕາ mt +Мальта mt +I-Malta mt +Á¡ø¼¡ mt +มอลตา mt +Мальта mt +Male mt +马耳他 mt +馬爾他 mt +Mauritius mu +Маўрыцы mu +Маурици mu +Mauricijus mu +Mauricio mu +ພາທິຊັ້ນ mu +Maurícius mu +Mavricij mu +毛里求斯 mu +Maldives mv +Мальдывы mv +Малдиви mv +Maldivi mv +Maldiverne mv +Maldivas mv +Maldív-szigetek mv +ມັລດິສ mv +Maldivas mv +Maldiv mv +Maldiverna mv +马尔代夫 mv +Malawi mw +Малаві mw +Малави mw +Malavi mw +ມອລຕາ mw +马拉维 mw +Mexico mx +Meksiko mx +المكسيك mx +Meksika mx +Мэксыка mx +Мексико mx +Mec'hiko mx +Meksiko mx +Mèxic mx +Mexiko mx +Mexiko mx +Μεξικό mx +Meksikujo mx +México mx +Mehhiko mx +Mexiko mx +مکزیک mx +Meksiko mx +Meksiko mx +Mexique mx +México mx +מקסיקו mx +Meksiko mx +Mexikó mx +Meksiko mx +MexÃkó mx +Messico mx +メキシコ mx +멕시코 mx +ເມັກຊີໂກ mx +Meksika mx +Meksika mx +Messiku mx +Mèxic mx +Meksyk mx +México mx +México mx +Mexic mx +Мексика mx +Mexiko mx +Mehika mx +Meksiko mx +I-Mexico mx +¦Á캢§¸¡ mx +เม็กซิโก mx +Meksika mx +Мексика mx +Mê hi cô mx +Mecsike mx +墨西哥 mx +墨西哥 mx +Malaysia my +Малайзыя my +Малайзия my +Malezija my +Malasia my +Malasia my +Malajzia my +ມອລຕາ my +Malásia my +Malajzia my +Malezija my +马来西亚 my +Mozambique mz +Мазамбік mz +Мозамбик mz +Mozambik mz +Mozambik mz +ຫນ່ວຍຄວາມຈຳ mz +Moçambique mz +Mozambik mz +Mozambik mz +Moçambique mz +莫桑比克 mz +Namibia na +Намібія na +Намибия na +Namibija na +Namíbia na +ຈາໄມກາ na +Namíbia na +Namíbia na +Namibija na +纳米比亚 na +New Caledonia nc +Нова Каледония nc +Nova Kaledonija nc +Ny Caledonien nc +Nueva Caledonia nc +Kaledonia Berria nc +Új-Kaledónia nc +ມາເຊໂດເນີຍ nc +Nova Caledônia nc +Nová Kaledónia nc +Nova Kaledonija nc +Nya Caledonien nc +新喀里多尼亚 nc +Niger ne +Нігер ne +Нигер ne +ຕົວຮງກພື້ນທີ່ທຳງານ ne +Nigéria ne +Nigéria ne +尼日尔 ne +Norfolk Island nf +Остров Норфолк nf +Norfolk ostrvo nf +Norfolk-øerne (Australien) nf +Isla Norfolk nf +Norfok Irla nf +Norfolk-szigetek nf +ໂປແລນ nf +Ilhas Norfolk nf +Ostrov Norfolk nf +Otok Norfolk nf +Norfolkön nf +诺福克岛 nf +Nigeria ng +Нігерыя ng +Нигерия ng +Nigerija ng +Nigéria ng +ບັນແກເລີຍ ng +Nigéria ng +Nigéria ng +Nigerija ng +尼日利亚 ng +Nicaragua ni +Nikaragua ni +نيكاراغوا ni +Нікарагуа ni +Никарагуа ni +Nikaragva ni +Nikaragua ni +Νικαράγουα ni +Nikaraagua ni +نیکاراگویه ni +Nikaragua ni +Nikaragua ni +ניקרגווה ni +ニカラグア ni +니카라과 ni +ປາລາກກວຍ ni +Nikaragua ni +Nikaragwa ni +Nikaragua ni +Nicarágua ni +Nicarágua ni +Никарагуа ni +Nikaragua ni +Nikaragva ni +I-Nicaragua ni +¿¢¸Ã¡Ì§Å ni +Nikaragua ni +Нікарагуа ni +尼加拉瓜 ni +尼加拉瓜 ni +Netherlands nl +Nederland nl +هولندا nl +Hollandiya nl +Галяндыя nl +Холандия nl +Izelvroioù nl +Nizozemska nl +Holanda nl +Nizozemí nl +Holland nl +Niederlande nl +Κάτω Χώρες nl +Nederlando nl +Países Bajos nl +Holland nl +Holanda nl +هلند nl +Alankomaat nl +Háland nl +Pays bas nl +Países Baixos nl +הולנד nl +Nizozemska nl +Hollandia nl +Belanda nl +Holland nl +Paesi Bassi nl +オランダ nl +네덜란드 nl +ເນເທີແລນ์ nl +Olandija nl +Nīderlande nl +Nederland nl +Nederland nl +Nederland nl +Holanda nl +Holandia nl +Países Baixos nl +Holanda nl +Olanda nl +Нидерланды nl +Holandsko nl +Nizozemska nl +Holandija nl +I-Netherlands nl +Nederländerna nl +¦¿¾÷Ä¡óÐ nl +เนเธอร์แลนด์ nl +Hollanda nl +Голландія nl +Hà Lan nl +荷兰 nl +荷蘭 nl +Norway no +Noorweë no +النرويج no +Norveç no +Нарвэгія no +Норвегия no +Norvegia no +Norveška no +Noruega no +Norsko no +Norge no +Norwegen no +Νορβηγία no +Norvegio no +Noruega no +Norra no +Norvegia no +نروژ no +Norja no +Norra no +Norvège no +Noruega no +נורבגיה no +Norveška no +Norvégia no +Norwegia no +Noregur no +Norvegia no +ノルウェー no +노르웨이 no +ນໍເວ no +Norvegija no +Norvēģija no +Norveġja no +Norge no +Noorwegen no +Noreg no +Noruega no +Norwegia no +Noruega no +Noruega no +Norvegia no +Норвегия no +Nórsko no +Norveška no +Norveška no +I-Norway no +Norge no +¿¡÷§Å no +นอร์เวย์ no +Norveç no +Норвегія no +Na uy no +挪威 no +挪威 no +Nepal np +Нэпал np +Непал np +Nepál np +ເວນດາ np +尼泊尔 np +Nauru nr +Науру nr +Науру nr +Naurú nr +ປາລາກກວຍ nr +瑙鲁 nr +Niue nu +Ниуе nu +ເນ໊ຕ nu +纽埃岛 nu +New Zealand nz +Nuwe Seeland nz +نيوزيلاندا nz +Yeni Zellandiya nz +Новая Зэляндыя nz +Нова Зеландия nz +Zeland nevez nz +Novi Zeland nz +Nova Zelanda nz +Nový Zéland nz +Neuseeland nz +Νέα Ζηλανδία nz +Novzelando nz +Nueva Zelanda nz +Uus-Meremaa nz +Zelanda Berria nz +زلاندنو nz +Uusi-Seelanti nz +Nýsæland nz +Nouvelle Zélande nz +Nova Celandia nz +ניו זילנד nz +Novi Zeland nz +Új-Zéland nz +Selandia Baru nz +Nýja Sjáland nz +Nuova Zelanda nz +ニュージーランド nz +뉴질랜드 nz +ນີວຊີແລນ nz +Naujoji Zelandija nz +JaunZēlande nz +Nieuw Zeeland nz +Navera Zelanda nz +Nowa Zelandia nz +Nova Zelândia nz +Nova Zelândia nz +Noua Zeelandă nz +Новая Зеландия nz +Nový Zéland nz +Nova Zelandija nz +Novi Zeland nz +I-New Zealand nz +Nya Zeeland nz +¿¢äº¢Ä¡óÐ nz +นิวซีแลนด์ nz +Yeni Zelanda nz +Нова Зеландія nz +Nouve Zelande nz +新西兰 nz +紐西蘭 nz +Oman om +عُمان om +Аман om +Оман om +Omán om +Ομάν om +Omano om +Omán om +Omaan om +عمان om +עומן om +Omán om +オマーン om +오만 om +ເຍີຍລະມັນ om +Omanas om +Omã om +Оман om +Omán om +I-Oman om +µÁý om +Umman om +Оман om + Oman om +阿曼 om +阿曼 om +Panama pa +بنما pa +Панама pa +Панама pa +Panamà pa +Παναμάς pa +Panamo pa +Panamá pa +پاناما pa +Panamá pa +פנמה pa +パナマ pa +파나마 pa +ປານາມາ pa +Panamá pa +Panamá pa +Панама pa +I-Panama pa +ÀÉ¡Á¡ pa +ปานามา pa +Панама pa +巴拿马 pa +巴拿馬 pa +Peru pe +البيرو pe +Пэру pe +Перу pe +Perou pe +Perú pe +Περού pe +Peruo pe +Perú pe +Peruu pe +پرو pe +Pérou pe +Perú pe +פרו pe +Perú pe +Perù pe +ペルー pe +페루 pe +ເປລູ pe +Perū pe +Pero pe +Perú pe +Перу pe +I-Peru pe +¦ÀÕ pe +เปรู pe +Перу pe +Perou pe +秘鲁 pe +秘魯 pe +French Polynesia pf +Француская Палінэзія pf +Френска Полинезия pf +Francuska Polinezija pf +Fransk Polynesien pf +Polinesia francesa pf +Polinesia Frantziarra pf +Francia-Polinézia pf +ຝຣັ່ງເສດ pf +Polinésia Francesa pf +Francúzska Polynézia pf +Francoska Polinezija pf +Franska Polynesien pf +法属波利尼西亚 pf +Papua New Guinea pg +Папуа–Новая Гвінэя pg +Папуа и Нова Гвинея pg +Papua Nova Gvineja pg +Papua Nueva Guinea pg +Papua Ginea Berria pg +Pápua Új-Guinea pg +ເທົາອ່ອນ pg +Nova Guiné Papua pg +Papua Nová Guinea pg +Papua Nova Gvineja pg +Papua Nya Guinea pg +巴布亚新几内亚 pg +Philippines ph +Філіпіны ph +Филипини ph +Filipini ph +Filippinerne ph +Filipinas ph +Filipinak ph +Fülöp-szigetek ph +ອາລະປະໂຫຍດ ph +Filipinas ph +Filipíny ph +Filipini ph +Filippinerna ph +菲律宾 ph +Pakistan pk +Пакістан pk +Пакистан pk +Pakisztán pk +ລງບ pk +Paquistão pk +巴基斯坦 pk +Poland pl +Poolland pl +بولندا pl +Polşa pl +Польшча pl +Полша pl +Polonia pl +Poljska pl +Polònia pl +Polsko pl +Polen pl +Polen pl +Πολωνία pl +Pollando pl +Polonia pl +Poola pl +Polonia pl +لهستان pl +Puola pl +Pólland pl +Pologne pl +Polonia pl +פולין pl +Poljska pl +Lengyelország pl +Polandia pl +Pólland pl +Polonia pl +ポーランド pl +폴란드 pl +ໂປແລນ pl +Lenkija pl +Polija pl +Polonja pl +Polen pl +Polen pl +Polen pl +Polònia pl +Polska pl +Polónia pl +Polônia pl +Polonia pl +Польша pl +Poľsko pl +Poljska pl +Poljska pl +I-Poland pl +Polen pl +§À¡Ä¡óÐ pl +โปแลนด์ pl +Polonya pl +Польща pl +Pholandi pl +Ba Lan pl +Pologne pl +波兰 pl +波蘭 pl +Saint Pierre and Miquelon pm +Sveti Pjer i Migelon pm +Saint Pierre og Miquelon pm +Saint Pierre y Miquelon pm +Saint Pierre eta Miquelon pm +Saint Pierre és Miquelon pm +Saint Pierre e Miquelon pm +Saint Pierre a Miquelon pm +Sveti Pierre in Miquelon pm +Saint Pierre och Miquelon pm +圣皮埃尔和密克隆岛 pm +Pitcairn pn +Pitkern pn +ລງບ pn +Puerto Rico pr +Пуерто Рико pr +Portoriko pr +ໂປຣໂຕຄອນ pr +Porto Rico pr +Portoriko pr +波多尼各 pr +Palestinian Territory ps +Palesteinse Gebied ps +السلطة الفلسطينية ps +Палестынская тэрыторыя ps +Палестина ps +Palestinska teritorija ps +Territori Palestí ps +Palestinské území ps +Palæstinensiske selvstyreområder ps +Palästinensisches Gebiet ps +Παλαιστίνη ps +Palestinaj teritorioj ps +Territorio palestino ps +Palestiina territoorium ps +Palestina ps +فلسطین ps +Palestiinalaisalue ps +Palestinensiska økið ps +Territoire palestinien ps +השטחים הפלסטיניים ps +Palestinski teritorij ps +Palesztin területek ps +Territori palestinesi ps +パレスチナ自治区 ps +팔레스타인 자치구 ps +ການພິມຜິດພາດ ps +Palestinos teritorija ps +Palestina ps +Palestinske territorier ps +Palestijns territorium ps +Palestinske territorium ps +Bohwa bja Palestina ps +Palestyna ps +Território Palestiniano ps +Território Palestino ps +Teritoriul Palestinian ps +Палестинские территории ps +Palestínske územia ps +Palestinski teritorij ps +I-Palestinian Territory ps +Palestina ps +À¡Äо£É ¬¨½Âõ ps +Filistin Bölgesi ps +Палестинська територія ps +Mukano wa maphalesitina ps +Palestene ps +Umhlaba wePalestina ps +巴勒斯坦地区 ps +巴勒斯坦領地 ps +Indawo yama-Phalesitina ps +Portugal pt +البرتغال pt +Portuqaliya pt +Партугалія pt +Португалия pt +Portugalsko pt +Πορτογαλία pt +Portugalo pt +پرتغال pt +Portugali pt +פורטוגל pt +Portugália pt +Portúgal pt +Portogallo pt +ポルトガル pt +포르투갈 pt +ໂປຣຕຸເກສ pt +Portugalija pt +Portugāle pt +Portugall pt +Portugalia pt +Portugalia pt +Португалия pt +Portugalsko pt +Portugalska pt +I-Portugal pt +§À¡÷òиø pt +โปรตุเกส pt +Portekiz pt +Португалія pt +BềEĐào Nha pt +葡萄牙 pt +葡萄牙 pt +Palau pw +Палау pw +Палау pw +ມອລຕາ pw +帕劳群岛 pw +Paraguay py +Paraguaai py +باراغواي py +Paraqvay py +Парагвай py +Парагвай py +Paragvaj py +Paraguai py +Παραγουάη py +Paragvajo py +Paraguai py +پاراگویه py +Paraguai py +פרגואי py +Paragvaj py +パラグアイ py +파라과이 py +ປາລາກກວຍ py +Paragvajus py +Paragvaja py +Paragwaj py +Paraguai py +Paragwaj py +Paraguai py +Paraguai py +Paraguai py +Парагвай py +Portugalsko py +Paragvaj py +Paragvaj py +I-Paraguay py +Àá̧Špy +ปารากวัย py +Парагвай py +Paragway py +巴拉圭 py +巴拉圭 py +Qatar qa +قطر qa +Катар qa +Катар qa +Katar qa +Katar qa +Katar qa +Κατάρ qa +Kataro qa +Katar qa +قطر qa +Katar qa +קטר qa +Katar qa +Katar qa +カタール qa +카타르 qa +ມອລຕາ qa +Katar qa +Катар qa +Katar qa +Katar qa +I-Qatar qa +¸¾¡÷ qa +Katar qa +Катар qa +卡塔尔 qa +卡達 qa +Romania ro +Romenië ro +رومانيا ro +Rumıniya ro +Румынія ro +Румъния ro +Roumania ro +Rumunija ro +Rumunsko ro +Rumænien ro +Rumänien ro +Ρουμανία ro +Rumanio ro +Rumanía ro +Rumeenia ro +Errumania ro +رومانی ro +Rumenia ro +Roumanie ro +Romanía ro +רומניה ro +Rumunjska ro +Románia ro +Rumania ro +RúmenÃa ro +ルーマニア ro +루마니아 ro +ໂລມາເນີຍ ro +Rumunija ro +Rumānija ro +Rumanija ro +Roemenië ro +Rumunia ro +Roménia ro +Romênia ro +Румыния ro +Rumunsko ro +Romunija ro +Rumunija ro +I-Romania ro +Rumänien ro +Õ§Áɢ¡ ro +โรมาเนีย ro +Romanya ro +Румунія ro +Ru ma ni ro +Roumaneye ro +罗马尼亚 ro +羅馬尼亞 ro +Russia ru +Rusland ru +روسيا ru +Rusiya ru +Расея ru +Русия ru +Rusia ru +Rusija ru +Rússia ru +Rusko ru +Rusland ru +Russland ru +Ρωσία ru +Ruslando ru +Rusia ru +Venemaa ru +Errusia ru +روسیه ru +Venäjä ru +Russland ru +Russie ru +Rusia ru +רוסיה ru +Rusija ru +Oroszország ru +Rusia ru +Rússland ru +ロシア ru +러시아 ru +ລັດເຊີຍ ru +Rusija ru +Krievija ru +Russja ru +Russland ru +Rusland ru +Russland ru +Rosja ru +Rússia ru +Rússia ru +Rusia ru +Россия ru +Rusko ru +Rusija ru +Rusija ru +I-Russia ru +Ryssland ru +ú¢Â¡ ru +รัสเซีย ru +Rusya ru +Росія ru +Rashia ru +Nga ru +Russeye ru +Rashiya ru +俄罗斯 ru +俄羅斯 ru +Rwanda rw +Руанда rw +Руанда rw +Ruanda rw +Ruanda rw +Ruanda rw +ແພນດ້າ rw +Ruanda rw +Ruanda rw +卢旺达 rw +Saudi Arabia sa +Saudi Arabië sa +السعودية sa +Саудаўская Арабія sa +Саудитска Арабия sa +Saudijska Arabija sa +Aràbia Saudí sa +Saúdská Arábie sa +Saudi Arabien sa +Saudi-Arabien sa +Σαουδική Αραβία sa +Saŭdi-Arabio sa +Arabia Saudí sa +Saudi Araabia sa +عربستان سعودی sa +Saudi-Arabia sa +Arabie Saoudite sa +ערב הסעודית sa +Saudijska Arabija sa +Szaúd-Arábia sa +Arabia saudita sa +サウジアラビア sa +사우디 아라비아 sa +ອາລະບິກ sa +Saudi Arabija sa +Għarabja Sawdita sa +Saudi-Arabia sa +Saudi-Arabië sa +Saudi-Arabia sa +Arabia Saudyjska sa +Arábia Saudita sa +Arábia Saudita sa +Arabia Saudită sa +Саудовская Аравия sa +Saudská arábia sa +Saudova Arabija sa +I-Saudi Arabia sa +Saudiarabien sa +º×¾¢ «§ÃÀ¢Â¡ sa +Suudi Arabistan sa +Саудівська Аравія sa +沙特阿拉伯 sa +沙烏地阿拉伯 sa +Solomon Islands sb +Саламонавы астравы sb +Соломонови Острови sb +Solomonska ostrva sb +Salomon-øerne sb +Islas Salomón sb +Solomon Irlak sb +Salamon-szigetek sb +ສະໂລວະເນີຍ sb +Ilhas Salomão sb +Šalamúnove ostrovy sb +Solomonovi otoki sb +Salomonöarna sb +所罗门群岛 sb +Seychelles sc +Сэйшэлы sc +Сейшелски острови sc +Sejšeli sc +Seychellerne sc +ເຊລ sc +Sejšeli sc +Seychellerna sc +塞舌尔 sc +Sudan sd +السودان sd +Судан sd +Судан sd +Sudán sd +Σουδάν sd +Sudano sd +Sudán sd +Sudaan sd +سودان sd +Sudania sd +Soudan sd +סודן sd +Szudán sd +Súdan sd +スーダン sd +수단 sd +ຊູດານ sd +Sudanas sd +Sudāna sd +Sudão sd +Sudão sd +Судан sd +Sudán sd +I-Sudan sd +ݼ¡ý sd +ซูดาน sd +Судан sd +Sudani sd +Soudan sd +苏丹 sd +蘇丹 sd +Sweden se +Swede se +السويد se +İsveç se +Швэцыя se +Швеция se +Sveden se +Švedska se +Suècia se +Švédsko se +Sverige se +Schweden se +Σουηδία se +Svedio se +Suecia se +Rootsi se +Suedia se +سوید se +Ruotsi se +Svøriki se +Suède se +Suecia se +שבדיה se +Švedska se +Svédország se +Swedia se +SvÃþjóð se +Svezia se +スウェーデン se +스웨덴 se +ສະວີເດນ se +Švedija se +Zviedrija se +Svezja se +Sverige se +Zweden se +Sverige se +Suècia se +Szwecja se +Suécia se +Suécia se +Suedia se +Швеция se +Švédsko se +Švedska se +Švedska se +I-Sweden se +Sverige se +ÍÅ£¼ý se +สวีเดน se +İsveç se +Швеція se +Swidene se +Thuỵ Điển se +瑞典 se +瑞典 se +Singapore sg +Сынгапур sg +Сингапур sg +Singapur sg +Singapur sg +Szingapúr sg +ໂຊນາ sg +Singapura sg +Singapur sg +Singapur sg +新加坡 sg +Saint Helena sh +Свети Елена sh +Sveta Helena sh +St. Helena sh +Santa Helena sh +Szent Heléna sh +ຫົວເລື່ອງ sh +Santa Helena sh +Svätá Helena sh +Sveta Helena sh +圣赫勒拿岛 sh +Slovenia si +Slovenië si +سلوفينيا si +Sloveniya si +Славенія si +Словения si +Slovenija si +Eslovenia si +Slovinsko si +Slovenien si +Slowenien si +Σλοβενία si +Slovenio si +Eslovenia si +Sloveenia si +Eslovenia si +اسلوانی si +Slovénie si +Eslovenia si +סלובניה si +Slovenija si +Szlovénia si +SlóvenÃa si +スロベニア si +슬로베니아 si +ສະໂລວະເນີຍ si +Slovėnija si +Slovēnija si +Slovenja si +Slovenië si +Eslovenia si +Słowenia si +Eslovénia si +Eslovênia si +Словения si +Slovinsko si +Slovenija si +Slovenija si +I-Slovenia si +Slovenien si +ͧġŢɢ¡ si +สโลเวเนีย si +Slovenya si +Словенія si +斯洛文尼亚 si +斯洛維尼亞 si +Slovakia sk +Slovakië sk +سلوفاكيا sk +Slovakiya sk +Славакія sk +Словакия sk +Slovačka sk +Eslovaquia sk +Slovensko sk +Slovakiet sk +Slowakien sk +Σλοβακία sk +Slovakujo sk +Eslovaquia sk +Slovakkia sk +Eslovakia sk +اسلواکی sk +Slovaquie sk +סלובקיה sk +Slovačka sk +Szlovákia sk +SlóvakÃa sk +Slovacchia sk +スロバキア sk +슬로바키아 sk +ສະໂລວັກ sk +Slovakija sk +Slovākija sk +Slovakja sk +Slovakije sk +Słowacja sk +Eslováquia sk +Eslováquia sk +Slovacia sk +Словакия sk +Slovensko sk +Slovaška sk +I-Slovakia sk +Slovakien sk +ͧġš츢 sk +สโลวัค sk +Slovakya sk +Словакія sk +斯洛伐克 sk +斯洛伐克 sk +San Marino sm +Сан-Марына sm +Сан Марино sm +ໂຊນາ sm +圣马力诺 sm +Senegal sn +Сэнэгал sn +Сенегал sn +Szenegál sn +ທົ່ວໄປ sn +塞内加尔 sn +Somalia so +Somalië so +صومال so +Самалі so +Сомалия so +Somalija so +Somàlia so +Somálsko so +Σομαλία so +Somalio so +Somaalia so +سومالی so +Somalie so +סומליה so +Somalija so +Szomália so +ソマリア so +소말리아 so +ໂລມາເນີຍ so +Somalis so +Somalija so +Somalie so +Somália so +Somália so +Сомали so +Somálsko so +Somalija so +I-Somalia so +§º¡Á¡Ä¢Â¡ so +Somali so +Сомалі so +Somaleye so +索马里 so +索馬利亞 so +Suriname sr +Сурынам sr +Суринам sr +Surinam sr +ເຊີເບີຍ sr +Surinam sr +Surinam sr +Surinam sr +Sao Tome and Principe st +Сан Томе и Приницпе st +Sao Tome i Principe st +Sao Tomé og Principe st +Sao Tome y Príncipe st +Sao Tome eta Principe st +Sao Tome és Principe st +ບໍລິການ st +São Tome e Príncipe st +Sao Tome a Principe st +Sao Tome in Principe st +São Tomé och Príncipe st +El Salvador sv +السلفادور sv +Сальвадор sv +Ел Салвадор sv +Salvador sv +Salvador sv +Ελ Σαλβαντόρ sv +Elsalvadoro sv +Salvador sv +السالوادور sv +Salvador sv +O Salvador sv +אל סלבדור sv +Salvador sv +エルサルバドル sv +엘살바도르 sv +ເອລຊັນວາດດໍ sv +Salvadoras sv +Salvadora sv +Salwador sv +Salvador sv +Сальвадор sv +Salvádor sv +Salvador sv +I-El Salvador sv +±ø º¡øÅ§¼¡÷ sv +เอลซัลวาดอร์ sv +Ель-Сальвадор sv +萨尔瓦多 sv +薩爾瓦多 sv +Syria sy +Sirië sy +سوريا sy +Сырыя sy +Сирия sy +Sirija sy +Síria sy +Sýrie sy +Syrien sy +Syrien sy +Συρία sy +Sirio sy +Siria sy +Süüria sy +Siria sy +سوریه sy +Syyria sy +Syrie sy +סוריה sy +Sirija sy +Szíria sy +Siria sy +シリア sy +시리아 sy +ເຊີເບີຍ sy +Sirija sy +Siria sy +Syrië sy +Síria sy +Síria sy +Siria sy +Сирия sy +Sýria sy +Sirija sy +I-Syria sy +Syrien sy +º¢Ã¢Â¡ sy +Suriye sy +Сирія sy +叙利亚 sy +敘利亞 sy +Swaziland sz +Свазылэнд sz +Свазиленд sz +Svazilend sz +Swazilandia sz +Swazilandia sz +Szváziföld sz +ລາດສະນາຈັກໄທຍ sz +Suécia sz +Swazijsko sz +Svazi sz +斯威士兰 sz +Turks and Caicos Islands tc +Turks i Kaikos ostrva tc +Turks- og Caicosøerne tc +Islas Turcos y Caicos tc +Turks eta Caicos Irlak tc +Turks- és Caicos-szigetek tc +Ilhas Caicos e Turca tc +Turks a Caicos ostrovy tc +Otoka Turks in Caicos tc +Turks- och Caicosöarna tc +特克斯和凯科斯群岛 tc +Chad td +Чад td +Чад td +Čad td +Tchad td +Txad td +Csád td +ເກມໄພ່ td +Čad td +Čad td +Tchad td +乍得 td +Togo tg +Тога tg +Того tg +ຂອງເລ່ນສະນຸກ tg +多哥 tg +Thailand th +تايلاند th +Tayland th +Тайлянд th +Тайланд th +Tajland th +Tailàndia th +Thajsko th +Ταϊλάνδη th +Tajlando th +Tailandia th +Tai th +Thailandia th +تایلند th +Thaimaa th +Tailand th +Thaïlande th +Tailandia th +תאילנד th +Tajland th +Thaiföld th +Tæland th +Tailandia th +タイ th +태국 (타이) th +ລາດສະນາຈັກໄທຍ th +Tailandas th +Taivāna th +Tajlandja th +Tailandia th +Tajlandia th +Tailândia th +Tailândia th +Tailanda th +Таиланд th +Thajsko th +Tajska th +Tajland th +I-Thailand th +¾¡öÄ¡óÐ th +ราชอาณาจักรไทย th +Tayland th +Таїланд th +Thái Lan th +Taylande th +泰国 th +泰國 th +Tajikistan tj +Таджыкістан tj +Таджикистан tj +Tadžikistan tj +Tajikistán tj +Tadzsikisztán tj +ໃຕ້ຫວັນ tj +Tajiquistão tj +Tadžikistan tj +Tadžikistan tj +Tadzjikistan tj +塔吉克斯坦 tj +Tokelau tk +Токелао tk +ເບລາລັສ tk +Turkmenistan tm +Туркмэністан tm +Туркменистан tm +Turkmenistán tm +Türkmenisztán tm +ຕຸລະກີ tm +Turquia tm +土库曼斯坦 tm +Tunisia tn +Tunisië tn +تونس tn +Туніс tn +Тунис tn +Tunis tn +Tuníssia tn +Tunisko tn +Tunesien tn +Tunesien tn +Τυνησία tn +Tunisio tn +Túnez tn +Tuneesia tn +تونس tn +Tunesia tn +Tunisie tn +תוניסיה tn +Tunis tn +Tunézia tn +チュニジア tn +튀니지 tn +ລັດເຊີຍ tn +Tunisas tn +Tuneżija tn +Tunisie tn +Tunezja tn +Tunísia tn +Tunísia tn +Тунис tn +Tunisko tn +Tunizija tn +I-Tunisia tn +Tunisien tn +ÐÉ¢º¢Â¡ tn +Tunus tn +Туніс tn +突尼斯 tn +突尼西亞 tn +Tonga to +Тонга to +Тонга to +ໂຊນາ to +汤加 to +East Timor tp +Источен Тимур tp +Istočni Timor tp +Østtimor tp +Timor oriental tp +Ekialdeko Timor tp +Kelet-Timor tp +ວັນແລະເວລາ tp +Timor Leste tp +Východný Timor tp +Vzhodni Timor tp +Östtimor tp +东帝汶 tp +Turkey tr +Turkeye tr +تركيا tr +Türkiyə tr +Турцыя tr +Турция tr +Turkia tr +Turska tr +Turquia tr +Turecko tr +Tyrkiet tr +Türkei tr +Τουρκία tr +Turkujo tr +Turquía tr +Türgi tr +Turkia tr +ترکیه tr +Turkki tr +Turkaland tr +Turquie tr +Turquía tr +טורקיה tr +Turska tr +Törökország tr +Turki tr +Tyrkland tr +Turchia tr +トルコ tr +터키 tr +ຕຸລະກີ tr +Turkija tr +Turcija tr +Turkija tr +Tyrkia tr +Turkije tr +Tyrkia tr +Turquia tr +Turcja tr +Turquia tr +Turquia tr +Turcia tr +Турция tr +Turecko tr +Turčija tr +Turska tr +I-Turkey tr +Turkiet tr +ÐÕ츢 tr +ตุรกี tr +Türkiye tr +Туреччина tr +ThềENhĩ Kì tr +土耳其 tr +土耳其 tr +Trinidad and Tobago tt +Trinidad en Tobago tt +ترينيداد و توباغو tt +Trinidad və Tabaqo tt +Трынідад і Табага tt +Тринидад и Тобаго tt +Trinidad ha Tobago tt +Trinidad i Tobago tt +Trinidad i Tobago tt +Trinidad a Tobago tt +Trinidad og Tobago tt +Trinidad und Tobago tt +Τρίνινταντ και Τομπάγκο tt +Trinidado kaj Tobago tt +Trinidad y Tobago tt +Trinidad ja Tobago tt +Trinidad eta Tobago tt +ترینیداد و تُباگو tt +Trinidad ja Tobago tt +Trinidad og Tobago tt +Trinidad et Tobago tt +Trindade e Tobago tt +טרינידד וטובגו tt +Trinidad i Tobago tt +Trinidad és Tobago tt +Trinidad dan Tobago tt +Trinidad og Tobago tt +Trinidad e Tobago tt +トリニダードトバコ tt +트리니다드토바고 tt +ຕີນິແດດແລະໂທບາໂກ tt +Trinidadas ir Tobagas tt +Trinidada un Tobago tt +Trinidad u Tobago tt +Trinidad og Tobago tt +Trinidad en Tobago tt +Trinidad og Tobago tt +Trinidad le Tobago tt +Trinidad e Tobago tt +Trinidad i Tobago tt +Trinidade e Tobago tt +Trinidad e Tobago tt +Trinidad şi Tobago tt +Тринидад и Тобаго tt +Trinidad a Tobago tt +Trinidad in Tabago tt +Trinidad i Tobago tt +I-Trinidad kanye neTobago tt +Trinidad och Tobago tt +ðâɢ¼¡ð & ¦¼¡À¡§¸¡ tt +ตรีนิแดดและโทบาโก tt +Trinidad veTabago tt +Республіка Трінідад та Тобаго tt +Trinidad na Tobago tt +Trinidad và Tobago tt +Trinidad ne Tobago tt +特里尼达和多巴哥 tt +千里達及托貝哥 tt +Trinidad knaye ne-Tobago tt +Tuvalu tv +Тувалу tv +Тували tv +ຊູລູ tv +图瓦卢 tv +Taiwan tw +تايوان tw +Tayvan tw +Тайвань tw +Тайван tw +Tajvan tw +Ταϊβάν tw +Tajvano tw +Taiwán tw +Taivan tw +تایوان tw +Taivan tw +Taïwan tw +Taiwán tw +טיוואן tw +Tajvan tw +Tajvan tw +台湾 tw +대만 tw +ໃຕ້ຫວັນ tw +Taivanis tw +Taivāna tw +Tajwan tw +Tajwan tw +Formosa tw +Тайвань tw +Tajvan tw +Tajvan tw +I-Taiwan tw +¾¡öÅ¡ý tw +ได้หวัน tw +Tayvan tw +Тайвань tw +Đài Loan tw +中国台湾 tw +台灣 tw +Tanzania, United Republic of tz +Злучаная Рэспубліка Танзанія tz +Танзания tz +Tanzanija, Ujedinjena Republika tz +Tanzania tz +Tanzania, Republica de tz +Tanazia, Errepublika Batua tz +Tanzánia tz +ໂດມິນິກັນ tz +República da Tanzânia tz +Tanzánia, Spojená republika tz +Tanzanija, Združena republika tz +Förenade republiken Tanzania tz +坦桑尼亚 tz +Ukraine ua +Ukraïne ua +أوكرانيا ua +Ukrayna ua +Украіна ua +Украйна ua +Ukraina ua +Ukrajina ua +Ucraïna ua +Ukrajina ua +Ουκρανία ua +Ukrainio ua +Ucrania ua +Ukraina ua +Ukrania ua +اکراین ua +Ukraina ua +Ukraina ua +Ucraína ua +אוקראינה ua +Ukrajina ua +Ukrajna ua +Ukraina ua +ÃkraÃna ua +Ucraina ua +ウクライナ ua +우크라이나 ua +ຍູເຄຣນ ua +Ukraina ua +Ukraina ua +Ukranja ua +Ukraina ua +Oekraïne ua +Ukraina ua +Ucraina ua +Ukraina ua +Ucrânia ua +Ucrânia ua +Ucraina ua +Украина ua +Ukrajina ua +Ukrajina ua +Ukrajna ua +I-Ukraine ua +Ukraina ua +¯ì¦Ãöý ua +ยูเครน ua +Ukrayna ua +Україна ua +Ukraina ua +Ucrinne ua +乌克兰 ua +烏克蘭 ua +Uganda ug +Уганда ug +Уганда ug +ແພນດ້າ ug +乌干达 ug +United States of America us +Vereenigde State van Amerika us +الولايات المتحدة الأمريكية us +Amerika Birləşmiş Ştatları us +Злучаныя Штаты Амэрыкі us +САЩ us +Stadoù-Unanet Amerika us +Sjedinjene Američke Države us +Estats Units d'Amèrica us +Spojené státy americké us +USA us +USA us +Ην. Πολιτείες της Αμερικής us +Usono us +Estados Unidos de América us +Ameerika Ühendriigid us +Amerikako Estatu Batuak us +ایالات متحدهی آمریکا us +Yhdysvallat us +Sambandsríki Amerika (USA) us +États Unis d'Amérique us +Estados Unidos de América us +ארצות הברית us +Sjedinjene Američke Države us +Amerikai Egyesült Államok us +Amerika Serikat us +BandarÃki Norður AmerÃku us +Stati Uniti d'America us +アメリカ us +미 합중국 us +ສະຫະລັດອາເມລິກາ us +Jungtinės Amerikos Valstijos us +Amerikas Savienotās Valstis us +Stati Uniti us +USA us +Verenigde Staten van Amerika us +USA us +Estats Units d'Amèrica us +Stany Zjednoczone Ameryki us +Estados Unidos da América us +Estados Unidos us +Statele Unite ale Americii us +Соединенные Штаты Америки us +USA us +Združene države Amerike us +Sjedinjene američke države us +I-United States of America us +Amerikas förenta stater us +³ì¸¢Â «¦ÁÃ¢ì¸ ¿¡Î¸û us +สหรัฐอเมริกา us +Amerika Birleşik Devletleri us +США us +mashango o tangananaho a America us +Mĩ us +United States ye Melika us +美利坚合众国 us +美利堅合眾國 us +Uruguay uy +الأوروغواي uy +Uruqvay uy +Уругвай uy +Уругвай uy +Urugvaj uy +Uruguai uy +Ουρουγουάη uy +Urugvajo uy +Uruguai uy +اروگویه uy +Uruguai uy +אורוגואי uy +Urugvaj uy +ウルグアイ uy +우루과이 uy +ອຸລຸກກວຍ uy +Urugvajus uy +Urugvaja uy +Urugwaj uy +Uruguai uy +Urugwaj uy +Uruguai uy +Uruguai uy +Uruguai uy +Уругвай uy +Uruguaj uy +Urugvaj uy +Urugvaj uy +I-Uruguay uy +¯Õ̧Šuy +อุรุกวัย uy +Уругвай uy +Ourougway uy +乌拉圭 uy +烏拉圭 uy +Uzbekistan uz +Узбэкістан uz +Узбекистан uz +Uzbekistán uz +Üzbegisztán uz +ເດນ່ງນ uz +Uzbequistão uz +乌兹别克斯坦 uz +Vatican City va +Ватыкан va +Ватикана va +Vatikan va +Vatikanstaten va +Vaticano va +Batikano Hiria va +Vatikán va +ລັດເວີຍ va +Cidade do Vaticano va +Vatikán va +Vatikan va +Vatikanstaten va +梵蒂冈 va +St. Vincent and the Grenadines vc +St. Vincent en die Grenadene vc +سانت فينسنت و الغرينادين vc +St. Vincent və Grenadines vc +Сент-Винсент и Гренадине vc +S. Visant hag ar Grenadinez vc +Sveti Vincent i Grenadini vc +St. Vincent i les Granadines vc +St. Vincent a Grenadiny vc +St. Vincent og Grenadinerne vc +St. Vincent und Grenadinen vc +St. Vincent kaj la Grenadinoj vc +San Vicente y las Granadinas vc +St. Vincent ja Grenadines vc +St. Vincent eta Grenadines vc +سن وینسن و گرادینس vc +St. Vincent ja Grenadiinit vc +Sankta Vinsent og Grenadinoyggjar vc +St Vincent et les Grenadines vc +San Vicente e as Granadinas vc +סנט וינסנט והגרנדינים vc +St. Vincent és Grenadines vc +St. Vincent dan the Grenadines vc +St. Vincent og Grenadines vc +S. Vincent e the Grenadines vc +セントヴィンセントグレナディン vc +세인트 빈센트 그레나딘 vc +ເຊີນວິນແຊນ ແລະເກນາດີນ vc +Šv. Vincentas ir Grenadinai vc +Sv. Vincents un Grenadīnes vc +St. Vinċenz u l-Grenadini vc +St. Vincent og Grenadinene vc +St. Vincent en de Grenadines vc +St. Vincent og Grenadinane vc +St. Vincent le Grenadines vc +St. Vincent e les Granadines vc +St. Vincent i Grenadyny vc +São Vicente e Grenadinas vc +São Vicente e Grenadines vc +Sf. Vincent şi Grenadines vc +Сент-Винсент и Гренадины vc +St. Vincent a Grenadines vc +Sv. Vincent in Grenadini vc +St. Vincent i Grenadine vc +I-St. Vincent and the Grenadines vc +St. Vincent och Grenadinerna vc +¦ºÂ¢ýð Å¢ý¦ºýð & ¸¢¦ÃÉËý¸û vc +เซนต์วินเซนต์ และ เกรนาดีน vc +St. Vincent ve Grenadines vc +Сент-Вінсент і Гренадіни vc +St. Vincent na Grenadines vc +St. Vincent và Grenadines vc +St. Vincent ne Grenadines vc +圣文森特和格林那达 vc +聖文森及格納那丁 vc +I-St. Vincent kanye ne-Grenadines vc +Venezuela ve +فنزويلا ve +Вэнэсуэла ve +Венецуела ve +Venecuela ve +Βενεζουέλα ve +Venezuelo ve +Venetsueela ve +ونزویلا ve +Venesuela ve +Vénézuela ve +ונצואלה ve +Venecuela ve +ベネズェラ ve +베네수엘라 ve +ເວເນຊຸເອລາ ve +Venesuela ve +Venecuēla ve +Veneżwela ve +Wenezuela ve +Венесуэла ve +Venecuela ve +I-Venezuela ve +¦ÅÉ¢ÍÅÄ¡ ve +เวเนซูเอลา ve +Венесуела ve +委内瑞拉 ve +委內瑞拉 ve +Virgin Islands, British vg +Вирджински Острови, Британски vg +Djevičanska ostrva, Britanska vg +Britiske jomfruøer vg +Islas Vírgenes Británicas vg +Irla Birjinak, Britaniar vg +Virgin-szigetek (brit) vg +Ilhas Virgens, Inglaterra vg +Panenské Ostrovy, Britské vg +Deviški otoki, Britanski vg +Brittiska Jungfruöarna vg +维尔京群岛,英国 vg +Virgin Islands, U.S. vi +Вирджински Острови, Американски vi +Djevičanska ostrva, Američka vi +Jomfruøerne vi +Islas Vírgenes Americanas vi +Irla Birjinak, EE.BB. vi +Virgin-szigetek (USA) vi +Ilhas Virgens, EUA vi +Panenské Ostrovy, Americké vi +Deviški otoki, ZDA vi +Amerikanska Jungfruöarna vi +维尔京群岛,美国 vi +Vietnam vn +Viëtnam vn +فييتنام vn +Vyetnam vn +Віетнам vn +Виетнам vn +Vijetnam vn +Βιετνάμ vn +Vjetnamo vn +ویتنام vn +וייטנאם vn +Vijetnam vn +VÃetnam vn +ベトナム vn +베트남 vn +ຫວງດນາມ vn +Vietnamas vn +Vjetnama vn +Vjetnam vn +Viëtnam vn +Wietnam vn +Vietname vn +Vietnã vn +Вьетнам vn +I-Vietnam vn +เวียตนาม vn +В'єтнам vn +越南 vn +越南 vn +Vanuatu vu +Вануату vu +Ванути vu +ຈີນ vu +瓦努阿图 vu +Wallis and Futuna wf +Valis i Futuna wf +Wallis- og Futuna-øerne wf +Wallis y Futuna wf +Wallis eta Futuna wf +Wallis és Futuna wf +ປັກອິນພາບ wf +Wallis e Futuna wf +Wallis a Futuna wf +Wallis in Futuna wf +Wallis och Futuna wf +Samoa ws +Самоа ws +Самоя ws +Szamoa ws +ໂຊນາ ws +萨摩亚群岛 ws +Yemen ye +اليمن ye +Емен ye +Йемен ye +Jemen ye +Iemen ye +Jemen ye +Jemen ye +Υεμένη ye +Jemeno ye +Jeemen ye +یمن ye +Jemen ye +Jemen ye +תימן ye +Jemen ye +Jemen ye +イエメン ye +예멘 ye +ເດມອນ ye +Jemenas ye +Jemen ye +Jemen ye +Jemen ye +Jemen ye +Jemen ye +Iémen ye +Йемен ye +Jemen ye +Jemen ye +I-Yemen ye +Jemen ye +§ÂÁý ye +Ємен ye +也门 ye +葉門 ye +Yugoslavia yu +Югаславія yu +Югославия yu +Jugoslavija yu +Jugoslavien (Serbien/Montenegro) yu +Jugoszlávia yu +ໂບລິເວີຍ yu +Iugoslávia yu +Juhoslávia yu +Jugoslavija yu +Jugoslavien yu +南斯拉夫 yu +South Africa za +Suid Afrika za +جنوب أفريقيا za +Cənubi Afrika za +Паўднёвая Афрыка za +Южна Африка za +Suafrika za +Južna Afrika za +Sudàfrica za +Jižní Afrika za +Sydafrikanske republik za +Südafrika za +Νότια Αφρική za +Sudafriko za +Sudáfrica za +Lõuna Aafrika za +Hego Afrika za +آفریقای جنوبی za +Etelä-Afrikka za +Suðurafrika za +Afrique du sud za +África do Sur za +דרום אפריקה za +Južna Afrika za +Dél-Afrika za +Afrika Selatan za +Suður AfrÃka za +Sud Africa za +南アフリカ za +남 아프리카 공화국 za +ແອບພິກາໃຕ້ za +Pietų Afrika za +Dienvid Āfrika za +Afrika t'Isfel za +Sør-Afrika za +Zuid-Afrika za +Sør-Afrika za +Afrika Borwa za +Sudafrica za +Afryka Południowa za +Africa do Sul za +África do Sul za +Africa de Sud za +Южная Африка za +Južná Afrika za +Južna Afrika za +Južna Afrika za +I-South Africa za +Sydafrika za +¦¾ý ¬ôâ측 za +แอฟริกาใต้ za +Güney Afrika za +Південна Африка za +Afurika tshipembe za +Nam Phi za +Mzantsi Afrika za +南非 za +南非 za +Emzantsi Afrika za +Zambia zm +Замбія zm +Замбия zm +ຈາໄມກາ້ zm +Zâmbia zm +Zambija zm +赞比亚 zm +Zimbabwe zw +Зымбабвэ zw +Зимбабве zw +Zimbabve zw +ລິຊາ zw +Zimbabve zw +津巴布韦 zw diff --git a/addressbook/gui/widgets/e-addressbook-model.c b/addressbook/gui/widgets/e-addressbook-model.c index 9244df8a38..683eed3499 100644 --- a/addressbook/gui/widgets/e-addressbook-model.c +++ b/addressbook/gui/widgets/e-addressbook-model.c @@ -1,641 +1,993 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. * - * Author: - * Christopher James Lahey <clahey@ximian.com> + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Christopher James Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * - * (C) 1999 Ximian, Inc. */ +#ifdef HAVE_CONFIG_H #include <config.h> -#include "e-addressbook-model.h" -#include <gnome-xml/tree.h> -#include <gnome-xml/parser.h> -#include <gnome-xml/xmlmemory.h> -#include <gnome.h> -#include <gal/widgets/e-gui-utils.h> -#include "e-addressbook-util.h" - -#define PARENT_TYPE gtk_object_get_type() -GtkObjectClass *parent_class; - -/* - * EAddressbookModel callbacks - * These are the callbacks that define the behavior of our custom model. - */ -static void e_addressbook_model_set_arg (GtkObject *o, GtkArg *arg, guint arg_id); -static void e_addressbook_model_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); +#endif +#include <string.h> +#include <glib/gi18n.h> +#include "e-addressbook-model.h" +#include <e-util/e-marshal.h> +#include <e-util/e-util.h> +#include "eab-gui-util.h" + +#define E_ADDRESSBOOK_MODEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ADDRESSBOOK_MODEL, EAddressbookModelPrivate)) + +struct _EAddressbookModelPrivate { + EClientCache *client_cache; + gulong client_notify_readonly_handler_id; + + EBookClient *book_client; + gchar *query_str; + EBookClientView *client_view; + guint client_view_idle_id; + + /* Query Results */ + GPtrArray *contacts; + + /* Signal Handler IDs */ + gulong create_contact_id; + gulong remove_contact_id; + gulong modify_contact_id; + gulong status_message_id; + gulong view_complete_id; + guint remove_status_id; + + guint search_in_progress : 1; + guint editable : 1; + guint first_get_view : 1; +}; enum { - ARG_0, - ARG_BOOK, - ARG_QUERY, - ARG_EDITABLE, + PROP_0, + PROP_CLIENT, + PROP_CLIENT_CACHE, + PROP_EDITABLE, + PROP_QUERY }; enum { WRITABLE_STATUS, STATUS_MESSAGE, + SEARCH_STARTED, SEARCH_RESULT, FOLDER_BAR_MESSAGE, - CARD_ADDED, - CARD_REMOVED, - CARD_CHANGED, + CONTACT_ADDED, + CONTACTS_REMOVED, + CONTACT_CHANGED, MODEL_CHANGED, STOP_STATE_CHANGED, - BACKEND_DIED, LAST_SIGNAL }; -#define COLS (E_CARD_SIMPLE_FIELD_LAST) +static guint signals[LAST_SIGNAL]; -static guint e_addressbook_model_signals [LAST_SIGNAL] = {0, }; +G_DEFINE_TYPE (EAddressbookModel, e_addressbook_model, G_TYPE_OBJECT) static void free_data (EAddressbookModel *model) { - int i; - - for ( i = 0; i < model->data_count; i++ ) { - gtk_object_unref(GTK_OBJECT(model->data[i])); - } + GPtrArray *array; - g_free(model->data); - model->data = NULL; - model->data_count = 0; - model->allocated_count = 0; + array = model->priv->contacts; + g_ptr_array_foreach (array, (GFunc) g_object_unref, NULL); + g_ptr_array_set_size (array, 0); } static void -remove_book_view(EAddressbookModel *model) -{ - if (model->book_view && model->create_card_id) - gtk_signal_disconnect(GTK_OBJECT (model->book_view), - model->create_card_id); - if (model->book_view && model->remove_card_id) - gtk_signal_disconnect(GTK_OBJECT (model->book_view), - model->remove_card_id); - if (model->book_view && model->modify_card_id) - gtk_signal_disconnect(GTK_OBJECT (model->book_view), - model->modify_card_id); - if (model->book_view && model->status_message_id) - gtk_signal_disconnect(GTK_OBJECT (model->book_view), - model->status_message_id); - if (model->book_view && model->sequence_complete_id) - gtk_signal_disconnect(GTK_OBJECT (model->book_view), - model->sequence_complete_id); - - model->create_card_id = 0; - model->remove_card_id = 0; - model->modify_card_id = 0; - model->status_message_id = 0; - model->sequence_complete_id = 0; - - model->search_in_progress = FALSE; - - if (model->book_view) { - e_book_view_stop (model->book_view); - gtk_object_unref(GTK_OBJECT(model->book_view)); - } - - model->book_view = NULL; -} - -static void -addressbook_destroy(GtkObject *object) +remove_book_view (EAddressbookModel *model) { - EAddressbookModel *model = E_ADDRESSBOOK_MODEL(object); - - if (model->get_view_idle) { - g_source_remove(model->get_view_idle); - model->get_view_idle = 0; - } - - remove_book_view(model); - free_data (model); - - if (model->book) { - if (model->writable_status_id) - gtk_signal_disconnect(GTK_OBJECT (model->book), - model->writable_status_id); + if (model->priv->client_view && model->priv->create_contact_id) + g_signal_handler_disconnect ( + model->priv->client_view, + model->priv->create_contact_id); + if (model->priv->client_view && model->priv->remove_contact_id) + g_signal_handler_disconnect ( + model->priv->client_view, + model->priv->remove_contact_id); + if (model->priv->client_view && model->priv->modify_contact_id) + g_signal_handler_disconnect ( + model->priv->client_view, + model->priv->modify_contact_id); + if (model->priv->client_view && model->priv->status_message_id) + g_signal_handler_disconnect ( + model->priv->client_view, + model->priv->status_message_id); + if (model->priv->client_view && model->priv->view_complete_id) + g_signal_handler_disconnect ( + model->priv->client_view, + model->priv->view_complete_id); + if (model->priv->remove_status_id) + g_source_remove (model->priv->remove_status_id); + + model->priv->create_contact_id = 0; + model->priv->remove_contact_id = 0; + model->priv->modify_contact_id = 0; + model->priv->status_message_id = 0; + model->priv->view_complete_id = 0; + model->priv->remove_status_id = 0; + + model->priv->search_in_progress = FALSE; + + if (model->priv->client_view) { + GError *error = NULL; + + e_book_client_view_stop (model->priv->client_view, &error); + + if (error != NULL) { + g_warning ( + "%s: Failed to stop client view: %s", + G_STRFUNC, error->message); + g_error_free (error); + } - model->writable_status_id = 0; + g_object_unref (model->priv->client_view); + model->priv->client_view = NULL; - gtk_object_unref(GTK_OBJECT(model->book)); - model->book = NULL; + g_signal_emit (model, signals[STATUS_MESSAGE], 0, NULL, -1); } - - g_free (model->query); } static void update_folder_bar_message (EAddressbookModel *model) { - int count; - char *message; + guint count; + gchar *message; - count = model->data_count; + count = model->priv->contacts->len; switch (count) { case 0: - message = g_strdup (_("No cards")); - break; - case 1: - message = g_strdup (_("1 card")); + message = g_strdup (_("No contacts")); break; default: - message = g_strdup_printf (_("%d cards"), count); + message = g_strdup_printf ( + ngettext ("%d contact", "%d contacts", count), count); break; } - gtk_signal_emit (GTK_OBJECT (model), - e_addressbook_model_signals [FOLDER_BAR_MESSAGE], - message); + g_signal_emit (model, signals[FOLDER_BAR_MESSAGE], 0, message); g_free (message); } static void -create_card(EBookView *book_view, - const GList *cards, - EAddressbookModel *model) +view_create_contact_cb (EBookClientView *client_view, + const GSList *contact_list, + EAddressbookModel *model) { - int old_count = model->data_count; - int length = g_list_length ((GList *)cards); + GPtrArray *array; + guint count; + guint index; - if (model->data_count + length > model->allocated_count) { - while (model->data_count + length > model->allocated_count) - model->allocated_count = model->allocated_count * 2 + 1; - model->data = g_renew(ECard *, model->data, model->allocated_count); - } + array = model->priv->contacts; + index = array->len; + count = g_list_length ((GList *) contact_list); - for ( ; cards; cards = cards->next) { - model->data[model->data_count++] = cards->data; - gtk_object_ref (cards->data); - } + while (contact_list != NULL) { + EContact *contact = contact_list->data; - gtk_signal_emit (GTK_OBJECT (model), - e_addressbook_model_signals [CARD_ADDED], - old_count, model->data_count - old_count); + g_ptr_array_add (array, g_object_ref (contact)); + contact_list = contact_list->next; + } + g_signal_emit (model, signals[CONTACT_ADDED], 0, index, count); update_folder_bar_message (model); } -static void -remove_card(EBookView *book_view, - const char *id, - EAddressbookModel *model) -{ - int i; - - for ( i = 0; i < model->data_count; i++) { - if ( !strcmp(e_card_get_id(model->data[i]), id) ) { - gtk_object_unref(GTK_OBJECT(model->data[i])); - memmove(model->data + i, model->data + i + 1, (model->data_count - i - 1) * sizeof (ECard *)); - model->data_count--; - - gtk_signal_emit (GTK_OBJECT (model), - e_addressbook_model_signals [CARD_REMOVED], - i); - update_folder_bar_message (model); - break; - } - } +static gint +sort_descending (gconstpointer ca, + gconstpointer cb) +{ + gint a = *((gint *) ca); + gint b = *((gint *) cb); + + return (a == b) ? 0 : (a < b) ? 1 : -1; } static void -modify_card(EBookView *book_view, - const GList *cards, - EAddressbookModel *model) -{ - for ( ; cards; cards = cards->next) { - int i; - for ( i = 0; i < model->data_count; i++) { - if ( !strcmp(e_card_get_id(model->data[i]), e_card_get_id(E_CARD(cards->data))) ) { - gtk_object_unref(GTK_OBJECT(model->data[i])); - model->data[i] = e_card_duplicate(E_CARD(cards->data)); - gtk_signal_emit (GTK_OBJECT (model), - e_addressbook_model_signals [CARD_CHANGED], - i); +view_remove_contact_cb (EBookClientView *client_view, + const GSList *ids, + EAddressbookModel *model) +{ + /* XXX we should keep a hash around instead of this O(n*m) loop */ + const GSList *iter; + GArray *indices; + GPtrArray *array; + gint ii; + + array = model->priv->contacts; + indices = g_array_new (FALSE, FALSE, sizeof (gint)); + + for (iter = ids; iter != NULL; iter = iter->next) { + const gchar *target_uid = iter->data; + + for (ii = 0; ii < array->len; ii++) { + EContact *contact; + const gchar *uid; + + contact = array->pdata[ii]; + /* check if already removed */ + if (!contact) + continue; + + uid = e_contact_get_const (contact, E_CONTACT_UID); + g_return_if_fail (uid != NULL); + + if (strcmp (uid, target_uid) == 0) { + g_object_unref (contact); + g_array_append_val (indices, ii); + array->pdata[ii] = NULL; break; } } } -} -static void -status_message (EBookView *book_view, - char* status, - EAddressbookModel *model) -{ - gtk_signal_emit (GTK_OBJECT (model), - e_addressbook_model_signals [STATUS_MESSAGE], - status); -} + /* Sort the 'indices' array in descending order, since + * g_ptr_array_remove_index() shifts subsequent elements + * down one position to fill the gap. */ + g_array_sort (indices, sort_descending); -static void -sequence_complete (EBookView *book_view, - EBookViewStatus status, - EAddressbookModel *model) -{ - model->search_in_progress = FALSE; - status_message (book_view, NULL, model); - gtk_signal_emit (GTK_OBJECT (model), - e_addressbook_model_signals [SEARCH_RESULT], - status); - gtk_signal_emit (GTK_OBJECT (model), - e_addressbook_model_signals [STOP_STATE_CHANGED]); + for (ii = 0; ii < indices->len; ii++) { + gint index; + + index = g_array_index (indices, gint, ii); + g_ptr_array_remove_index (array, index); + } + + g_signal_emit (model, signals[CONTACTS_REMOVED], 0, indices); + g_array_free (indices, FALSE); + + update_folder_bar_message (model); } static void -writable_status (EBook *book, - gboolean writable, - EAddressbookModel *model) +view_modify_contact_cb (EBookClientView *client_view, + const GSList *contact_list, + EAddressbookModel *model) { - if (!model->editable_set) { - model->editable = writable; + GPtrArray *array; + + array = model->priv->contacts; + + while (contact_list != NULL) { + EContact *new_contact = contact_list->data; + const gchar *target_uid; + gint ii; + + target_uid = e_contact_get_const (new_contact, E_CONTACT_UID); + g_warn_if_fail (target_uid != NULL); + + /* skip contacts without UID */ + if (!target_uid) { + contact_list = contact_list->next; + continue; + } - gtk_signal_emit (GTK_OBJECT (model), - e_addressbook_model_signals [WRITABLE_STATUS], - writable); + for (ii = 0; ii < array->len; ii++) { + EContact *old_contact; + const gchar *uid; + + old_contact = array->pdata[ii]; + g_return_if_fail (old_contact != NULL); + + uid = e_contact_get_const (old_contact, E_CONTACT_UID); + g_return_if_fail (uid != NULL); + + if (strcmp (uid, target_uid) != 0) + continue; + + g_object_unref (old_contact); + array->pdata[ii] = e_contact_duplicate (new_contact); + + g_signal_emit ( + model, signals[CONTACT_CHANGED], 0, ii); + break; + } + + contact_list = contact_list->next; } } static void -backend_died (EBook *book, - EAddressbookModel *model) +view_progress_cb (EBookClientView *client_view, + guint percent, + const gchar *message, + EAddressbookModel *model) { - gtk_signal_emit (GTK_OBJECT (model), - e_addressbook_model_signals [BACKEND_DIED]); + if (model->priv->remove_status_id) + g_source_remove (model->priv->remove_status_id); + model->priv->remove_status_id = 0; + + g_signal_emit (model, signals[STATUS_MESSAGE], 0, message, percent); } static void -e_addressbook_model_class_init (GtkObjectClass *object_class) -{ - parent_class = gtk_type_class (PARENT_TYPE); - - object_class->destroy = addressbook_destroy; - object_class->set_arg = e_addressbook_model_set_arg; - object_class->get_arg = e_addressbook_model_get_arg; - - gtk_object_add_arg_type ("EAddressbookModel::book", GTK_TYPE_OBJECT, - GTK_ARG_READWRITE, ARG_BOOK); - gtk_object_add_arg_type ("EAddressbookModel::query", GTK_TYPE_STRING, - GTK_ARG_READWRITE, ARG_QUERY); - gtk_object_add_arg_type ("EAddressbookModel::editable", GTK_TYPE_BOOL, - GTK_ARG_READWRITE, ARG_EDITABLE); - - e_addressbook_model_signals [WRITABLE_STATUS] = - gtk_signal_new ("writable_status", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EAddressbookModelClass, writable_status), - gtk_marshal_NONE__BOOL, - GTK_TYPE_NONE, 1, GTK_TYPE_BOOL); - - e_addressbook_model_signals [STATUS_MESSAGE] = - gtk_signal_new ("status_message", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EAddressbookModelClass, status_message), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); - - e_addressbook_model_signals [SEARCH_RESULT] = - gtk_signal_new ("search_result", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EAddressbookModelClass, search_result), - gtk_marshal_NONE__ENUM, - GTK_TYPE_NONE, 1, GTK_TYPE_ENUM); - - e_addressbook_model_signals [FOLDER_BAR_MESSAGE] = - gtk_signal_new ("folder_bar_message", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EAddressbookModelClass, folder_bar_message), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); - - e_addressbook_model_signals [CARD_ADDED] = - gtk_signal_new ("card_added", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EAddressbookModelClass, card_added), - gtk_marshal_NONE__INT_INT, - GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); - - e_addressbook_model_signals [CARD_REMOVED] = - gtk_signal_new ("card_removed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EAddressbookModelClass, card_removed), - gtk_marshal_NONE__INT, - GTK_TYPE_NONE, 1, GTK_TYPE_INT); - - e_addressbook_model_signals [CARD_CHANGED] = - gtk_signal_new ("card_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EAddressbookModelClass, card_changed), - gtk_marshal_NONE__INT, - GTK_TYPE_NONE, 1, GTK_TYPE_INT); - - e_addressbook_model_signals [MODEL_CHANGED] = - gtk_signal_new ("model_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EAddressbookModelClass, model_changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - e_addressbook_model_signals [STOP_STATE_CHANGED] = - gtk_signal_new ("stop_state_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EAddressbookModelClass, stop_state_changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - e_addressbook_model_signals [BACKEND_DIED] = - gtk_signal_new ("backend_died", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EAddressbookModelClass, backend_died), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - gtk_object_class_add_signals (object_class, e_addressbook_model_signals, LAST_SIGNAL); +view_complete_cb (EBookClientView *client_view, + const GError *error, + EAddressbookModel *model) +{ + model->priv->search_in_progress = FALSE; + view_progress_cb (client_view, -1, NULL, model); + g_signal_emit (model, signals[SEARCH_RESULT], 0, error); + g_signal_emit (model, signals[STOP_STATE_CHANGED], 0); } static void -e_addressbook_model_init (GtkObject *object) -{ - EAddressbookModel *model = E_ADDRESSBOOK_MODEL(object); - model->book = NULL; - model->query = g_strdup("(contains \"x-evolution-any-field\" \"\")"); - model->book_view = NULL; - model->get_view_idle = 0; - model->create_card_id = 0; - model->remove_card_id = 0; - model->modify_card_id = 0; - model->status_message_id = 0; - model->writable_status_id = 0; - model->backend_died_id = 0; - model->sequence_complete_id = 0; - model->data = NULL; - model->data_count = 0; - model->allocated_count = 0; - model->search_in_progress = FALSE; - model->editable = FALSE; - model->editable_set = FALSE; - model->first_get_view = TRUE; +addressbook_model_client_notify_readonly_cb (EClientCache *client_cache, + EClient *client, + GParamSpec *pspec, + EAddressbookModel *model) +{ + if (!E_IS_BOOK_CLIENT (client)) + return; + + if (E_BOOK_CLIENT (client) == model->priv->book_client) { + gboolean editable = !e_client_is_readonly (client); + e_addressbook_model_set_editable (model, editable); + } } static void -book_view_loaded (EBook *book, EBookStatus status, EBookView *book_view, gpointer closure) +client_view_ready_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - EAddressbookModel *model = closure; + EBookClient *book_client = E_BOOK_CLIENT (source_object); + EBookClientView *client_view = NULL; + EAddressbookModel *model = user_data; + GError *error = NULL; - remove_book_view(model); + if (!e_book_client_get_view_finish (book_client, result, &client_view, &error)) + client_view = NULL; - if (status != E_BOOK_STATUS_SUCCESS) { - e_addressbook_error_dialog (_("Error getting book view"), status); + if (error) { + eab_error_dialog (NULL, NULL, _("Error getting book view"), error); + g_error_free (error); return; } - model->book_view = book_view; - if (model->book_view) - gtk_object_ref(GTK_OBJECT(model->book_view)); - model->create_card_id = gtk_signal_connect(GTK_OBJECT(model->book_view), - "card_added", - GTK_SIGNAL_FUNC(create_card), - model); - model->remove_card_id = gtk_signal_connect(GTK_OBJECT(model->book_view), - "card_removed", - GTK_SIGNAL_FUNC(remove_card), - model); - model->modify_card_id = gtk_signal_connect(GTK_OBJECT(model->book_view), - "card_changed", - GTK_SIGNAL_FUNC(modify_card), - model); - model->status_message_id = gtk_signal_connect(GTK_OBJECT(model->book_view), - "status_message", - GTK_SIGNAL_FUNC(status_message), - model); - model->sequence_complete_id = gtk_signal_connect(GTK_OBJECT(model->book_view), - "sequence_complete", - GTK_SIGNAL_FUNC(sequence_complete), - model); - + remove_book_view (model); free_data (model); - model->search_in_progress = TRUE; - gtk_signal_emit (GTK_OBJECT (model), - e_addressbook_model_signals [MODEL_CHANGED]); - gtk_signal_emit (GTK_OBJECT (model), - e_addressbook_model_signals [STOP_STATE_CHANGED]); + model->priv->client_view = client_view; + if (model->priv->client_view) { + model->priv->create_contact_id = g_signal_connect ( + model->priv->client_view, "objects-added", + G_CALLBACK (view_create_contact_cb), model); + model->priv->remove_contact_id = g_signal_connect ( + model->priv->client_view, "objects-removed", + G_CALLBACK (view_remove_contact_cb), model); + model->priv->modify_contact_id = g_signal_connect ( + model->priv->client_view, "objects-modified", + G_CALLBACK (view_modify_contact_cb), model); + model->priv->status_message_id = g_signal_connect ( + model->priv->client_view, "progress", + G_CALLBACK (view_progress_cb), model); + model->priv->view_complete_id = g_signal_connect ( + model->priv->client_view, "complete", + G_CALLBACK (view_complete_cb), model); + + model->priv->search_in_progress = TRUE; + } + + g_signal_emit (model, signals[MODEL_CHANGED], 0); + g_signal_emit (model, signals[SEARCH_STARTED], 0); + g_signal_emit (model, signals[STOP_STATE_CHANGED], 0); + + if (model->priv->client_view) { + e_book_client_view_start (model->priv->client_view, &error); + + if (error != NULL) { + g_warning ( + "%s: Failed to start client view: %s", + G_STRFUNC, error->message); + g_error_free (error); + } + } } static gboolean -get_view (EAddressbookModel *model) -{ - if (model->book && model->query) { - if (model->first_get_view) { - char *capabilities; - capabilities = e_book_get_static_capabilities (model->book); - if (capabilities && strstr (capabilities, "do-initial-query")) { - e_book_get_book_view (model->book, model->query, book_view_loaded, model); +addressbook_model_idle_cb (EAddressbookModel *model) +{ + model->priv->client_view_idle_id = 0; + + if (model->priv->book_client && model->priv->query_str) { + remove_book_view (model); + + if (model->priv->first_get_view) { + model->priv->first_get_view = FALSE; + + if (e_client_check_capability (E_CLIENT (model->priv->book_client), "do-initial-query")) { + e_book_client_get_view ( + model->priv->book_client, model->priv->query_str, + NULL, client_view_ready_cb, model); } else { - remove_book_view(model); free_data (model); - gtk_signal_emit (GTK_OBJECT (model), - e_addressbook_model_signals [MODEL_CHANGED]); - gtk_signal_emit (GTK_OBJECT (model), - e_addressbook_model_signals [STOP_STATE_CHANGED]); + + g_signal_emit ( + model, signals[MODEL_CHANGED], 0); + g_signal_emit ( + model, signals[STOP_STATE_CHANGED], 0); } - model->first_get_view = FALSE; - g_free (capabilities); - } - else - e_book_get_book_view (model->book, model->query, book_view_loaded, model); + } else + e_book_client_get_view ( + model->priv->book_client, model->priv->query_str, + NULL, client_view_ready_cb, model); + } - model->get_view_idle = 0; + g_object_unref (model); + return FALSE; } -ECard * -e_addressbook_model_get_card(EAddressbookModel *model, - int row) +static gboolean +remove_status_cb (gpointer data) { - if (model->data && 0 <= row && row < model->data_count) { - ECard *card; - card = e_card_duplicate (model->data[row]); - return card; + EAddressbookModel *model = data; + + g_return_val_if_fail (model != NULL, FALSE); + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), FALSE); + + g_signal_emit (model, signals[STATUS_MESSAGE], 0, NULL, -1); + model->priv->remove_status_id = 0; + + return FALSE; +} + +static void +addressbook_model_set_client_cache (EAddressbookModel *model, + EClientCache *client_cache) +{ + g_return_if_fail (E_IS_CLIENT_CACHE (client_cache)); + g_return_if_fail (model->priv->client_cache == NULL); + + model->priv->client_cache = g_object_ref (client_cache); +} + +static void +addressbook_model_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CLIENT: + e_addressbook_model_set_client ( + E_ADDRESSBOOK_MODEL (object), + g_value_get_object (value)); + return; + + case PROP_CLIENT_CACHE: + addressbook_model_set_client_cache ( + E_ADDRESSBOOK_MODEL (object), + g_value_get_object (value)); + return; + + case PROP_EDITABLE: + e_addressbook_model_set_editable ( + E_ADDRESSBOOK_MODEL (object), + g_value_get_boolean (value)); + return; + + case PROP_QUERY: + e_addressbook_model_set_query ( + E_ADDRESSBOOK_MODEL (object), + g_value_get_string (value)); + return; } - return NULL; + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } -const ECard * -e_addressbook_model_peek_card(EAddressbookModel *model, - int row) +static void +addressbook_model_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - if (model->data && 0 <= row && row < model->data_count) { - return model->data[row]; + switch (property_id) { + case PROP_CLIENT: + g_value_set_object ( + value, e_addressbook_model_get_client ( + E_ADDRESSBOOK_MODEL (object))); + return; + + case PROP_CLIENT_CACHE: + g_value_set_object ( + value, e_addressbook_model_get_client_cache ( + E_ADDRESSBOOK_MODEL (object))); + return; + + case PROP_EDITABLE: + g_value_set_boolean ( + value, e_addressbook_model_get_editable ( + E_ADDRESSBOOK_MODEL (object))); + return; + + case PROP_QUERY: + g_value_set_string ( + value, e_addressbook_model_get_query ( + E_ADDRESSBOOK_MODEL (object))); + return; } - return NULL; + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -e_addressbook_model_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) +addressbook_model_dispose (GObject *object) { - EAddressbookModel *model; + EAddressbookModel *model = E_ADDRESSBOOK_MODEL (object); - model = E_ADDRESSBOOK_MODEL (o); - - switch (arg_id){ - case ARG_BOOK: - if (model->book) { - if (model->writable_status_id) - gtk_signal_disconnect(GTK_OBJECT (model->book), - model->writable_status_id); - model->writable_status_id = 0; - - if (model->backend_died_id) - gtk_signal_disconnect(GTK_OBJECT (model->book), - model->backend_died_id); - model->backend_died_id = 0; - - gtk_object_unref(GTK_OBJECT(model->book)); - } - model->book = E_BOOK(GTK_VALUE_OBJECT (*arg)); - if (model->book) { - model->first_get_view = TRUE; - gtk_object_ref(GTK_OBJECT(model->book)); - if (model->get_view_idle == 0) - model->get_view_idle = g_idle_add((GSourceFunc)get_view, model); - gtk_signal_connect (GTK_OBJECT(model->book), - "writable_status", - writable_status, model); - gtk_signal_connect (GTK_OBJECT(model->book), - "backend_died", - backend_died, model); - } - break; - case ARG_QUERY: - if (model->query) - g_free(model->query); - model->query = g_strdup(GTK_VALUE_STRING (*arg)); - if (model->get_view_idle == 0) - model->get_view_idle = g_idle_add((GSourceFunc)get_view, model); - break; - case ARG_EDITABLE: - model->editable = GTK_VALUE_BOOL (*arg); - model->editable_set = TRUE; - break; + remove_book_view (model); + free_data (model); + + if (model->priv->client_notify_readonly_handler_id > 0) { + g_signal_handler_disconnect ( + model->priv->client_cache, + model->priv->client_notify_readonly_handler_id); + model->priv->client_notify_readonly_handler_id = 0; } + + g_clear_object (&model->priv->client_cache); + g_clear_object (&model->priv->book_client); + + if (model->priv->query_str) { + g_free (model->priv->query_str); + model->priv->query_str = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_addressbook_model_parent_class)->dispose (object); } static void -e_addressbook_model_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +addressbook_model_finalize (GObject *object) { - EAddressbookModel *e_addressbook_model; + EAddressbookModelPrivate *priv; - e_addressbook_model = E_ADDRESSBOOK_MODEL (object); + priv = E_ADDRESSBOOK_MODEL_GET_PRIVATE (object); - switch (arg_id) { - case ARG_BOOK: - GTK_VALUE_OBJECT (*arg) = GTK_OBJECT(e_addressbook_model->book); - break; - case ARG_QUERY: - GTK_VALUE_STRING (*arg) = g_strdup(e_addressbook_model->query); - break; - case ARG_EDITABLE: - GTK_VALUE_BOOL (*arg) = e_addressbook_model->editable; - break; - default: - arg->type = GTK_TYPE_INVALID; - break; - } + g_ptr_array_free (priv->contacts, TRUE); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_addressbook_model_parent_class)->finalize (object); } -GtkType -e_addressbook_model_get_type (void) +static void +addressbook_model_constructed (GObject *object) { - static GtkType type = 0; + EAddressbookModel *model; + EClientCache *client_cache; + gulong handler_id; - if (!type){ - GtkTypeInfo info = { - "EAddressbookModel", - sizeof (EAddressbookModel), - sizeof (EAddressbookModelClass), - (GtkClassInitFunc) e_addressbook_model_class_init, - (GtkObjectInitFunc) e_addressbook_model_init, - NULL, /* reserved 1 */ - NULL, /* reserved 2 */ - (GtkClassInitFunc) NULL - }; + model = E_ADDRESSBOOK_MODEL (object); - type = gtk_type_unique (PARENT_TYPE, &info); - } + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_addressbook_model_parent_class)->constructed (object); - return type; + client_cache = e_addressbook_model_get_client_cache (model); + + handler_id = g_signal_connect ( + client_cache, "client-notify::readonly", + G_CALLBACK (addressbook_model_client_notify_readonly_cb), + model); + model->priv->client_notify_readonly_handler_id = handler_id; } -EAddressbookModel* -e_addressbook_model_new (void) +static void +e_addressbook_model_class_init (EAddressbookModelClass *class) { - EAddressbookModel *et; + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (EAddressbookModelPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = addressbook_model_set_property; + object_class->get_property = addressbook_model_get_property; + object_class->dispose = addressbook_model_dispose; + object_class->finalize = addressbook_model_finalize; + object_class->constructed = addressbook_model_constructed; + + g_object_class_install_property ( + object_class, + PROP_CLIENT, + g_param_spec_object ( + "client", + "EBookClient", + NULL, + E_TYPE_BOOK_CLIENT, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_CLIENT_CACHE, + g_param_spec_object ( + "client-cache", + "Client Cache", + "Shared EClient instances", + E_TYPE_CLIENT_CACHE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_EDITABLE, + g_param_spec_boolean ( + "editable", + "Editable", + NULL, + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_QUERY, + g_param_spec_string ( + "query", + "Query", + NULL, + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + signals[WRITABLE_STATUS] = g_signal_new ( + "writable_status", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookModelClass, writable_status), + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, + G_TYPE_BOOLEAN); + + signals[STATUS_MESSAGE] = g_signal_new ( + "status_message", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookModelClass, status_message), + NULL, NULL, + e_marshal_VOID__STRING_INT, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_INT); + + signals[SEARCH_STARTED] = g_signal_new ( + "search_started", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookModelClass, search_started), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[SEARCH_RESULT] = g_signal_new ( + "search_result", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookModelClass, search_result), + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + G_TYPE_ERROR); + + signals[FOLDER_BAR_MESSAGE] = g_signal_new ( + "folder_bar_message", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookModelClass, folder_bar_message), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); + + signals[CONTACT_ADDED] = g_signal_new ( + "contact_added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookModelClass, contact_added), + NULL, NULL, + e_marshal_NONE__INT_INT, + G_TYPE_NONE, 2, + G_TYPE_INT, + G_TYPE_INT); + + signals[CONTACTS_REMOVED] = g_signal_new ( + "contacts_removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookModelClass, contacts_removed), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); + + signals[CONTACT_CHANGED] = g_signal_new ( + "contact_changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookModelClass, contact_changed), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, + G_TYPE_INT); + + signals[MODEL_CHANGED] = g_signal_new ( + "model_changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookModelClass, model_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[STOP_STATE_CHANGED] = g_signal_new ( + "stop_state_changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookModelClass, stop_state_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} - et = gtk_type_new (e_addressbook_model_get_type ()); - - return et; +static void +e_addressbook_model_init (EAddressbookModel *model) +{ + model->priv = E_ADDRESSBOOK_MODEL_GET_PRIVATE (model); + model->priv->contacts = g_ptr_array_new (); + model->priv->first_get_view = TRUE; } -void e_addressbook_model_stop (EAddressbookModel *model) +EAddressbookModel * +e_addressbook_model_new (EClientCache *client_cache) { - remove_book_view(model); - gtk_signal_emit (GTK_OBJECT (model), - e_addressbook_model_signals [STOP_STATE_CHANGED]); - gtk_signal_emit (GTK_OBJECT (model), - e_addressbook_model_signals [STATUS_MESSAGE], - "Search Interrupted."); + g_return_val_if_fail (E_IS_CLIENT_CACHE (client_cache), NULL); + + return g_object_new ( + E_TYPE_ADDRESSBOOK_MODEL, + "client-cache", client_cache, NULL); +} + +EClientCache * +e_addressbook_model_get_client_cache (EAddressbookModel *model) +{ + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL); + + return model->priv->client_cache; +} + +EContact * +e_addressbook_model_get_contact (EAddressbookModel *model, + gint row) +{ + GPtrArray *array; + + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL); + + array = model->priv->contacts; + + if (0 <= row && row < array->len) + return e_contact_duplicate (array->pdata[row]); + + return NULL; +} + +void +e_addressbook_model_stop (EAddressbookModel *model) +{ + const gchar *message; + + g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model)); + + remove_book_view (model); + + message = _("Search Interrupted"); + g_signal_emit (model, signals[STOP_STATE_CHANGED], 0); + g_signal_emit (model, signals[STATUS_MESSAGE], 0, message, -1); + + if (!model->priv->remove_status_id) + model->priv->remove_status_id = + g_timeout_add_seconds (3, remove_status_cb, model); } gboolean e_addressbook_model_can_stop (EAddressbookModel *model) { - return model->search_in_progress; + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), FALSE); + + return model->priv->search_in_progress; } void e_addressbook_model_force_folder_bar_message (EAddressbookModel *model) { + g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model)); + update_folder_bar_message (model); } -int -e_addressbook_model_card_count (EAddressbookModel *model) +gint +e_addressbook_model_contact_count (EAddressbookModel *model) +{ + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), 0); + + return model->priv->contacts->len; +} + +EContact * +e_addressbook_model_contact_at (EAddressbookModel *model, + gint index) +{ + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL); + + return model->priv->contacts->pdata[index]; +} + +gint +e_addressbook_model_find (EAddressbookModel *model, + EContact *contact) +{ + GPtrArray *array; + gint ii; + + /* XXX This searches for a particular EContact instance, + * as opposed to an equivalent but possibly different + * EContact instance. Might have to revise this in + * the future. */ + + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), -1); + g_return_val_if_fail (E_IS_CONTACT (contact), -1); + + array = model->priv->contacts; + for (ii = 0; ii < array->len; ii++) { + EContact *candidate = array->pdata[ii]; + + if (contact == candidate) + return ii; + } + + return -1; +} + +EBookClient * +e_addressbook_model_get_client (EAddressbookModel *model) { - return model->data_count; + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL); + + return model->priv->book_client; } -ECard * -e_addressbook_model_card_at (EAddressbookModel *model, int index) +void +e_addressbook_model_set_client (EAddressbookModel *model, + EBookClient *book_client) { - return model->data[index]; + gboolean editable; + + g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model)); + g_return_if_fail (E_IS_BOOK_CLIENT (book_client)); + + if (model->priv->book_client == book_client) + return; + + if (model->priv->book_client != NULL) + g_object_unref (model->priv->book_client); + + model->priv->book_client = g_object_ref (book_client); + model->priv->first_get_view = TRUE; + + editable = !e_client_is_readonly (E_CLIENT (book_client)); + e_addressbook_model_set_editable (model, editable); + + if (model->priv->client_view_idle_id == 0) + model->priv->client_view_idle_id = g_idle_add ( + (GSourceFunc) addressbook_model_idle_cb, + g_object_ref (model)); + + g_object_notify (G_OBJECT (model), "client"); } gboolean -e_addressbook_model_editable (EAddressbookModel *model) +e_addressbook_model_get_editable (EAddressbookModel *model) { - return model->editable; + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), FALSE); + + return model->priv->editable; } -EBook * -e_addressbook_model_get_ebook (EAddressbookModel *model) +void +e_addressbook_model_set_editable (EAddressbookModel *model, + gboolean editable) { - return model->book; + g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model)); + + if (model->priv->editable != editable) { + model->priv->editable = editable; + + g_signal_emit ( + model, signals[WRITABLE_STATUS], 0, + model->priv->editable); + + g_object_notify (G_OBJECT (model), "editable"); + } +} + +gchar * +e_addressbook_model_get_query (EAddressbookModel *model) +{ + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL); + + return model->priv->query_str; +} + +void +e_addressbook_model_set_query (EAddressbookModel *model, + const gchar *query) +{ + EBookQuery *book_query; + + g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model)); + + if (query == NULL) + book_query = e_book_query_any_field_contains (""); + else + book_query = e_book_query_from_string (query); + + /* also checks whether the query is a valid query string */ + if (!book_query) + return; + + if (model->priv->query_str != NULL) { + gchar *new_query; + + new_query = e_book_query_to_string (book_query); + + if (new_query && g_str_equal (model->priv->query_str, new_query)) { + g_free (new_query); + e_book_query_unref (book_query); + return; + } + + g_free (new_query); + } + + g_free (model->priv->query_str); + model->priv->query_str = e_book_query_to_string (book_query); + e_book_query_unref (book_query); + + if (model->priv->client_view_idle_id == 0) + model->priv->client_view_idle_id = g_idle_add ( + (GSourceFunc) addressbook_model_idle_cb, + g_object_ref (model)); + + g_object_notify (G_OBJECT (model), "query"); } diff --git a/addressbook/gui/widgets/e-addressbook-model.h b/addressbook/gui/widgets/e-addressbook-model.h index eb1004499a..c08fdb4319 100644 --- a/addressbook/gui/widgets/e-addressbook-model.h +++ b/addressbook/gui/widgets/e-addressbook-model.h @@ -1,80 +1,119 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -#ifndef _E_ADDRESSBOOK_MODEL_H_ -#define _E_ADDRESSBOOK_MODEL_H_ - -#include "addressbook/backend/ebook/e-book.h" -#include "addressbook/backend/ebook/e-book-view.h" -#include "addressbook/backend/ebook/e-card-simple.h" - -#define E_ADDRESSBOOK_MODEL_TYPE (e_addressbook_model_get_type ()) -#define E_ADDRESSBOOK_MODEL(o) (GTK_CHECK_CAST ((o), E_ADDRESSBOOK_MODEL_TYPE, EAddressbookModel)) -#define E_ADDRESSBOOK_MODEL_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_ADDRESSBOOK_MODEL_TYPE, EAddressbookModelClass)) -#define E_IS_ADDRESSBOOK_MODEL(o) (GTK_CHECK_TYPE ((o), E_ADDRESSBOOK_MODEL_TYPE)) -#define E_IS_ADDRESSBOOK_MODEL_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_ADDRESSBOOK_MODEL_TYPE)) +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_ADDRESSBOOK_MODEL_H +#define E_ADDRESSBOOK_MODEL_H + +#include <libebook/libebook.h> + +#include <e-util/e-util.h> + +/* Standard GObject macros */ +#define E_TYPE_ADDRESSBOOK_MODEL \ + (e_addressbook_model_get_type ()) +#define E_ADDRESSBOOK_MODEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_ADDRESSBOOK_MODEL, EAddressbookModel)) +#define E_ADDRESSBOOK_MODEL_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_ADDRESSBOOK_MODEL, EAddressbookModelClass)) +#define E_IS_ADDRESSBOOK_MODEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_ADDRESSBOOK_MODEL)) +#define E_IS_ADDRESSBOOK_MODEL_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_ADDRESSBOOK_MODEL)) +#define E_ADDRESSBOOK_MODEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_ADDRESSBOOK_MODEL)) + +G_BEGIN_DECLS typedef struct _EAddressbookModel EAddressbookModel; typedef struct _EAddressbookModelClass EAddressbookModelClass; +typedef struct _EAddressbookModelPrivate EAddressbookModelPrivate; struct _EAddressbookModel { - GtkObject parent; - - /* item specific fields */ - EBook *book; - char *query; - EBookView *book_view; - - int get_view_idle; - - ECard **data; - int data_count; - int allocated_count; - - int create_card_id, remove_card_id, modify_card_id, status_message_id, writable_status_id, sequence_complete_id, backend_died_id; - - guint search_in_progress : 1; - guint editable : 1; - guint editable_set : 1; - guint first_get_view : 1; + GObject parent; + EAddressbookModelPrivate *priv; }; - struct _EAddressbookModelClass { - GtkObjectClass parent_class; - - /* - * Signals - */ - void (*writable_status) (EAddressbookModel *model, gboolean writable); - void (*search_result) (EAddressbookModel *model, EBookViewStatus status); - void (*status_message) (EAddressbookModel *model, const gchar *message); - void (*folder_bar_message) (EAddressbookModel *model, const gchar *message); - void (*card_added) (EAddressbookModel *model, gint index, gint count); - void (*card_removed) (EAddressbookModel *model, gint index); - void (*card_changed) (EAddressbookModel *model, gint index); - void (*model_changed) (EAddressbookModel *model); - void (*stop_state_changed) (EAddressbookModel *model); - void (*backend_died) (EAddressbookModel *model); + GObjectClass parent_class; + + /* Signals */ + void (*writable_status) (EAddressbookModel *model, + gboolean writable); + void (*search_started) (EAddressbookModel *model); + void (*search_result) (EAddressbookModel *model, + const GError *error); + void (*status_message) (EAddressbookModel *model, + const gchar *message, + gint percent); + void (*folder_bar_message) (EAddressbookModel *model, + const gchar *message); + void (*contact_added) (EAddressbookModel *model, + gint index, + gint count); + void (*contacts_removed) (EAddressbookModel *model, + gpointer id_list); + void (*contact_changed) (EAddressbookModel *model, + gint index); + void (*model_changed) (EAddressbookModel *model); + void (*stop_state_changed) (EAddressbookModel *model); }; - -GtkType e_addressbook_model_get_type (void); -EAddressbookModel *e_addressbook_model_new (void); +GType e_addressbook_model_get_type (void); +EAddressbookModel * + e_addressbook_model_new (EClientCache *client_cache); +EClientCache * e_addressbook_model_get_client_cache + (EAddressbookModel *model); /* Returns object with ref count of 1. */ -ECard *e_addressbook_model_get_card (EAddressbookModel *model, - int row); -const ECard *e_addressbook_model_peek_card (EAddressbookModel *model, - int row); -EBook *e_addressbook_model_get_ebook (EAddressbookModel *model); - -void e_addressbook_model_stop (EAddressbookModel *model); -gboolean e_addressbook_model_can_stop (EAddressbookModel *model); - -void e_addressbook_model_force_folder_bar_message (EAddressbookModel *model); - -int e_addressbook_model_card_count (EAddressbookModel *model); -ECard *e_addressbook_model_card_at (EAddressbookModel *model, - int index); -gboolean e_addressbook_model_editable (EAddressbookModel *model); - -#endif /* _E_ADDRESSBOOK_MODEL_H_ */ +EContact * e_addressbook_model_get_contact (EAddressbookModel *model, + gint row); + +void e_addressbook_model_stop (EAddressbookModel *model); +gboolean e_addressbook_model_can_stop (EAddressbookModel *model); + +void e_addressbook_model_force_folder_bar_message + (EAddressbookModel *model); + +gint e_addressbook_model_contact_count + (EAddressbookModel *model); +EContact * e_addressbook_model_contact_at (EAddressbookModel *model, + gint index); +gint e_addressbook_model_find (EAddressbookModel *model, + EContact *contact); +EBookClient * e_addressbook_model_get_client (EAddressbookModel *model); +void e_addressbook_model_set_client (EAddressbookModel *model, + EBookClient *book_client); +gboolean e_addressbook_model_get_editable + (EAddressbookModel *model); +void e_addressbook_model_set_editable + (EAddressbookModel *model, + gboolean editable); +gchar * e_addressbook_model_get_query (EAddressbookModel *model); +void e_addressbook_model_set_query (EAddressbookModel *model, + const gchar *query); + +G_END_DECLS + +#endif /* E_ADDRESSBOOK_MODEL_H */ diff --git a/addressbook/gui/widgets/e-addressbook-reflow-adapter.c b/addressbook/gui/widgets/e-addressbook-reflow-adapter.c index 16e61a2d89..48ed73bb25 100644 --- a/addressbook/gui/widgets/e-addressbook-reflow-adapter.c +++ b/addressbook/gui/widgets/e-addressbook-reflow-adapter.c @@ -1,452 +1,613 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - - +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + */ + +#ifdef HAVE_CONFIG_H #include <config.h> +#endif +#include <string.h> + +#include <glib/gi18n.h> #include "e-addressbook-reflow-adapter.h" #include "e-addressbook-model.h" -#include "e-addressbook-view.h" -#include "e-addressbook-util.h" - -#include <gal/util/e-i18n.h> +#include "eab-gui-util.h" #include "e-minicard.h" -#include <gal/widgets/e-unicode.h> -#include <gal/widgets/e-font.h> -#include <gal/widgets/e-popup-menu.h> -#include <gal/widgets/e-gui-utils.h> -#include <gal/unicode/gunicode.h> -#include "e-contact-save-as.h" +#include <e-util/e-util.h> #include "addressbook/printing/e-contact-print.h" -#include "addressbook/printing/e-contact-print-envelope.h" +#define E_ADDRESSBOOK_REFLOW_ADAPTER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ADDRESSBOOK_REFLOW_ADAPTER, EAddressbookReflowAdapterPrivate)) struct _EAddressbookReflowAdapterPrivate { EAddressbookModel *model; - - int create_card_id, remove_card_id, modify_card_id, model_changed_id; -}; -#define PARENT_TYPE e_reflow_model_get_type() -EReflowModel *parent_class; + gboolean loading; + + gint create_contact_id, remove_contact_id, modify_contact_id, model_changed_id; + gint search_started_id, search_result_id; +}; #define d(x) enum { - ARG_0, - ARG_BOOK, - ARG_QUERY, - ARG_EDITABLE, - ARG_MODEL, + PROP_0, + PROP_CLIENT, + PROP_QUERY, + PROP_EDITABLE, + PROP_MODEL }; enum { DRAG_BEGIN, + OPEN_CONTACT, LAST_SIGNAL }; -static guint e_addressbook_reflow_adapter_signals [LAST_SIGNAL] = {0, }; +static guint signals[LAST_SIGNAL] = {0, }; + +G_DEFINE_TYPE ( + EAddressbookReflowAdapter, + e_addressbook_reflow_adapter, + E_TYPE_REFLOW_MODEL) static void -unlink_model(EAddressbookReflowAdapter *adapter) +unlink_model (EAddressbookReflowAdapter *adapter) { EAddressbookReflowAdapterPrivate *priv = adapter->priv; - gtk_signal_disconnect(GTK_OBJECT (priv->model), - priv->create_card_id); - gtk_signal_disconnect(GTK_OBJECT (priv->model), - priv->remove_card_id); - gtk_signal_disconnect(GTK_OBJECT (priv->model), - priv->modify_card_id); - - priv->create_card_id = 0; - priv->remove_card_id = 0; - priv->modify_card_id = 0; + if (priv->model && priv->create_contact_id) + g_signal_handler_disconnect ( + priv->model, + priv->create_contact_id); + if (priv->model && priv->remove_contact_id) + g_signal_handler_disconnect ( + priv->model, + priv->remove_contact_id); + if (priv->model && priv->modify_contact_id) + g_signal_handler_disconnect ( + priv->model, + priv->modify_contact_id); + if (priv->model && priv->model_changed_id) + g_signal_handler_disconnect ( + priv->model, + priv->model_changed_id); + if (priv->model && priv->search_started_id) + g_signal_handler_disconnect ( + priv->model, + priv->search_started_id); + if (priv->model && priv->search_result_id) + g_signal_handler_disconnect ( + priv->model, + priv->search_result_id); + + priv->create_contact_id = 0; + priv->remove_contact_id = 0; + priv->modify_contact_id = 0; + priv->model_changed_id = 0; + priv->search_started_id = 0; + priv->search_result_id = 0; - gtk_object_unref(GTK_OBJECT(priv->model)); + if (priv->model) + g_object_unref (priv->model); priv->model = NULL; } - -static int -count_lines (const gchar *text) +static gint +text_height (PangoLayout *layout, + const gchar *text) { - int num_lines = 1; - gunichar unival; + gint height; - for (text = e_unicode_get_utf8 (text, &unival); (unival && text); text = e_unicode_get_utf8 (text, &unival)) { - if (unival == '\n') { - num_lines ++; - } - } + pango_layout_set_text (layout, text, -1); - return num_lines; -} - -static int -text_height (GnomeCanvas *canvas, const gchar *text) -{ - EFont *font = e_font_from_gdk_font (((GtkWidget *) canvas)->style->font); - gint height = e_font_height (font) * count_lines (text) / canvas->pixels_per_unit; + pango_layout_get_pixel_size (layout, NULL, &height); - e_font_unref (font); return height; } static void -addressbook_finalize(GtkObject *object) +addressbook_dispose (GObject *object) { - EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER(object); + EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER (object); unlink_model (adapter); } static void -addressbook_set_width (EReflowModel *erm, int width) +addressbook_set_width (EReflowModel *erm, + gint width) { } /* This function returns the number of items in our EReflowModel. */ -static int +static gint addressbook_count (EReflowModel *erm) { - EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER(erm); + EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER (erm); EAddressbookReflowAdapterPrivate *priv = adapter->priv; - return e_addressbook_model_card_count (priv->model); + return e_addressbook_model_contact_count (priv->model); } -/* This function returns the number of items in our EReflowModel. */ -static int -addressbook_height (EReflowModel *erm, int i, GnomeCanvasGroup *parent) +/* This function returns the height of the minicontact in question */ +static gint +addressbook_height (EReflowModel *erm, + gint i, + GnomeCanvasGroup *parent) { - EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER(erm); + EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER (erm); EAddressbookReflowAdapterPrivate *priv = adapter->priv; - /* FIXME */ - ECardSimpleField field; - int count = 0; - int height; - char *string; - ECardSimple *simple = e_card_simple_new (e_addressbook_model_card_at (priv->model, i)); + EContactField field; + gint count = 0; + gchar *string; + EContact *contact = (EContact *) e_addressbook_model_contact_at (priv->model, i); + PangoLayout *layout; + gint height; - string = e_card_simple_get(simple, E_CARD_SIMPLE_FIELD_FILE_AS); - height = text_height (GNOME_CANVAS_ITEM (parent)->canvas, string ? string : "") + 10.0; - g_free(string); + layout = gtk_widget_create_pango_layout ( + GTK_WIDGET (GNOME_CANVAS_ITEM (parent)->canvas), ""); - for(field = E_CARD_SIMPLE_FIELD_FULL_NAME; field != E_CARD_SIMPLE_FIELD_LAST_SIMPLE_STRING && count < 5; field++) { + string = e_contact_get (contact, E_CONTACT_FILE_AS); + height = text_height (layout, string ? string : "") + 10.0; + g_free (string); - if (field == E_CARD_SIMPLE_FIELD_FAMILY_NAME) + for (field = E_CONTACT_FULL_NAME; + field != E_CONTACT_LAST_SIMPLE_STRING && count < 5; field++) { + + if (field == E_CONTACT_FAMILY_NAME || field == E_CONTACT_GIVEN_NAME) continue; - string = e_card_simple_get(simple, field); + string = e_contact_get (contact, field); if (string && *string) { - int this_height; - int field_text_height; + gint this_height; + gint field_text_height; - this_height = text_height (GNOME_CANVAS_ITEM (parent)->canvas, e_card_simple_get_name(simple, field)); + this_height = text_height (layout, e_contact_pretty_name (field)); - field_text_height = text_height (GNOME_CANVAS_ITEM (parent)->canvas, string); + field_text_height = text_height (layout, string); if (this_height < field_text_height) this_height = field_text_height; this_height += 3; height += this_height; - count ++; + count++; } g_free (string); } height += 2; - gtk_object_unref (GTK_OBJECT (simple)); + g_object_unref (layout); return height; } -static int -addressbook_compare (EReflowModel *erm, int n1, int n2) +static GHashTable * +addressbook_create_cmp_cache (EReflowModel *erm) +{ + EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER (erm); + EAddressbookReflowAdapterPrivate *priv = adapter->priv; + GHashTable *cmp_cache; + gint ii, count; + + count = e_reflow_model_count (erm); + + if (priv->loading || count <= 0) + return NULL; + + cmp_cache = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); + + for (ii = 0; ii < count; ii++) { + EContact *contact; + + contact = (EContact *) + e_addressbook_model_contact_at (priv->model, ii); + if (contact != NULL) { + const gchar *file_as; + + file_as = e_contact_get_const ( + contact, E_CONTACT_FILE_AS); + if (file_as != NULL) + g_hash_table_insert ( + cmp_cache, GINT_TO_POINTER (ii), + g_utf8_collate_key (file_as, -1)); + } + } + + return cmp_cache; +} + +static gint +addressbook_compare (EReflowModel *erm, + gint n1, + gint n2, + GHashTable *cmp_cache) { - EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER(erm); + EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER (erm); EAddressbookReflowAdapterPrivate *priv = adapter->priv; - ECard *card1, *card2; - - card1 = e_addressbook_model_card_at (priv->model, n1); - card2 = e_addressbook_model_card_at (priv->model, n2); - - if (card1 && card2) { - char *file_as1, *file_as2; - file_as1 = card1->file_as; - file_as2 = card2->file_as; - if (file_as1 && file_as2) - return g_utf8_collate(file_as1, file_as2); - if (file_as1) + EContact *contact1, *contact2; + + if (priv->loading) { + return n1 - n2; + } + else { + contact1 = (EContact *) e_addressbook_model_contact_at (priv->model, n1); + contact2 = (EContact *) e_addressbook_model_contact_at (priv->model, n2); + + if (contact1 && contact2) { + const gchar *file_as1, *file_as2; + const gchar *uid1, *uid2; + + if (cmp_cache) { + file_as1 = g_hash_table_lookup (cmp_cache, GINT_TO_POINTER (n1)); + file_as2 = g_hash_table_lookup (cmp_cache, GINT_TO_POINTER (n2)); + if (file_as1 && file_as2) + return strcmp (file_as1, file_as2); + } else { + file_as1 = e_contact_get_const (contact1, E_CONTACT_FILE_AS); + file_as2 = e_contact_get_const (contact2, E_CONTACT_FILE_AS); + if (file_as1 && file_as2) + return g_utf8_collate (file_as1, file_as2); + } + if (file_as1) + return -1; + if (file_as2) + return 1; + uid1 = e_contact_get_const (contact1, E_CONTACT_UID); + uid2 = e_contact_get_const (contact2, E_CONTACT_UID); + if (uid1 && uid2) + return strcmp (uid1, uid2); + if (uid1) + return -1; + if (uid2) + return 1; + } + if (contact1) return -1; - if (file_as2) + if (contact2) return 1; - return strcmp(e_card_get_id(card1), e_card_get_id(card2)); + return 0; } - if (card1) - return -1; - if (card2) - return 1; - return 0; } -static int -adapter_drag_begin (EMinicard *card, GdkEvent *event, EAddressbookReflowAdapter *adapter) +static gint +adapter_drag_begin (EMinicard *card, + GdkEvent *event, + EAddressbookReflowAdapter *adapter) { gint ret_val = 0; - gtk_signal_emit (GTK_OBJECT(adapter), - e_addressbook_reflow_adapter_signals[DRAG_BEGIN], - event, &ret_val); + g_signal_emit ( + adapter, + signals[DRAG_BEGIN], 0, + event, &ret_val); return ret_val; } +static void +adapter_open_contact (EMinicard *card, + EContact *contact, + EAddressbookReflowAdapter *adapter) +{ + g_signal_emit (adapter, signals[OPEN_CONTACT], 0, contact); +} + static GnomeCanvasItem * -addressbook_incarnate (EReflowModel *erm, int i, GnomeCanvasGroup *parent) +addressbook_incarnate (EReflowModel *erm, + gint i, + GnomeCanvasGroup *parent) { - EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER(erm); + EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER (erm); EAddressbookReflowAdapterPrivate *priv = adapter->priv; GnomeCanvasItem *item; - item = gnome_canvas_item_new(parent, - e_minicard_get_type(), - "card", e_addressbook_model_card_at (priv->model, i), - "editable", e_addressbook_model_editable (priv->model), - NULL); + item = gnome_canvas_item_new ( + parent, e_minicard_get_type (), + "contact", e_addressbook_model_contact_at (priv->model, i), + "editable", e_addressbook_model_get_editable (priv->model), + NULL); -#if 0 - gtk_signal_connect (GTK_OBJECT (item), "selected", - GTK_SIGNAL_FUNC(card_selected), emvm); -#endif + g_signal_connect ( + item, "drag_begin", + G_CALLBACK (adapter_drag_begin), adapter); - gtk_signal_connect (GTK_OBJECT (item), "drag_begin", - GTK_SIGNAL_FUNC(adapter_drag_begin), adapter); + g_signal_connect ( + item, "open-contact", + G_CALLBACK (adapter_open_contact), adapter); return item; } static void -addressbook_reincarnate (EReflowModel *erm, int i, GnomeCanvasItem *item) +addressbook_reincarnate (EReflowModel *erm, + gint i, + GnomeCanvasItem *item) { - EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER(erm); + EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER (erm); EAddressbookReflowAdapterPrivate *priv = adapter->priv; - gnome_canvas_item_set(item, - "card", e_addressbook_model_card_at (priv->model, i), - NULL); + gnome_canvas_item_set ( + item, + "contact", e_addressbook_model_contact_at (priv->model, i), + NULL); } +static void +create_contact (EAddressbookModel *model, + gint index, + gint count, + EAddressbookReflowAdapter *adapter) +{ + e_reflow_model_items_inserted ( + E_REFLOW_MODEL (adapter), + index, + count); +} + +static void +remove_contacts (EAddressbookModel *model, + gpointer data, + EAddressbookReflowAdapter *adapter) +{ + GArray *indices = (GArray *) data; + gint count = indices->len; + + if (count == 1) + e_reflow_model_item_removed ( + E_REFLOW_MODEL (adapter), + g_array_index (indices, gint, 0)); + else + e_reflow_model_changed (E_REFLOW_MODEL (adapter)); +} static void -create_card(EAddressbookModel *model, - gint index, gint count, - EAddressbookReflowAdapter *adapter) +modify_contact (EAddressbookModel *model, + gint index, + EAddressbookReflowAdapter *adapter) { - e_reflow_model_items_inserted (E_REFLOW_MODEL (adapter), - index, - count); + e_reflow_model_item_changed (E_REFLOW_MODEL (adapter), index); } static void -remove_card(EAddressbookModel *model, - gint index, - EAddressbookReflowAdapter *adapter) +model_changed (EAddressbookModel *model, + EAddressbookReflowAdapter *adapter) { e_reflow_model_changed (E_REFLOW_MODEL (adapter)); } static void -modify_card(EAddressbookModel *model, - gint index, - EAddressbookReflowAdapter *adapter) +search_started (EAddressbookModel *model, + EAddressbookReflowAdapter *adapter) { - e_reflow_model_item_changed (E_REFLOW_MODEL (adapter), index); + EAddressbookReflowAdapterPrivate *priv = adapter->priv; + + priv->loading = TRUE; } static void -model_changed(EAddressbookModel *model, - EAddressbookReflowAdapter *adapter) +search_result (EAddressbookModel *model, + const GError *error, + EAddressbookReflowAdapter *adapter) { - e_reflow_model_changed (E_REFLOW_MODEL (adapter)); + EAddressbookReflowAdapterPrivate *priv = adapter->priv; + + priv->loading = FALSE; + + e_reflow_model_comparison_changed (E_REFLOW_MODEL (adapter)); } static void -addressbook_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) +addressbook_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER(o); + EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER (object); EAddressbookReflowAdapterPrivate *priv = adapter->priv; - switch (arg_id){ - case ARG_BOOK: - gtk_object_set (GTK_OBJECT (priv->model), - "book", GTK_VALUE_OBJECT (*arg), - NULL); + switch (property_id) { + case PROP_CLIENT: + g_object_set ( + priv->model, + "client", g_value_get_object (value), + NULL); break; - case ARG_QUERY: - gtk_object_set (GTK_OBJECT (priv->model), - "query", GTK_VALUE_STRING (*arg), - NULL); + case PROP_QUERY: + g_object_set ( + priv->model, + "query", g_value_get_string (value), + NULL); break; - case ARG_EDITABLE: - gtk_object_set (GTK_OBJECT (priv->model), - "editable", GTK_VALUE_BOOL (*arg), - NULL); + case PROP_EDITABLE: + g_object_set ( + priv->model, + "editable", g_value_get_boolean (value), + NULL); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void -addressbook_get_arg (GtkObject *o, GtkArg *arg, guint arg_id) +addressbook_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER(o); + EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER (object); EAddressbookReflowAdapterPrivate *priv = adapter->priv; - switch (arg_id) { - case ARG_BOOK: { - EBook *book; - gtk_object_get (GTK_OBJECT (priv->model), - "book", &book, - NULL); - if (book) - GTK_VALUE_OBJECT (*arg) = GTK_OBJECT(book); - else - GTK_VALUE_OBJECT (*arg) = NULL; + switch (property_id) { + case PROP_CLIENT: { + g_object_get_property ( + G_OBJECT (priv->model), + "client", value); break; } - case ARG_QUERY: { - char *query; - gtk_object_get (GTK_OBJECT (priv->model), - "query", &query, - NULL); - GTK_VALUE_STRING (*arg) = query; + case PROP_QUERY: { + g_object_get_property ( + G_OBJECT (priv->model), + "query", value); break; } - case ARG_EDITABLE: { - gboolean editable; - gtk_object_get (GTK_OBJECT (priv->model), - "editable", &editable, - NULL); - GTK_VALUE_BOOL (*arg) = editable; + case PROP_EDITABLE: { + g_object_get_property ( + G_OBJECT (priv->model), + "editable", value); break; } - case ARG_MODEL: - if (priv->model) - GTK_VALUE_OBJECT (*arg) = GTK_OBJECT (priv->model); - else - GTK_VALUE_OBJECT (*arg) = NULL; + case PROP_MODEL: + g_value_set_object (value, priv->model); break; default: - arg->type = GTK_TYPE_INVALID; + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void -e_addressbook_reflow_adapter_class_init (GtkObjectClass *object_class) +e_addressbook_reflow_adapter_class_init (EAddressbookReflowAdapterClass *class) { - EReflowModelClass *model_class = (EReflowModelClass *) object_class; - - parent_class = gtk_type_class (PARENT_TYPE); - - object_class->set_arg = addressbook_set_arg; - object_class->get_arg = addressbook_get_arg; - object_class->finalize = addressbook_finalize; - - gtk_object_add_arg_type ("EAddressbookReflowAdapter::book", GTK_TYPE_OBJECT, - GTK_ARG_READWRITE, ARG_BOOK); - gtk_object_add_arg_type ("EAddressbookReflowAdapter::query", GTK_TYPE_STRING, - GTK_ARG_READWRITE, ARG_QUERY); - gtk_object_add_arg_type ("EAddressbookReflowAdapter::editable", GTK_TYPE_BOOL, - GTK_ARG_READWRITE, ARG_EDITABLE); - gtk_object_add_arg_type ("EAddressbookReflowAdapter::model", E_ADDRESSBOOK_MODEL_TYPE, - GTK_ARG_READABLE, ARG_MODEL); - - e_addressbook_reflow_adapter_signals [DRAG_BEGIN] = - gtk_signal_new ("drag_begin", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EAddressbookReflowAdapterClass, drag_begin), - gtk_marshal_INT__POINTER, - GTK_TYPE_INT, 1, GTK_TYPE_POINTER); - - - gtk_object_class_add_signals (object_class, e_addressbook_reflow_adapter_signals, LAST_SIGNAL); - - model_class->set_width = addressbook_set_width; - model_class->count = addressbook_count; - model_class->height = addressbook_height; - model_class->compare = addressbook_compare; - model_class->incarnate = addressbook_incarnate; - model_class->reincarnate = addressbook_reincarnate; + GObjectClass *object_class; + EReflowModelClass *reflow_model_class; + + g_type_class_add_private ( + class, sizeof (EAddressbookReflowAdapterPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = addressbook_set_property; + object_class->get_property = addressbook_get_property; + object_class->dispose = addressbook_dispose; + + reflow_model_class = E_REFLOW_MODEL_CLASS (class); + reflow_model_class->set_width = addressbook_set_width; + reflow_model_class->count = addressbook_count; + reflow_model_class->height = addressbook_height; + reflow_model_class->create_cmp_cache = addressbook_create_cmp_cache; + reflow_model_class->compare = addressbook_compare; + reflow_model_class->incarnate = addressbook_incarnate; + reflow_model_class->reincarnate = addressbook_reincarnate; + + g_object_class_install_property ( + object_class, + PROP_CLIENT, + g_param_spec_object ( + "client", + "EBookClient", + NULL, + E_TYPE_BOOK_CLIENT, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_QUERY, + g_param_spec_string ( + "query", + "Query", + NULL, + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_EDITABLE, + g_param_spec_boolean ( + "editable", + "Editable", + NULL, + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_MODEL, + g_param_spec_object ( + "model", + "Model", + NULL, + E_TYPE_ADDRESSBOOK_MODEL, + G_PARAM_READABLE)); + + signals[DRAG_BEGIN] = g_signal_new ( + "drag_begin", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookReflowAdapterClass, drag_begin), + NULL, NULL, + e_marshal_INT__POINTER, + G_TYPE_INT, 1, + G_TYPE_POINTER); + + signals[OPEN_CONTACT] = g_signal_new ( + "open-contact", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookReflowAdapterClass, open_contact), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CONTACT); } static void -e_addressbook_reflow_adapter_init (GtkObject *object) -{ - EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER(object); - EAddressbookReflowAdapterPrivate *priv; - - priv = adapter->priv = g_new0 (EAddressbookReflowAdapterPrivate, 1); - - priv->create_card_id = 0; - priv->remove_card_id = 0; - priv->modify_card_id = 0; - priv->model_changed_id = 0; -} - -GtkType -e_addressbook_reflow_adapter_get_type (void) +e_addressbook_reflow_adapter_init (EAddressbookReflowAdapter *adapter) { - static GtkType type = 0; - - if (!type){ - GtkTypeInfo info = { - "EAddressbookReflowAdapter", - sizeof (EAddressbookReflowAdapter), - sizeof (EAddressbookReflowAdapterClass), - (GtkClassInitFunc) e_addressbook_reflow_adapter_class_init, - (GtkObjectInitFunc) e_addressbook_reflow_adapter_init, - NULL, /* reserved 1 */ - NULL, /* reserved 2 */ - (GtkClassInitFunc) NULL - }; - - type = gtk_type_unique (PARENT_TYPE, &info); - } - - return type; + adapter->priv = E_ADDRESSBOOK_REFLOW_ADAPTER_GET_PRIVATE (adapter); } void e_addressbook_reflow_adapter_construct (EAddressbookReflowAdapter *adapter, - EAddressbookModel *model) + EAddressbookModel *model) { EAddressbookReflowAdapterPrivate *priv = adapter->priv; - priv->model = model; - gtk_object_ref (GTK_OBJECT (priv->model)); - - priv->create_card_id = gtk_signal_connect(GTK_OBJECT(priv->model), - "card_added", - GTK_SIGNAL_FUNC(create_card), - adapter); - priv->remove_card_id = gtk_signal_connect(GTK_OBJECT(priv->model), - "card_removed", - GTK_SIGNAL_FUNC(remove_card), - adapter); - priv->modify_card_id = gtk_signal_connect(GTK_OBJECT(priv->model), - "card_changed", - GTK_SIGNAL_FUNC(modify_card), - adapter); - priv->model_changed_id = gtk_signal_connect(GTK_OBJECT(priv->model), - "model_changed", - GTK_SIGNAL_FUNC(model_changed), - adapter); + priv->model = g_object_ref (model); + + priv->create_contact_id = g_signal_connect ( + priv->model, "contact_added", + G_CALLBACK (create_contact), adapter); + + priv->remove_contact_id = g_signal_connect ( + priv->model, "contacts_removed", + G_CALLBACK (remove_contacts), adapter); + + priv->modify_contact_id = g_signal_connect ( + priv->model, "contact_changed", + G_CALLBACK (modify_contact), adapter); + + priv->model_changed_id = g_signal_connect ( + priv->model, "model_changed", + G_CALLBACK (model_changed), adapter); + + priv->search_started_id = g_signal_connect ( + priv->model, "search_started", + G_CALLBACK (search_started), adapter); + + priv->search_result_id = g_signal_connect ( + priv->model, "search_result", + G_CALLBACK (search_result), adapter); } EReflowModel * @@ -454,19 +615,18 @@ e_addressbook_reflow_adapter_new (EAddressbookModel *model) { EAddressbookReflowAdapter *et; - et = gtk_type_new (e_addressbook_reflow_adapter_get_type ()); + et = g_object_new (E_TYPE_ADDRESSBOOK_REFLOW_ADAPTER, NULL); e_addressbook_reflow_adapter_construct (et, model); - return E_REFLOW_MODEL(et); + return E_REFLOW_MODEL (et); } - -ECard * -e_addressbook_reflow_adapter_get_card (EAddressbookReflowAdapter *adapter, - int index) +EContact * +e_addressbook_reflow_adapter_get_contact (EAddressbookReflowAdapter *adapter, + gint index) { EAddressbookReflowAdapterPrivate *priv = adapter->priv; - return e_addressbook_model_get_card (priv->model, index); + return e_addressbook_model_get_contact (priv->model, index); } diff --git a/addressbook/gui/widgets/e-addressbook-reflow-adapter.h b/addressbook/gui/widgets/e-addressbook-reflow-adapter.h index b3f6ab9c0d..fee217c2f1 100644 --- a/addressbook/gui/widgets/e-addressbook-reflow-adapter.h +++ b/addressbook/gui/widgets/e-addressbook-reflow-adapter.h @@ -1,19 +1,37 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + #ifndef _E_ADDRESSBOOK_REFLOW_ADAPTER_H_ #define _E_ADDRESSBOOK_REFLOW_ADAPTER_H_ -#include <gal/widgets/e-reflow-model.h> -#include <gal/widgets/e-selection-model.h> +#include <libebook/libebook.h> + +#include <e-util/e-util.h> + #include "e-addressbook-model.h" -#include "addressbook/backend/ebook/e-book.h" -#include "addressbook/backend/ebook/e-book-view.h" -#include "addressbook/backend/ebook/e-card.h" -#define E_ADDRESSBOOK_REFLOW_ADAPTER_TYPE (e_addressbook_reflow_adapter_get_type ()) -#define E_ADDRESSBOOK_REFLOW_ADAPTER(o) (GTK_CHECK_CAST ((o), E_ADDRESSBOOK_REFLOW_ADAPTER_TYPE, EAddressbookReflowAdapter)) -#define E_ADDRESSBOOK_REFLOW_ADAPTER_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_ADDRESSBOOK_REFLOW_ADAPTER_TYPE, EAddressbookReflowAdapterClass)) -#define E_IS_ADDRESSBOOK_REFLOW_ADAPTER(o) (GTK_CHECK_TYPE ((o), E_ADDRESSBOOK_REFLOW_ADAPTER_TYPE)) -#define E_IS_ADDRESSBOOK_REFLOW_ADAPTER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_ADDRESSBOOK_REFLOW_ADAPTER_TYPE)) +#define E_TYPE_ADDRESSBOOK_REFLOW_ADAPTER (e_addressbook_reflow_adapter_get_type ()) +#define E_ADDRESSBOOK_REFLOW_ADAPTER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_ADDRESSBOOK_REFLOW_ADAPTER, EAddressbookReflowAdapter)) +#define E_ADDRESSBOOK_REFLOW_ADAPTER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), E_TYPE_ADDRESSBOOK_REFLOW_ADAPTER, EAddressbookReflowAdapterClass)) +#define E_IS_ADDRESSBOOK_REFLOW_ADAPTER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_ADDRESSBOOK_REFLOW_ADAPTER)) +#define E_IS_ADDRESSBOOK_REFLOW_ADAPTER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_ADDRESSBOOK_REFLOW_ADAPTER)) typedef struct _EAddressbookReflowAdapter EAddressbookReflowAdapter; typedef struct _EAddressbookReflowAdapterPrivate EAddressbookReflowAdapterPrivate; @@ -25,23 +43,24 @@ struct _EAddressbookReflowAdapter { EAddressbookReflowAdapterPrivate *priv; }; - struct _EAddressbookReflowAdapterClass { EReflowModelClass parent_class; /* * Signals */ - gint (* drag_begin) (EAddressbookReflowAdapter *adapter, GdkEvent *event); + gint (*drag_begin) (EAddressbookReflowAdapter *adapter, + GdkEvent *event); + void (*open_contact) (EAddressbookReflowAdapter *adapter, + EContact *contact); }; - -GtkType e_addressbook_reflow_adapter_get_type (void); +GType e_addressbook_reflow_adapter_get_type (void); void e_addressbook_reflow_adapter_construct (EAddressbookReflowAdapter *adapter, EAddressbookModel *model); EReflowModel *e_addressbook_reflow_adapter_new (EAddressbookModel *model); /* Returns object with ref count of 1. */ -ECard *e_addressbook_reflow_adapter_get_card (EAddressbookReflowAdapter *adapter, - int index); +EContact *e_addressbook_reflow_adapter_get_contact (EAddressbookReflowAdapter *adapter, + gint index); #endif /* _E_ADDRESSBOOK_REFLOW_ADAPTER_H_ */ diff --git a/addressbook/gui/widgets/e-addressbook-selector.c b/addressbook/gui/widgets/e-addressbook-selector.c new file mode 100644 index 0000000000..7ef9ccd047 --- /dev/null +++ b/addressbook/gui/widgets/e-addressbook-selector.c @@ -0,0 +1,443 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-addressbook-selector.c + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "e-addressbook-selector.h" + +#include <e-util/e-util.h> + +#include <eab-book-util.h> +#include <eab-contact-merging.h> + +#define E_ADDRESSBOOK_SELECTOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ADDRESSBOOK_SELECTOR, EAddressbookSelectorPrivate)) + +typedef struct _MergeContext MergeContext; + +struct _EAddressbookSelectorPrivate { + EAddressbookView *current_view; +}; + +struct _MergeContext { + ESourceRegistry *registry; + EBookClient *source_client; + EBookClient *target_client; + + EContact *current_contact; + GSList *remaining_contacts; + guint pending_removals; + gboolean pending_adds; + + gint remove_from_source : 1; + gint copy_done : 1; +}; + +enum { + PROP_0, + PROP_CURRENT_VIEW +}; + +static GtkTargetEntry drag_types[] = { + { (gchar *) "text/x-source-vcard", 0, 0 } +}; + +G_DEFINE_TYPE ( + EAddressbookSelector, + e_addressbook_selector, + E_TYPE_CLIENT_SELECTOR) + +static void +merge_context_next (MergeContext *merge_context) +{ + GSList *list; + + merge_context->current_contact = NULL; + if (!merge_context->remaining_contacts) + return; + + list = merge_context->remaining_contacts; + merge_context->current_contact = list->data; + list = g_slist_delete_link (list, list); + merge_context->remaining_contacts = list; +} + +static MergeContext * +merge_context_new (ESourceRegistry *registry, + EBookClient *source_client, + EBookClient *target_client, + GSList *contact_list) +{ + MergeContext *merge_context; + + merge_context = g_slice_new0 (MergeContext); + merge_context->registry = g_object_ref (registry); + merge_context->source_client = source_client; + merge_context->target_client = target_client; + merge_context->remaining_contacts = contact_list; + merge_context_next (merge_context); + + return merge_context; +} + +static void +merge_context_free (MergeContext *merge_context) +{ + if (merge_context->registry != NULL) + g_object_unref (merge_context->registry); + + if (merge_context->source_client != NULL) + g_object_unref (merge_context->source_client); + + if (merge_context->target_client != NULL) + g_object_unref (merge_context->target_client); + + g_slice_free (MergeContext, merge_context); +} + +static void +addressbook_selector_removed_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + EBookClient *book_client = E_BOOK_CLIENT (source_object); + MergeContext *merge_context = user_data; + GError *error = NULL; + + e_book_client_remove_contact_finish (book_client, result, &error); + + if (error != NULL) { + g_warning ( + "%s: Failed to remove contact: %s", + G_STRFUNC, error->message); + g_error_free (error); + } + + merge_context->pending_removals--; + + if (merge_context->pending_adds) + return; + + if (merge_context->pending_removals > 0) + return; + + merge_context_free (merge_context); +} + +static void +addressbook_selector_merge_next_cb (EBookClient *book_client, + const GError *error, + const gchar *id, + gpointer closure) +{ + MergeContext *merge_context = closure; + + if (merge_context->remove_from_source && !error) { + /* Remove previous contact from source. */ + e_book_client_remove_contact ( + merge_context->source_client, + merge_context->current_contact, NULL, + addressbook_selector_removed_cb, merge_context); + merge_context->pending_removals++; + } + + g_object_unref (merge_context->current_contact); + + if (merge_context->remaining_contacts != NULL) { + merge_context_next (merge_context); + eab_merging_book_add_contact ( + merge_context->registry, + merge_context->target_client, + merge_context->current_contact, + addressbook_selector_merge_next_cb, merge_context); + + } else if (merge_context->pending_removals == 0) { + merge_context_free (merge_context); + } else + merge_context->pending_adds = FALSE; +} + +static void +addressbook_selector_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CURRENT_VIEW: + e_addressbook_selector_set_current_view ( + E_ADDRESSBOOK_SELECTOR (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +addressbook_selector_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CURRENT_VIEW: + g_value_set_object ( + value, + e_addressbook_selector_get_current_view ( + E_ADDRESSBOOK_SELECTOR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +addressbook_selector_dispose (GObject *object) +{ + EAddressbookSelectorPrivate *priv; + + priv = E_ADDRESSBOOK_SELECTOR_GET_PRIVATE (object); + + if (priv->current_view != NULL) { + g_object_unref (priv->current_view); + priv->current_view = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_addressbook_selector_parent_class)->dispose (object); +} + +static void +addressbook_selector_constructed (GObject *object) +{ + ESourceSelector *selector; + ESourceRegistry *registry; + ESource *source; + + selector = E_SOURCE_SELECTOR (object); + registry = e_source_selector_get_registry (selector); + source = e_source_registry_ref_default_address_book (registry); + e_source_selector_set_primary_selection (selector, source); + g_object_unref (source); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_addressbook_selector_parent_class)-> + constructed (object); +} + +static void +target_client_connect_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + MergeContext *merge_context = user_data; + EClient *client; + GError *error = NULL; + + g_return_if_fail (merge_context != NULL); + + client = e_client_selector_get_client_finish ( + E_CLIENT_SELECTOR (source_object), result, &error); + + /* Sanity check. */ + g_return_if_fail ( + ((client != NULL) && (error == NULL)) || + ((client == NULL) && (error != NULL))); + + if (error != NULL) { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_error_free (error); + } + + merge_context->target_client = client ? E_BOOK_CLIENT (client) : NULL; + + if (!merge_context->target_client) { + g_slist_foreach ( + merge_context->remaining_contacts, + (GFunc) g_object_unref, NULL); + g_slist_free (merge_context->remaining_contacts); + + merge_context_free (merge_context); + return; + } + + eab_merging_book_add_contact ( + merge_context->registry, + merge_context->target_client, + merge_context->current_contact, + addressbook_selector_merge_next_cb, merge_context); +} + +static gboolean +addressbook_selector_data_dropped (ESourceSelector *selector, + GtkSelectionData *selection_data, + ESource *destination, + GdkDragAction action, + guint info) +{ + EAddressbookSelectorPrivate *priv; + MergeContext *merge_context; + EAddressbookModel *model; + EBookClient *source_client; + ESourceRegistry *registry; + GSList *list; + const gchar *string; + gboolean remove_from_source; + + priv = E_ADDRESSBOOK_SELECTOR_GET_PRIVATE (selector); + g_return_val_if_fail (priv->current_view != NULL, FALSE); + + string = (const gchar *) gtk_selection_data_get_data (selection_data); + remove_from_source = (action == GDK_ACTION_MOVE); + + registry = e_source_selector_get_registry (selector); + + eab_source_and_contact_list_from_string ( + registry, string, NULL, &list); + + if (list == NULL) + return FALSE; + + model = e_addressbook_view_get_model (priv->current_view); + source_client = e_addressbook_model_get_client (model); + g_return_val_if_fail (E_IS_BOOK_CLIENT (source_client), FALSE); + + merge_context = merge_context_new ( + registry, g_object_ref (source_client), NULL, list); + merge_context->remove_from_source = remove_from_source; + merge_context->pending_adds = TRUE; + + e_client_selector_get_client ( + E_CLIENT_SELECTOR (selector), destination, NULL, + target_client_connect_cb, merge_context); + + return TRUE; +} + +static void +e_addressbook_selector_class_init (EAddressbookSelectorClass *class) +{ + GObjectClass *object_class; + ESourceSelectorClass *selector_class; + + g_type_class_add_private (class, sizeof (EAddressbookSelectorPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = addressbook_selector_set_property; + object_class->get_property = addressbook_selector_get_property; + object_class->dispose = addressbook_selector_dispose; + object_class->constructed = addressbook_selector_constructed; + + selector_class = E_SOURCE_SELECTOR_CLASS (class); + selector_class->data_dropped = addressbook_selector_data_dropped; + + g_object_class_install_property ( + object_class, + PROP_CURRENT_VIEW, + g_param_spec_object ( + "current-view", + NULL, + NULL, + E_TYPE_ADDRESSBOOK_VIEW, + G_PARAM_READWRITE)); +} + +static void +e_addressbook_selector_init (EAddressbookSelector *selector) +{ + selector->priv = E_ADDRESSBOOK_SELECTOR_GET_PRIVATE (selector); + + e_source_selector_set_show_colors ( + E_SOURCE_SELECTOR (selector), FALSE); + + e_source_selector_set_show_toggles ( + E_SOURCE_SELECTOR (selector), FALSE); + + gtk_drag_dest_set ( + GTK_WIDGET (selector), GTK_DEST_DEFAULT_ALL, + drag_types, G_N_ELEMENTS (drag_types), + GDK_ACTION_COPY | GDK_ACTION_MOVE); + + e_drag_dest_add_directory_targets (GTK_WIDGET (selector)); +} + +GtkWidget * +e_addressbook_selector_new (EClientCache *client_cache) +{ + ESourceRegistry *registry; + GtkWidget *widget; + + g_return_val_if_fail (E_IS_CLIENT_CACHE (client_cache), NULL); + + registry = e_client_cache_ref_registry (client_cache); + + widget = g_object_new ( + E_TYPE_ADDRESSBOOK_SELECTOR, + "client-cache", client_cache, + "extension-name", E_SOURCE_EXTENSION_ADDRESS_BOOK, + "registry", registry, NULL); + + g_object_unref (registry); + + return widget; +} + +EAddressbookView * +e_addressbook_selector_get_current_view (EAddressbookSelector *selector) +{ + g_return_val_if_fail (E_IS_ADDRESSBOOK_SELECTOR (selector), NULL); + + return selector->priv->current_view; +} + +void +e_addressbook_selector_set_current_view (EAddressbookSelector *selector, + EAddressbookView *current_view) +{ + /* XXX This is only needed for moving contacts via drag-and-drop. + * The selection data doesn't include the source of the data + * (the model for the currently selected address book view), + * so we have to rely on it being provided to us. I would + * be happy to see this function go away. */ + + g_return_if_fail (E_IS_ADDRESSBOOK_SELECTOR (selector)); + + if (current_view != NULL) + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (current_view)); + + if (selector->priv->current_view == current_view) + return; + + if (selector->priv->current_view != NULL) { + g_object_unref (selector->priv->current_view); + selector->priv->current_view = NULL; + } + + if (current_view != NULL) + g_object_ref (current_view); + + selector->priv->current_view = current_view; + + g_object_notify (G_OBJECT (selector), "current-view"); +} diff --git a/addressbook/gui/widgets/e-addressbook-selector.h b/addressbook/gui/widgets/e-addressbook-selector.h new file mode 100644 index 0000000000..3746bc3aeb --- /dev/null +++ b/addressbook/gui/widgets/e-addressbook-selector.h @@ -0,0 +1,71 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-addressbook-selector.h + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef E_ADDRESSBOOK_SELECTOR_H +#define E_ADDRESSBOOK_SELECTOR_H + +#include "e-addressbook-view.h" + +/* Standard GObject macros */ +#define E_TYPE_ADDRESSBOOK_SELECTOR \ + (e_addressbook_selector_get_type ()) +#define E_ADDRESSBOOK_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_ADDRESSBOOK_SELECTOR, EAddressbookSelector)) +#define E_ADDRESSBOOK_SELECTOR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_ADDRESSBOOK_SELECTOR, EAddressbookSelectorClass)) +#define E_IS_ADDRESSBOOK_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_ADDRESSBOOK_SELECTOR)) +#define E_IS_ADDRESSBOOK_SELECTOR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_ADDRESSBOOK_SELECTOR)) +#define E_ADDRESSBOOK_SELECTOR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_ADDRESSBOOK_SELECTOR, EAddressbookSelectorClass)) + +G_BEGIN_DECLS + +typedef struct _EAddressbookSelector EAddressbookSelector; +typedef struct _EAddressbookSelectorClass EAddressbookSelectorClass; +typedef struct _EAddressbookSelectorPrivate EAddressbookSelectorPrivate; + +struct _EAddressbookSelector { + EClientSelector parent; + EAddressbookSelectorPrivate *priv; +}; + +struct _EAddressbookSelectorClass { + EClientSelectorClass parent_class; +}; + +GType e_addressbook_selector_get_type (void); +GtkWidget * e_addressbook_selector_new (EClientCache *client_cache); +EAddressbookView * + e_addressbook_selector_get_current_view + (EAddressbookSelector *selector); +void e_addressbook_selector_set_current_view + (EAddressbookSelector *selector, + EAddressbookView *current_view); + +G_END_DECLS + +#endif /* E_ADDRESSBOOK_SELECTOR_H */ diff --git a/addressbook/gui/widgets/e-addressbook-table-adapter.c b/addressbook/gui/widgets/e-addressbook-table-adapter.c index abcaf6e6b0..a7f1f6bb5b 100644 --- a/addressbook/gui/widgets/e-addressbook-table-adapter.c +++ b/addressbook/gui/widgets/e-addressbook-table-adapter.c @@ -1,398 +1,434 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifdef HAVE_CONFIG_H #include <config.h> +#endif + +#include <gtk/gtk.h> +#include <glib/gi18n.h> + +#include <libebook/libebook.h> + #include "e-addressbook-model.h" #include "e-addressbook-table-adapter.h" -#include "e-card-merging.h" -#include "e-addressbook-util.h" -#include <gnome-xml/tree.h> -#include <gnome-xml/parser.h> -#include <gnome-xml/xmlmemory.h> -#include <gnome.h> +#include "eab-book-util.h" +#include "eab-contact-merging.h" +#include "eab-gui-util.h" +#include <libxml/tree.h> +#include <libxml/parser.h> +#include <libxml/xmlmemory.h> + +#define E_ADDRESSBOOK_TABLE_ADAPTER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ADDRESSBOOK_TABLE_ADAPTER, EAddressbookTableAdapterPrivate)) struct _EAddressbookTableAdapterPrivate { EAddressbookModel *model; - ECardSimple **simples; - int count; + gint create_contact_id, remove_contact_id, modify_contact_id, model_changed_id; - int create_card_id, remove_card_id, modify_card_id, model_changed_id; + GHashTable *emails; }; -#define PARENT_TYPE e_table_model_get_type() -ETableModelClass *parent_class; +/* Forward Declarations */ +static void e_addressbook_table_adapter_table_model_init + (ETableModelInterface *interface); -#define COLS (E_CARD_SIMPLE_FIELD_LAST) +G_DEFINE_TYPE_WITH_CODE ( + EAddressbookTableAdapter, + e_addressbook_table_adapter, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE ( + E_TYPE_TABLE_MODEL, + e_addressbook_table_adapter_table_model_init)) static void -unlink_model(EAddressbookTableAdapter *adapter) +unlink_model (EAddressbookTableAdapter *adapter) { EAddressbookTableAdapterPrivate *priv = adapter->priv; - int i; - - gtk_signal_disconnect(GTK_OBJECT (priv->model), - priv->create_card_id); - gtk_signal_disconnect(GTK_OBJECT (priv->model), - priv->remove_card_id); - gtk_signal_disconnect(GTK_OBJECT (priv->model), - priv->modify_card_id); - gtk_signal_disconnect(GTK_OBJECT (priv->model), - priv->model_changed_id); - - priv->create_card_id = 0; - priv->remove_card_id = 0; - priv->modify_card_id = 0; - priv->model_changed_id = 0; - /* free up the existing mapping if there is one */ - if (priv->simples) { - for (i = 0; i < priv->count; i ++) - gtk_object_unref (GTK_OBJECT (priv->simples[i])); - g_free (priv->simples); - priv->simples = NULL; - } + g_signal_handler_disconnect (priv->model, priv->create_contact_id); + g_signal_handler_disconnect (priv->model, priv->remove_contact_id); + g_signal_handler_disconnect (priv->model, priv->modify_contact_id); + g_signal_handler_disconnect (priv->model, priv->model_changed_id); + + priv->create_contact_id = 0; + priv->remove_contact_id = 0; + priv->modify_contact_id = 0; + priv->model_changed_id = 0; - gtk_object_unref(GTK_OBJECT(priv->model)); + g_object_unref (priv->model); priv->model = NULL; } static void -build_simple_mapping(EAddressbookTableAdapter *adapter) +addressbook_finalize (GObject *object) { - EAddressbookTableAdapterPrivate *priv = adapter->priv; - int i; + EAddressbookTableAdapter *adapter; - /* free up the existing mapping if there is one */ - if (priv->simples) { - for (i = 0; i < priv->count; i ++) - gtk_object_unref (GTK_OBJECT (priv->simples[i])); - g_free (priv->simples); - } + adapter = E_ADDRESSBOOK_TABLE_ADAPTER (object); - /* build up our mapping to ECardSimple*'s */ - priv->count = e_addressbook_model_card_count (priv->model); - priv->simples = g_new (ECardSimple*, priv->count); - for (i = 0; i < priv->count; i ++) { - priv->simples[i] = e_card_simple_new (e_addressbook_model_card_at (priv->model, i)); - gtk_object_ref (GTK_OBJECT (priv->simples[i])); - } -} - -static void -addressbook_destroy(GtkObject *object) -{ - EAddressbookTableAdapter *adapter = E_ADDRESSBOOK_TABLE_ADAPTER(object); + unlink_model (adapter); - unlink_model(adapter); + g_hash_table_destroy (adapter->priv->emails); - g_free (adapter->priv); + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_addressbook_table_adapter_parent_class)->finalize (object); } /* This function returns the number of columns in our ETableModel. */ -static int +static gint addressbook_col_count (ETableModel *etc) { - return COLS; + return E_CONTACT_FIELD_LAST; } /* This function returns the number of rows in our ETableModel. */ -static int +static gint addressbook_row_count (ETableModel *etc) { - EAddressbookTableAdapter *adapter = E_ADDRESSBOOK_TABLE_ADAPTER(etc); + EAddressbookTableAdapter *adapter = E_ADDRESSBOOK_TABLE_ADAPTER (etc); EAddressbookTableAdapterPrivate *priv = adapter->priv; - return e_addressbook_model_card_count (priv->model); + return e_addressbook_model_contact_count (priv->model); +} + +static void +addressbook_append_row (ETableModel *etm, + ETableModel *source, + gint row) +{ + EAddressbookTableAdapter *adapter = E_ADDRESSBOOK_TABLE_ADAPTER (etm); + EAddressbookTableAdapterPrivate *priv = adapter->priv; + EClientCache *client_cache; + ESourceRegistry *registry; + EBookClient *book_client; + EContact *contact; + gint col; + + contact = e_contact_new (); + + for (col = 1; col < E_CONTACT_LAST_SIMPLE_STRING; col++) { + gconstpointer val = e_table_model_value_at (source, col, row); + e_contact_set (contact, col, (gpointer) val); + } + + client_cache = + e_addressbook_model_get_client_cache (priv->model); + book_client = e_addressbook_model_get_client (priv->model); + + registry = e_client_cache_ref_registry (client_cache); + + eab_merging_book_add_contact ( + registry, book_client, contact, NULL, NULL); + + g_object_unref (registry); + + g_object_unref (contact); } /* This function returns the value at a particular point in our ETableModel. */ -static void * -addressbook_value_at (ETableModel *etc, int col, int row) +static gpointer +addressbook_value_at (ETableModel *etc, + gint col, + gint row) { - EAddressbookTableAdapter *adapter = E_ADDRESSBOOK_TABLE_ADAPTER(etc); + EAddressbookTableAdapter *adapter = E_ADDRESSBOOK_TABLE_ADAPTER (etc); EAddressbookTableAdapterPrivate *priv = adapter->priv; - const char *value; + EContact *contact; + const gchar *value; - if ( col >= COLS || row >= e_addressbook_model_card_count (priv->model) ) + if (col >= E_CONTACT_FIELD_LAST) return NULL; - value = e_card_simple_get_const(priv->simples[row], col); + if (row >= e_addressbook_model_contact_count (priv->model)) + return NULL; + + contact = e_addressbook_model_contact_at (priv->model, row); + value = e_contact_get_const (contact, col); + + if (value && *value && (col == E_CONTACT_EMAIL_1 || + col == E_CONTACT_EMAIL_2 || col == E_CONTACT_EMAIL_3)) { + gchar *val = g_hash_table_lookup (priv->emails, value); + + if (val) { + /* we have this already cached, so use value from the cache */ + value = val; + } else { + gchar *name = NULL, *mail = NULL; + + if (eab_parse_qp_email (value, &name, &mail)) + val = g_strdup_printf ("%s <%s>", name, mail); + else + val = g_strdup (value); - if (value && !strncmp (value, "<?xml", 5)) { - EDestination *dest = e_destination_import (value); - if (dest) { - g_free ((gchar *) value); - value = g_strdup (e_destination_get_address (dest)); - gtk_object_unref (GTK_OBJECT (dest)); + g_free (name); + g_free (mail); + + g_hash_table_insert (priv->emails, g_strdup (value), val); + value = val; } } - - return (void *)(value ? value : ""); + return (gpointer)(value ? value : ""); } /* This function sets the value at a particular point in our ETableModel. */ static void -card_modified_cb (EBook* book, EBookStatus status, - gpointer user_data) +contact_modified_cb (EBookClient *book_client, + const GError *error, + gpointer user_data) { - /* g_print ("%s: %s(): a card was modified\n", __FILE__, __FUNCTION__); */ - if (status != E_BOOK_STATUS_SUCCESS) - e_addressbook_error_dialog (_("Error modifying card"), status); + if (error) + eab_error_dialog (NULL, NULL, _("Error modifying card"), error); } + static void -addressbook_set_value_at (ETableModel *etc, int col, int row, const void *val) +addressbook_set_value_at (ETableModel *etc, + gint col, + gint row, + gconstpointer val) { - EAddressbookTableAdapter *adapter = E_ADDRESSBOOK_TABLE_ADAPTER(etc); + EAddressbookTableAdapter *adapter = E_ADDRESSBOOK_TABLE_ADAPTER (etc); EAddressbookTableAdapterPrivate *priv = adapter->priv; - if (e_addressbook_model_editable (priv->model)) { - ECard *card; - if ( col >= COLS|| row >= e_addressbook_model_card_count (priv->model) ) + if (e_addressbook_model_get_editable (priv->model)) { + EClientCache *client_cache; + ESourceRegistry *registry; + EBookClient *book_client; + EContact *contact; + + if (col >= E_CONTACT_FIELD_LAST) return; - e_table_model_pre_change(etc); + if (row >= e_addressbook_model_contact_count (priv->model)) + return; - e_card_simple_set(priv->simples[row], - col, - val); - gtk_object_get(GTK_OBJECT(priv->simples[row]), - "card", &card, - NULL); + contact = e_addressbook_model_get_contact (priv->model, row); + if (!contact) + return; - e_card_merging_book_commit_card(e_addressbook_model_get_ebook(priv->model), - card, card_modified_cb, NULL); + e_table_model_pre_change (etc); - /* XXX do we need this? shouldn't the commit_card generate a changed signal? */ - e_table_model_cell_changed(etc, col, row); - } -} + if (col == E_CONTACT_EMAIL_1 || + col == E_CONTACT_EMAIL_2 || + col == E_CONTACT_EMAIL_3) { + const gchar *old_value = e_contact_get_const (contact, col); -/* This function returns whether a particular cell is editable. */ -static gboolean -addressbook_is_cell_editable (ETableModel *etc, int col, int row) -{ - EAddressbookTableAdapter *adapter = E_ADDRESSBOOK_TABLE_ADAPTER(etc); - EAddressbookTableAdapterPrivate *priv = adapter->priv; - ECard *card; + /* remove old value from cache and use new one */ + if (old_value && *old_value) + g_hash_table_remove (priv->emails, old_value); + } - if (row >= 0 && row < e_addressbook_model_card_count (priv->model)) - card = e_addressbook_model_card_at (priv->model, row); - else - card = NULL; - - if (!e_addressbook_model_editable(priv->model)) - return FALSE; - else if (card && e_card_evolution_list (card)) - /* we only allow editing of the name and file as for - lists */ - return col == E_CARD_SIMPLE_FIELD_FULL_NAME || col == E_CARD_SIMPLE_FIELD_FILE_AS; - else - return col < E_CARD_SIMPLE_FIELD_LAST_SIMPLE_STRING; -} + client_cache = + e_addressbook_model_get_client_cache (priv->model); + book_client = e_addressbook_model_get_client (priv->model); -static void -addressbook_append_row (ETableModel *etm, ETableModel *source, gint row) -{ - EAddressbookTableAdapter *adapter = E_ADDRESSBOOK_TABLE_ADAPTER(etm); - EAddressbookTableAdapterPrivate *priv = adapter->priv; - ECard *card; - ECardSimple *simple; - int col; + registry = e_client_cache_ref_registry (client_cache); + + e_contact_set (contact, col, (gpointer) val); + eab_merging_book_modify_contact ( + registry, book_client, + contact, contact_modified_cb, etc); - card = e_card_new(""); - simple = e_card_simple_new(card); + g_object_unref (registry); - for (col = 0; col < E_CARD_SIMPLE_FIELD_LAST_SIMPLE_STRING; col++) { - const void *val = e_table_model_value_at(source, col, row); - e_card_simple_set(simple, col, val); + g_object_unref (contact); + + /* XXX Do we need this? Shouldn't the commit_contact + * generate a changed signal? */ + e_table_model_cell_changed (etc, col, row); } - e_card_simple_sync_card(simple); - e_card_merging_book_add_card (e_addressbook_model_get_ebook (priv->model), card, NULL, NULL); - gtk_object_unref(GTK_OBJECT(simple)); - gtk_object_unref(GTK_OBJECT(card)); +} + +/* This function returns whether a particular cell is editable. */ +static gboolean +addressbook_is_cell_editable (ETableModel *etc, + gint col, + gint row) +{ + return FALSE; } /* This function duplicates the value passed to it. */ -static void * -addressbook_duplicate_value (ETableModel *etc, int col, const void *value) +static gpointer +addressbook_duplicate_value (ETableModel *etc, + gint col, + gconstpointer value) { - return g_strdup(value); + return g_strdup (value); } /* This function frees the value passed to it. */ static void -addressbook_free_value (ETableModel *etc, int col, void *value) +addressbook_free_value (ETableModel *etc, + gint col, + gpointer value) { - g_free(value); + g_free (value); } -static void * -addressbook_initialize_value (ETableModel *etc, int col) +static gpointer +addressbook_initialize_value (ETableModel *etc, + gint col) { - return g_strdup(""); + return g_strdup (""); } static gboolean -addressbook_value_is_empty (ETableModel *etc, int col, const void *value) +addressbook_value_is_empty (ETableModel *etc, + gint col, + gconstpointer value) { - return !(value && *(char *)value); + return !(value && *(gchar *) value); } -static char * -addressbook_value_to_string (ETableModel *etc, int col, const void *value) +static gchar * +addressbook_value_to_string (ETableModel *etc, + gint col, + gconstpointer value) { - return g_strdup(value); + return g_strdup (value); } static void -e_addressbook_table_adapter_class_init (GtkObjectClass *object_class) +e_addressbook_table_adapter_class_init (EAddressbookTableAdapterClass *class) { - ETableModelClass *model_class = (ETableModelClass *) object_class; - - parent_class = gtk_type_class (PARENT_TYPE); - - object_class->destroy = addressbook_destroy; - - model_class->column_count = addressbook_col_count; - model_class->row_count = addressbook_row_count; - model_class->value_at = addressbook_value_at; - model_class->set_value_at = addressbook_set_value_at; - model_class->is_cell_editable = addressbook_is_cell_editable; - model_class->append_row = addressbook_append_row; - model_class->duplicate_value = addressbook_duplicate_value; - model_class->free_value = addressbook_free_value; - model_class->initialize_value = addressbook_initialize_value; - model_class->value_is_empty = addressbook_value_is_empty; - model_class->value_to_string = addressbook_value_to_string; + GObjectClass *object_class; + + g_type_class_add_private ( + class, sizeof (EAddressbookTableAdapterPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->finalize = addressbook_finalize; } static void -e_addressbook_table_adapter_init (GtkObject *object) +e_addressbook_table_adapter_table_model_init (ETableModelInterface *interface) { - EAddressbookTableAdapter *adapter = E_ADDRESSBOOK_TABLE_ADAPTER(object); - EAddressbookTableAdapterPrivate *priv; - - priv = adapter->priv = g_new0 (EAddressbookTableAdapterPrivate, 1); - - priv->create_card_id = 0; - priv->remove_card_id = 0; - priv->modify_card_id = 0; - priv->model_changed_id = 0; - priv->simples = NULL; - priv->count = 0; + interface->column_count = addressbook_col_count; + interface->row_count = addressbook_row_count; + interface->append_row = addressbook_append_row; + + interface->value_at = addressbook_value_at; + interface->set_value_at = addressbook_set_value_at; + interface->is_cell_editable = addressbook_is_cell_editable; + + interface->duplicate_value = addressbook_duplicate_value; + interface->free_value = addressbook_free_value; + interface->initialize_value = addressbook_initialize_value; + interface->value_is_empty = addressbook_value_is_empty; + interface->value_to_string = addressbook_value_to_string; } - static void -create_card (EAddressbookModel *model, - gint index, gint count, - EAddressbookTableAdapter *adapter) +e_addressbook_table_adapter_init (EAddressbookTableAdapter *adapter) { - EAddressbookTableAdapterPrivate *priv = adapter->priv; - int i; - - priv->count += count; - priv->simples = g_renew(ECardSimple *, priv->simples, priv->count); - memmove (priv->simples + index + count, priv->simples + index, (priv->count - index - count) * sizeof (ECardSimple *)); + adapter->priv = E_ADDRESSBOOK_TABLE_ADAPTER_GET_PRIVATE (adapter); +} +static void +create_contact (EAddressbookModel *model, + gint index, + gint count, + EAddressbookTableAdapter *adapter) +{ e_table_model_pre_change (E_TABLE_MODEL (adapter)); - for (i = 0; i < count; i ++) { - priv->simples[index + i] = e_card_simple_new (e_addressbook_model_card_at (priv->model, index + i)); - } e_table_model_rows_inserted (E_TABLE_MODEL (adapter), index, count); } static void -remove_card (EAddressbookModel *model, - gint index, - EAddressbookTableAdapter *adapter) +remove_contacts (EAddressbookModel *model, + gpointer data, + EAddressbookTableAdapter *adapter) { - EAddressbookTableAdapterPrivate *priv = adapter->priv; + GArray *indices = (GArray *) data; + gint count = indices->len; - e_table_model_pre_change (E_TABLE_MODEL (adapter)); + /* clear whole cache */ + g_hash_table_remove_all (adapter->priv->emails); - gtk_object_unref (GTK_OBJECT (priv->simples[index])); - memmove (priv->simples + index, priv->simples + index + 1, (priv->count - index - 1) * sizeof (ECardSimple *)); - priv->count --; - e_table_model_rows_deleted (E_TABLE_MODEL (adapter), index, 1); + e_table_model_pre_change (E_TABLE_MODEL (adapter)); + if (count == 1) + e_table_model_rows_deleted ( + E_TABLE_MODEL (adapter), + g_array_index (indices, gint, 0), 1); + else + e_table_model_changed (E_TABLE_MODEL (adapter)); } static void -modify_card (EAddressbookModel *model, - gint index, - EAddressbookTableAdapter *adapter) +modify_contact (EAddressbookModel *model, + gint index, + EAddressbookTableAdapter *adapter) { - EAddressbookTableAdapterPrivate *priv = adapter->priv; + /* clear whole cache */ + g_hash_table_remove_all (adapter->priv->emails); e_table_model_pre_change (E_TABLE_MODEL (adapter)); - - gtk_object_unref (GTK_OBJECT (priv->simples[index])); - priv->simples[index] = e_card_simple_new (e_addressbook_model_card_at (priv->model, index)); - gtk_object_ref (GTK_OBJECT (priv->simples[index])); e_table_model_row_changed (E_TABLE_MODEL (adapter), index); } static void model_changed (EAddressbookModel *model, - EAddressbookTableAdapter *adapter) + EAddressbookTableAdapter *adapter) { + /* clear whole cache */ + g_hash_table_remove_all (adapter->priv->emails); + e_table_model_pre_change (E_TABLE_MODEL (adapter)); - build_simple_mapping (adapter); e_table_model_changed (E_TABLE_MODEL (adapter)); } -GtkType -e_addressbook_table_adapter_get_type (void) -{ - static GtkType type = 0; - - if (!type){ - GtkTypeInfo info = { - "EAddressbookTableAdapter", - sizeof (EAddressbookTableAdapter), - sizeof (EAddressbookTableAdapterClass), - (GtkClassInitFunc) e_addressbook_table_adapter_class_init, - (GtkObjectInitFunc) e_addressbook_table_adapter_init, - NULL, /* reserved 1 */ - NULL, /* reserved 2 */ - (GtkClassInitFunc) NULL - }; - - type = gtk_type_unique (PARENT_TYPE, &info); - } - - return type; -} - void e_addressbook_table_adapter_construct (EAddressbookTableAdapter *adapter, - EAddressbookModel *model) + EAddressbookModel *model) { EAddressbookTableAdapterPrivate *priv = adapter->priv; priv->model = model; - gtk_object_ref (GTK_OBJECT (priv->model)); - - priv->create_card_id = gtk_signal_connect(GTK_OBJECT(priv->model), - "card_added", - GTK_SIGNAL_FUNC(create_card), - adapter); - priv->remove_card_id = gtk_signal_connect(GTK_OBJECT(priv->model), - "card_removed", - GTK_SIGNAL_FUNC(remove_card), - adapter); - priv->modify_card_id = gtk_signal_connect(GTK_OBJECT(priv->model), - "card_changed", - GTK_SIGNAL_FUNC(modify_card), - adapter); - priv->model_changed_id = gtk_signal_connect(GTK_OBJECT(priv->model), - "model_changed", - GTK_SIGNAL_FUNC(model_changed), - adapter); - - build_simple_mapping (adapter); + g_object_ref (priv->model); + + priv->create_contact_id = g_signal_connect ( + priv->model, "contact_added", + G_CALLBACK (create_contact), adapter); + + priv->remove_contact_id = g_signal_connect ( + priv->model, "contacts_removed", + G_CALLBACK (remove_contacts), adapter); + + priv->modify_contact_id = g_signal_connect ( + priv->model, "contact_changed", + G_CALLBACK (modify_contact), adapter); + + priv->model_changed_id = g_signal_connect ( + priv->model, "model_changed", + G_CALLBACK (model_changed), adapter); + + priv->emails = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_free); } ETableModel * @@ -400,9 +436,9 @@ e_addressbook_table_adapter_new (EAddressbookModel *model) { EAddressbookTableAdapter *et; - et = gtk_type_new (e_addressbook_table_adapter_get_type ()); + et = g_object_new (E_TYPE_ADDRESSBOOK_TABLE_ADAPTER, NULL); e_addressbook_table_adapter_construct (et, model); - return E_TABLE_MODEL(et); + return E_TABLE_MODEL (et); } diff --git a/addressbook/gui/widgets/e-addressbook-table-adapter.h b/addressbook/gui/widgets/e-addressbook-table-adapter.h index d76434e80a..93b7ae9553 100644 --- a/addressbook/gui/widgets/e-addressbook-table-adapter.h +++ b/addressbook/gui/widgets/e-addressbook-table-adapter.h @@ -1,44 +1,70 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -#ifndef _E_ADDRESSBOOK_TABLE_ADAPTER_H_ -#define _E_ADDRESSBOOK_TABLE_ADAPTER_H_ - -#include <gal/e-table/e-table-model.h> -#include "addressbook/backend/ebook/e-book.h" -#include "addressbook/backend/ebook/e-book-view.h" -#include "addressbook/backend/ebook/e-card-simple.h" - -#define E_ADDRESSBOOK_TABLE_ADAPTER_TYPE (e_addressbook_table_adapter_get_type ()) -#define E_ADDRESSBOOK_TABLE_ADAPTER(o) (GTK_CHECK_CAST ((o), E_ADDRESSBOOK_TABLE_ADAPTER_TYPE, EAddressbookTableAdapter)) -#define E_ADDRESSBOOK_TABLE_ADAPTER_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_ADDRESSBOOK_TABLE_ADAPTER_TYPE, EAddressbookTableAdapterClass)) -#define E_IS_ADDRESSBOOK_TABLE_ADAPTER(o) (GTK_CHECK_TYPE ((o), E_ADDRESSBOOK_TABLE_ADAPTER_TYPE)) -#define E_IS_ADDRESSBOOK_TABLE_ADAPTER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_ADDRESSBOOK_TABLE_ADAPTER_TYPE)) - -/* Virtual Column list: - 0 Email - 1 Full Name - 2 Street - 3 Phone -*/ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef _EAB_TABLE_ADAPTER_H_ +#define _EAB_TABLE_ADAPTER_H_ + +#include <e-util/e-util.h> + +/* Standard GObject macros */ +#define E_TYPE_ADDRESSBOOK_TABLE_ADAPTER \ + (e_addressbook_table_adapter_get_type ()) +#define E_ADDRESSBOOK_TABLE_ADAPTER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_ADDRESSBOOK_TABLE_ADAPTER, EAddressbookTableAdapter)) +#define E_ADDRESSBOOK_TABLE_ADAPTER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_ADDRESSBOOK_TABLE_ADAPTER, EAddressbookTableAdapterClass)) +#define E_IS_ADDRESSBOOK_TABLE_ADAPTER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_ADDRESSBOOK_TABLE_ADAPTER)) +#define E_IS_ADDRESSBOOK_TABLE_ADAPTER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_ADDRESSBOOK_TABLE_ADAPTER)) +#define E_ADDRESSBOOK_TABLE_ADAPTER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_ADDRESSBOOK_TABLE_ADAPTER, EAddressbookTableAdapterClass)) + +G_BEGIN_DECLS typedef struct _EAddressbookTableAdapter EAddressbookTableAdapter; -typedef struct _EAddressbookTableAdapterPrivate EAddressbookTableAdapterPrivate; typedef struct _EAddressbookTableAdapterClass EAddressbookTableAdapterClass; +typedef struct _EAddressbookTableAdapterPrivate EAddressbookTableAdapterPrivate; struct _EAddressbookTableAdapter { - ETableModel parent; - + GObject parent; EAddressbookTableAdapterPrivate *priv; }; - struct _EAddressbookTableAdapterClass { - ETableModelClass parent_class; + GObjectClass parent_class; }; +GType e_addressbook_table_adapter_get_type + (void) G_GNUC_CONST; +void e_addressbook_table_adapter_construct + (EAddressbookTableAdapter *adapter, + EAddressbookModel *model); +ETableModel * e_addressbook_table_adapter_new + (EAddressbookModel *model); -GtkType e_addressbook_table_adapter_get_type (void); -void e_addressbook_table_adapter_construct (EAddressbookTableAdapter *adapter, - EAddressbookModel *model); -ETableModel *e_addressbook_table_adapter_new (EAddressbookModel *model); +G_END_DECLS -#endif /* _E_ADDRESSBOOK_TABLE_ADAPTER_H_ */ +#endif /* _EAB_TABLE_ADAPTER_H_ */ diff --git a/addressbook/gui/widgets/e-addressbook-util.c b/addressbook/gui/widgets/e-addressbook-util.c deleted file mode 100644 index 04f4238fbd..0000000000 --- a/addressbook/gui/widgets/e-addressbook-util.c +++ /dev/null @@ -1,385 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-table-field-chooser.c - * Copyright (C) 2001 Ximian, Inc. - * Author: Chris Toshok <toshok@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <config.h> -#include "e-addressbook-util.h" - -#include <gnome.h> - -#include "e-card-merging.h" -#include <shell/evolution-shell-client.h> -#include <addressbook/backend/ebook/e-book-util.h> - -void -e_addressbook_error_dialog (const gchar *msg, EBookStatus status) -{ - static char *status_to_string[] = { - N_("Success"), - N_("Unknown error"), - N_("Repository offline"), - N_("Permission denied"), - N_("Card not found"), - N_("Card ID already exists"), - N_("Protocol not supported"), - N_("Cancelled"), - N_("Authentication Failed"), - N_("Authentication Required"), - N_("TLS not Available"), - N_("Addressbook does not exist"), - N_("Other error") - }; - char *error_msg; - - error_msg = g_strdup_printf ("%s: %s", msg, _(status_to_string [status])); - - gtk_widget_show (gnome_error_dialog (error_msg)); - - g_free (error_msg); -} - -gint -e_addressbook_prompt_save_dialog (GtkWindow *parent) -{ - GtkWidget *dialog; - - dialog = gnome_message_box_new (_("Do you want to save changes?"), - GNOME_MESSAGE_BOX_QUESTION, - GNOME_STOCK_BUTTON_YES, - GNOME_STOCK_BUTTON_NO, - GNOME_STOCK_BUTTON_CANCEL, - NULL); - - gnome_dialog_set_default (GNOME_DIALOG (dialog), 0); - gnome_dialog_grab_focus (GNOME_DIALOG (dialog), 0); - gnome_dialog_set_parent (GNOME_DIALOG (dialog), parent); - - return gnome_dialog_run_and_close (GNOME_DIALOG (dialog)); -} - -static void -added_cb (EBook* book, EBookStatus status, const char *id, - gboolean is_list) -{ - if (status != E_BOOK_STATUS_SUCCESS) { - e_addressbook_error_dialog (is_list ? _("Error adding list") : _("Error adding card"), status); - } -} - -static void -modified_cb (EBook* book, EBookStatus status, - gboolean is_list) -{ - if (status != E_BOOK_STATUS_SUCCESS) { - e_addressbook_error_dialog (is_list ? _("Error modifying list") : _("Error modifying card"), - status); - } -} - -static void -deleted_cb (EBook* book, EBookStatus status, - gboolean is_list) -{ - if (status != E_BOOK_STATUS_SUCCESS) { - e_addressbook_error_dialog (is_list ? _("Error removing list") : _("Error removing card"), - status); - } -} - -static void -editor_closed_cb (GtkObject *editor, gpointer data) -{ - gtk_object_unref (editor); -} - -EContactEditor * -e_addressbook_show_contact_editor (EBook *book, ECard *card, - gboolean is_new_card, - gboolean editable) -{ - EContactEditor *ce; - - ce = e_contact_editor_new (book, card, is_new_card, editable); - - gtk_signal_connect (GTK_OBJECT (ce), "card_added", - GTK_SIGNAL_FUNC (added_cb), GINT_TO_POINTER (FALSE)); - gtk_signal_connect (GTK_OBJECT (ce), "card_modified", - GTK_SIGNAL_FUNC (modified_cb), GINT_TO_POINTER (FALSE)); - gtk_signal_connect (GTK_OBJECT (ce), "card_deleted", - GTK_SIGNAL_FUNC (deleted_cb), GINT_TO_POINTER (FALSE)); - gtk_signal_connect (GTK_OBJECT (ce), "editor_closed", - GTK_SIGNAL_FUNC (editor_closed_cb), NULL); - - return ce; -} - -EContactListEditor * -e_addressbook_show_contact_list_editor (EBook *book, ECard *card, - gboolean is_new_card, - gboolean editable) -{ - EContactListEditor *ce; - - ce = e_contact_list_editor_new (book, card, is_new_card, editable); - - gtk_signal_connect (GTK_OBJECT (ce), "list_added", - GTK_SIGNAL_FUNC (added_cb), GINT_TO_POINTER (TRUE)); - gtk_signal_connect (GTK_OBJECT (ce), "list_modified", - GTK_SIGNAL_FUNC (modified_cb), GINT_TO_POINTER (TRUE)); - gtk_signal_connect (GTK_OBJECT (ce), "list_deleted", - GTK_SIGNAL_FUNC (deleted_cb), GINT_TO_POINTER (TRUE)); - gtk_signal_connect (GTK_OBJECT (ce), "editor_closed", - GTK_SIGNAL_FUNC (editor_closed_cb), GINT_TO_POINTER (TRUE)); - - e_contact_list_editor_show (ce); - - return ce; -} - -typedef struct { - EBook *book; - GList *list; - gboolean editable; -} BookAndList; - -static void -view_cards (EBook *book, GList *list, gboolean editable) -{ - for (; list; list = list->next) { - ECard *card = list->data; - if (e_card_evolution_list (card)) - e_addressbook_show_contact_list_editor (book, card, FALSE, editable); - else - e_addressbook_show_contact_editor (book, card, FALSE, editable); - } -} - -static void -view_question_clicked (GtkObject *object, int button, BookAndList *bnl) -{ - GnomeDialog *dialog = GNOME_DIALOG (object); - switch (button) { - case 0: - view_cards (bnl->book, bnl->list, bnl->editable); - break; - } - gnome_dialog_close(dialog); -} - -static void -view_question_destroyed (GtkObject *object, GList *list) -{ - gtk_main_quit(); -} - -void -e_addressbook_show_multiple_cards (EBook *book, - GList *list, - gboolean editable) -{ - if (list) { - int length = g_list_length (list); - if (length > 5) { - char *string; - GtkWidget *dialog; - BookAndList bnl; - - bnl.book = book; - bnl.list = list; - bnl.editable = editable; - - dialog = gnome_dialog_new (_("Display Cards?"), - _("Display Cards"), - GNOME_STOCK_BUTTON_CANCEL, - NULL); - - string = g_strdup_printf (_("Opening %d cards will open %d new windows as well.\n" - "Do you really want to display all of these cards?"), length, length); - gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), gtk_label_new (string), FALSE, FALSE, 0); - g_free (string); - - gtk_signal_connect (GTK_OBJECT (dialog), "destroy", - GTK_SIGNAL_FUNC (view_question_destroyed), &bnl); - gtk_signal_connect (GTK_OBJECT (dialog), "clicked", - GTK_SIGNAL_FUNC (view_question_clicked), &bnl); - - gtk_widget_show_all (dialog); - - gtk_main(); - } else { - view_cards (book, list, editable); - } - } -} - - - -typedef struct CardCopyProcess_ CardCopyProcess; - -typedef void (*CardCopyDone) (CardCopyProcess *process); - -struct CardCopyProcess_ { - int count; - GList *cards; - EBook *source; - EBook *destination; - CardCopyDone done_cb; -}; - -static void -card_deleted_cb (EBook* book, EBookStatus status, gpointer user_data) -{ - if (status != E_BOOK_STATUS_SUCCESS) { - e_addressbook_error_dialog (_("Error removing card"), status); - } -} - -static void -do_delete (gpointer data, gpointer user_data) -{ - EBook *book = user_data; - ECard *card = data; - - e_book_remove_card(book, card, card_deleted_cb, NULL); -} - -static void -delete_cards (CardCopyProcess *process) -{ - g_list_foreach (process->cards, - do_delete, - process->source); -} - -static void -process_unref (CardCopyProcess *process) -{ - process->count --; - if (process->count == 0) { - if (process->done_cb) { - process->done_cb (process); - } - e_free_object_list(process->cards); - gtk_object_unref (GTK_OBJECT (process->source)); - gtk_object_unref (GTK_OBJECT (process->destination)); - g_free (process); - } -} - -static void -card_added_cb (EBook* book, EBookStatus status, const char *id, gpointer user_data) -{ - CardCopyProcess *process = user_data; - - if (status != E_BOOK_STATUS_SUCCESS) { - e_addressbook_error_dialog (_("Error adding card"), status); - } else { - process_unref (process); - } -} - -static void -do_copy (gpointer data, gpointer user_data) -{ - EBook *book; - ECard *card; - CardCopyProcess *process; - - process = user_data; - card = data; - - book = process->destination; - - process->count ++; - e_book_add_card(book, card, card_added_cb, process); -} - -static void -got_book_cb (EBook *book, gpointer closure) -{ - CardCopyProcess *process; - process = closure; - if (book) { - process->destination = book; - gtk_object_ref (GTK_OBJECT (book)); - g_list_foreach (process->cards, - do_copy, - process); - } - process_unref (process); -} - -extern EvolutionShellClient *global_shell_client; - -void -e_addressbook_transfer_cards (EBook *source, GList *cards /* adopted */, gboolean delete_from_source, GtkWindow *parent_window) -{ - const char *allowed_types[] = { "contacts/*", NULL }; - GNOME_Evolution_Folder *folder; - static char *last_uri = NULL; - CardCopyProcess *process; - char *desc; - - if (cards == NULL) - return; - - if (last_uri == NULL) - last_uri = g_strdup (""); - - if (cards->next == NULL) { - if (delete_from_source) - desc = _("Move card to"); - else - desc = _("Copy card to"); - } else { - if (delete_from_source) - desc = _("Move cards to"); - else - desc = _("Copy cards to"); - } - - evolution_shell_client_user_select_folder (global_shell_client, - parent_window, - desc, last_uri, allowed_types, - &folder); - if (!folder) - return; - - if (strcmp (last_uri, folder->evolutionUri) != 0) { - g_free (last_uri); - last_uri = g_strdup (folder->evolutionUri); - } - - process = g_new (CardCopyProcess, 1); - process->count = 1; - process->source = source; - gtk_object_ref (GTK_OBJECT (source)); - process->cards = cards; - process->destination = NULL; - - if (delete_from_source) - process->done_cb = delete_cards; - else - process->done_cb = NULL; - - e_book_use_address_book_by_uri (folder->physicalUri, got_book_cb, process); - - CORBA_free (folder); -} diff --git a/addressbook/gui/widgets/e-addressbook-util.h b/addressbook/gui/widgets/e-addressbook-util.h deleted file mode 100644 index f0681cea4d..0000000000 --- a/addressbook/gui/widgets/e-addressbook-util.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* e-addressbook-util.h - * Copyright (C) 2001 Ximian, Inc. - * Author: Chris Toshok <toshok@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#ifndef __E_ADDRESSBOOK_UTIL_H__ -#define __E_ADDRESSBOOK_UTIL_H__ - -#include "addressbook/backend/ebook/e-book.h" -#include "addressbook/gui/contact-editor/e-contact-editor.h" -#include "addressbook/gui/contact-list-editor/e-contact-list-editor.h" - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -void e_addressbook_error_dialog (const gchar *msg, - EBookStatus status); -gint e_addressbook_prompt_save_dialog (GtkWindow *parent); -EContactEditor *e_addressbook_show_contact_editor (EBook *book, - ECard *card, - gboolean is_new_card, - gboolean editable); -EContactListEditor *e_addressbook_show_contact_list_editor (EBook *book, - ECard *card, - gboolean is_new_card, - gboolean editable); -void e_addressbook_show_multiple_cards (EBook *book, - GList *list, - gboolean editable); -void e_addressbook_transfer_cards (EBook *source, - GList *cards, /* adopted */ - gboolean delete_from_source, - GtkWindow *parent_window); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __E_ADDRESSBOOK_UTIL_H__ */ diff --git a/addressbook/gui/widgets/e-addressbook-view.c b/addressbook/gui/widgets/e-addressbook-view.c index f9669a20ac..38d7196217 100644 --- a/addressbook/gui/widgets/e-addressbook-view.c +++ b/addressbook/gui/widgets/e-addressbook-view.c @@ -1,1977 +1,1695 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-table-field-chooser.c - * Copyright (C) 2000 Ximian, Inc. - * Author: Chris Lahey <clahey@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. * * 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. + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * Chris Toshok <toshok@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. */ +#ifdef HAVE_CONFIG_H #include <config.h> +#endif -#include <gtk/gtkinvisible.h> - -#include <libgnome/gnome-paper.h> -#include <libgnome/gnome-i18n.h> -#include <libgnome/gnome-util.h> -#include <gal/e-table/e-table-scrolled.h> -#include <gal/e-table/e-table-model.h> -#include <gal/widgets/e-scroll-frame.h> -#include <gal/widgets/e-popup-menu.h> -#include <gal/widgets/e-gui-utils.h> -#include <gal/widgets/e-unicode.h> -#include <gal/menus/gal-view-factory-etable.h> -#include <gal/menus/gal-view-etable.h> -#include <gal/util/e-unicode-i18n.h> -#include <gal/util/e-xml-utils.h> -#include <gal/unicode/gunicode.h> -#include <libgnomeui/gnome-dialog-util.h> -#include <libgnomeui/gnome-stock.h> - -#include <libgnomeprint/gnome-print.h> -#include <libgnomeprint/gnome-print-dialog.h> -#include <libgnomeprint/gnome-print-master.h> -#include <libgnomeprint/gnome-print-master-preview.h> +#include <ctype.h> +#include <string.h> + +#include <glib/gi18n.h> +#include <gdk/gdkkeysyms.h> + +#include "e-addressbook-view.h" + +#include "e-util/e-util.h" +#include "shell/e-shell-sidebar.h" #include "addressbook/printing/e-contact-print.h" -#include "addressbook/printing/e-contact-print-envelope.h" +#include "ea-addressbook.h" -#include "gal-view-factory-minicard.h" #include "gal-view-minicard.h" -#include "e-addressbook-view.h" #include "e-addressbook-model.h" -#include "e-addressbook-util.h" +#include "eab-gui-util.h" +#include "util/eab-book-util.h" #include "e-addressbook-table-adapter.h" -#include "e-addressbook-reflow-adapter.h" -#include "e-minicard-view-widget.h" -#include "e-contact-save-as.h" -#include "e-card-merging.h" +#include "eab-contact-merging.h" -#include "e-contact-editor.h" -#include <gdk/gdkkeysyms.h> -#include <ctype.h> +#define E_ADDRESSBOOK_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ADDRESSBOOK_VIEW, EAddressbookViewPrivate)) -#include <gnome-xml/tree.h> -#include <gnome-xml/parser.h> +#define d(x) -#define SHOW_ALL_SEARCH "(contains \"x-evolution-any-field\" \"\")" +static void status_message (EAddressbookView *view, + const gchar *status, gint percent); +static void search_result (EAddressbookView *view, + const GError *error); +static void folder_bar_message (EAddressbookView *view, + const gchar *status); +static void stop_state_changed (GObject *object, + EAddressbookView *view); +static void command_state_change (EAddressbookView *view); -#define d(x) +struct _EAddressbookViewPrivate { + gpointer shell_view; /* weak pointer */ + + EAddressbookModel *model; + EActivity *activity; + + ESource *source; + + GObject *object; + + GalViewInstance *view_instance; + + /* stored search setup for this view */ + gint filter_id; + gchar *search_text; + gint search_id; + EFilterRule *advanced_search; + + GtkTargetList *copy_target_list; + GtkTargetList *paste_target_list; +}; -static void e_addressbook_view_init (EAddressbookView *card); -static void e_addressbook_view_class_init (EAddressbookViewClass *klass); -static void e_addressbook_view_set_arg (GtkObject *o, GtkArg *arg, guint arg_id); -static void e_addressbook_view_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); -static void e_addressbook_view_destroy (GtkObject *object); -static void change_view_type (EAddressbookView *view, EAddressbookViewType view_type); - -static void status_message (GtkObject *object, const gchar *status, EAddressbookView *eav); -static void search_result (GtkObject *object, EBookViewStatus status, EAddressbookView *eav); -static void folder_bar_message (GtkObject *object, const gchar *status, EAddressbookView *eav); -static void stop_state_changed (GtkObject *object, EAddressbookView *eav); -static void writable_status (GtkObject *object, gboolean writable, EAddressbookView *eav); -static void backend_died (GtkObject *object, EAddressbookView *eav); -static void command_state_change (EAddressbookView *eav); -static void alphabet_state_change (EAddressbookView *eav, gunichar letter); - -static void selection_clear_event (GtkWidget *invisible, GdkEventSelection *event, - EAddressbookView *view); -static void selection_received (GtkWidget *invisible, GtkSelectionData *selection_data, - guint time, EAddressbookView *view); -static void selection_get (GtkWidget *invisible, GtkSelectionData *selection_data, - guint info, guint time_stamp, EAddressbookView *view); -static void invisible_destroyed (GtkWidget *invisible, EAddressbookView *view); - -static GtkTableClass *parent_class = NULL; - -/* The arguments we take */ enum { - ARG_0, - ARG_BOOK, - ARG_QUERY, - ARG_TYPE, + PROP_0, + PROP_COPY_TARGET_LIST, + PROP_MODEL, + PROP_PASTE_TARGET_LIST, + PROP_SHELL_VIEW, + PROP_SOURCE }; enum { - STATUS_MESSAGE, - SEARCH_RESULT, - FOLDER_BAR_MESSAGE, + OPEN_CONTACT, + POPUP_EVENT, COMMAND_STATE_CHANGE, - ALPHABET_STATE_CHANGE, + SELECTION_CHANGE, LAST_SIGNAL }; -enum DndTargetType { - DND_TARGET_TYPE_VCARD, +enum { + DND_TARGET_TYPE_SOURCE_VCARD, + DND_TARGET_TYPE_VCARD }; -#define VCARD_TYPE "text/x-vcard" + static GtkTargetEntry drag_types[] = { - { VCARD_TYPE, 0, DND_TARGET_TYPE_VCARD }, + { (gchar *) "text/x-source-vcard", 0, DND_TARGET_TYPE_SOURCE_VCARD }, + { (gchar *) "text/x-vcard", 0, DND_TARGET_TYPE_VCARD } }; -static const int num_drag_types = sizeof (drag_types) / sizeof (drag_types[0]); -static guint e_addressbook_view_signals [LAST_SIGNAL] = {0, }; +static guint signals[LAST_SIGNAL]; -static GdkAtom clipboard_atom = GDK_NONE; +/* Forward Declarations */ +static void e_addressbook_view_selectable_init + (ESelectableInterface *interface); -static GalViewCollection *collection = NULL; +G_DEFINE_TYPE_WITH_CODE ( + EAddressbookView, + e_addressbook_view, + GTK_TYPE_SCROLLED_WINDOW, + G_IMPLEMENT_INTERFACE ( + E_TYPE_SELECTABLE, + e_addressbook_view_selectable_init)) -GtkType -e_addressbook_view_get_type (void) +static void +addressbook_view_emit_open_contact (EAddressbookView *view, + EContact *contact, + gboolean is_new_contact) { - static GtkType type = 0; - - if (!type) { - static const GtkTypeInfo info = - { - "EAddressbookView", - sizeof (EAddressbookView), - sizeof (EAddressbookViewClass), - (GtkClassInitFunc) e_addressbook_view_class_init, - (GtkObjectInitFunc) e_addressbook_view_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - type = gtk_type_unique (gtk_table_get_type (), &info); - } - - return type; + g_signal_emit (view, signals[OPEN_CONTACT], 0, contact, is_new_contact); } static void -e_addressbook_view_class_init (EAddressbookViewClass *klass) +addressbook_view_emit_popup_event (EAddressbookView *view, + GdkEvent *event) { - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - - object_class = GTK_OBJECT_CLASS(klass); - widget_class = GTK_WIDGET_CLASS(klass); - - parent_class = gtk_type_class (gtk_table_get_type ()); - - object_class->set_arg = e_addressbook_view_set_arg; - object_class->get_arg = e_addressbook_view_get_arg; - object_class->destroy = e_addressbook_view_destroy; - - gtk_object_add_arg_type ("EAddressbookView::book", GTK_TYPE_OBJECT, - GTK_ARG_READWRITE, ARG_BOOK); - gtk_object_add_arg_type ("EAddressbookView::query", GTK_TYPE_STRING, - GTK_ARG_READWRITE, ARG_QUERY); - gtk_object_add_arg_type ("EAddressbookView::type", GTK_TYPE_ENUM, - GTK_ARG_READWRITE, ARG_TYPE); - - e_addressbook_view_signals [STATUS_MESSAGE] = - gtk_signal_new ("status_message", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EAddressbookViewClass, status_message), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); - - e_addressbook_view_signals [SEARCH_RESULT] = - gtk_signal_new ("search_result", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EAddressbookViewClass, search_result), - gtk_marshal_NONE__ENUM, - GTK_TYPE_NONE, 1, GTK_TYPE_ENUM); - - e_addressbook_view_signals [FOLDER_BAR_MESSAGE] = - gtk_signal_new ("folder_bar_message", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EAddressbookViewClass, folder_bar_message), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); - - e_addressbook_view_signals [COMMAND_STATE_CHANGE] = - gtk_signal_new ("command_state_change", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EAddressbookViewClass, command_state_change), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - e_addressbook_view_signals [ALPHABET_STATE_CHANGE] = - gtk_signal_new ("alphabet_state_change", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EAddressbookViewClass, alphabet_state_change), - gtk_marshal_NONE__UINT, - GTK_TYPE_NONE, 1, GTK_TYPE_UINT); - - gtk_object_class_add_signals (object_class, e_addressbook_view_signals, LAST_SIGNAL); - - if (!clipboard_atom) - clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); + /* Grab focus so that EFocusTracker asks us to update the + * selection-related actions before showing the popup menu. + * Apparently ETable doesn't automatically grab focus on + * right-clicks (is that a bug?). */ + gtk_widget_grab_focus (GTK_WIDGET (view)); + + g_signal_emit (view, signals[POPUP_EVENT], 0, event); } static void -e_addressbook_view_init (EAddressbookView *eav) +addressbook_view_emit_selection_change (EAddressbookView *view) { - eav->view_type = E_ADDRESSBOOK_VIEW_NONE; - - eav->model = e_addressbook_model_new (); - - gtk_signal_connect (GTK_OBJECT(eav->model), - "status_message", - GTK_SIGNAL_FUNC (status_message), - eav); - - gtk_signal_connect (GTK_OBJECT(eav->model), - "search_result", - GTK_SIGNAL_FUNC (search_result), - eav); - - gtk_signal_connect (GTK_OBJECT(eav->model), - "folder_bar_message", - GTK_SIGNAL_FUNC (folder_bar_message), - eav); - - gtk_signal_connect (GTK_OBJECT(eav->model), - "stop_state_changed", - GTK_SIGNAL_FUNC (stop_state_changed), - eav); - - gtk_signal_connect (GTK_OBJECT(eav->model), - "writable_status", - GTK_SIGNAL_FUNC (writable_status), - eav); - - gtk_signal_connect (GTK_OBJECT(eav->model), - "backend_died", - GTK_SIGNAL_FUNC (backend_died), - eav); - - eav->editable = FALSE; - eav->book = NULL; - eav->query = g_strdup (SHOW_ALL_SEARCH); - - eav->object = NULL; - eav->widget = NULL; - - eav->view_instance = NULL; - eav->view_menus = NULL; - eav->uic = NULL; - eav->current_alphabet_widget = NULL; - - eav->invisible = gtk_invisible_new (); - - gtk_selection_add_target (eav->invisible, - clipboard_atom, - GDK_SELECTION_TYPE_STRING, - 0); - - gtk_signal_connect (GTK_OBJECT(eav->invisible), "selection_get", - GTK_SIGNAL_FUNC (selection_get), - eav); - gtk_signal_connect (GTK_OBJECT(eav->invisible), "selection_clear_event", - GTK_SIGNAL_FUNC (selection_clear_event), - eav); - gtk_signal_connect (GTK_OBJECT(eav->invisible), "selection_received", - GTK_SIGNAL_FUNC (selection_received), - eav); - gtk_signal_connect (GTK_OBJECT(eav->invisible), "destroy", - GTK_SIGNAL_FUNC (invisible_destroyed), - eav); + g_signal_emit (view, signals[SELECTION_CHANGE], 0); } static void -e_addressbook_view_destroy (GtkObject *object) +addressbook_view_open_contact (EAddressbookView *view, + EContact *contact) { - EAddressbookView *eav = E_ADDRESSBOOK_VIEW(object); - - if (eav->model) { - gtk_object_unref(GTK_OBJECT(eav->model)); - eav->model = NULL; - } + addressbook_view_emit_open_contact (view, contact, FALSE); +} - if (eav->book) { - gtk_object_unref(GTK_OBJECT(eav->book)); - eav->book = NULL; - } +static void +addressbook_view_create_contact (EAddressbookView *view) +{ + EContact *contact; - g_free(eav->query); - eav->query = NULL; + contact = e_contact_new (); + addressbook_view_emit_open_contact (view, contact, TRUE); + g_object_unref (contact); +} - eav->uic = NULL; +static void +addressbook_view_create_contact_list (EAddressbookView *view) +{ + EContact *contact; - if (eav->view_instance) { - gtk_object_unref (GTK_OBJECT (eav->view_instance)); - eav->view_instance = NULL; - } + contact = e_contact_new (); + e_contact_set (contact, E_CONTACT_IS_LIST, GINT_TO_POINTER (TRUE)); + addressbook_view_emit_open_contact (view, contact, TRUE); + g_object_unref (contact); +} - if (eav->view_menus) { - gtk_object_unref (GTK_OBJECT (eav->view_menus)); - eav->view_menus = NULL; - } +static void +table_double_click (ETable *table, + gint row, + gint col, + GdkEvent *event, + EAddressbookView *view) +{ + EAddressbookModel *model; + EContact *contact; - if (eav->clipboard_cards) { - g_list_foreach (eav->clipboard_cards, (GFunc)gtk_object_unref, NULL); - g_list_free (eav->clipboard_cards); - eav->clipboard_cards = NULL; - } - - if (eav->invisible) { - gtk_widget_destroy (eav->invisible); - eav->invisible = NULL; - } + if (!E_IS_ADDRESSBOOK_TABLE_ADAPTER (view->priv->object)) + return; - if (GTK_OBJECT_CLASS(parent_class)->destroy) - GTK_OBJECT_CLASS(parent_class)->destroy(object); + model = e_addressbook_view_get_model (view); + contact = e_addressbook_model_get_contact (model, row); + addressbook_view_emit_open_contact (view, contact, FALSE); + g_object_unref (contact); } -GtkWidget* -e_addressbook_view_new (void) +static gint +table_right_click (ETable *table, + gint row, + gint col, + GdkEvent *event, + EAddressbookView *view) { - GtkWidget *widget = GTK_WIDGET (gtk_type_new (e_addressbook_view_get_type ())); - return widget; + addressbook_view_emit_popup_event (view, event); + + return TRUE; } -static void -writable_status (GtkObject *object, gboolean writable, EAddressbookView *eav) +static gint +table_white_space_event (ETable *table, + GdkEvent *event, + EAddressbookView *view) { - eav->editable = writable; - command_state_change (eav); + guint event_button = 0; + + gdk_event_get_button (event, &event_button); + + if (event->type == GDK_BUTTON_PRESS && event_button == 3) { + addressbook_view_emit_popup_event (view, event); + return TRUE; + } + + return FALSE; } static void -init_collection (void) +table_drag_data_get (ETable *table, + gint row, + gint col, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time, + gpointer user_data) { - GalViewFactory *factory; - ETableSpecification *spec; - char *galview; + EAddressbookView *view = user_data; + EAddressbookModel *model; + EBookClient *book_client; + GSList *contact_list; + GdkAtom target; + gchar *value; - if (collection == NULL) { - collection = gal_view_collection_new(); + if (!E_IS_ADDRESSBOOK_TABLE_ADAPTER (view->priv->object)) + return; - gal_view_collection_set_title (collection, _("Addressbook")); + model = e_addressbook_view_get_model (view); + book_client = e_addressbook_model_get_client (model); - galview = gnome_util_prepend_user_home("/evolution/views/addressbook/"); - gal_view_collection_set_storage_directories - (collection, - EVOLUTION_DATADIR "/evolution/views/addressbook/", - galview); - g_free(galview); + contact_list = e_addressbook_view_get_selected (view); + target = gtk_selection_data_get_target (selection_data); - spec = e_table_specification_new(); - e_table_specification_load_from_file (spec, EVOLUTION_ETSPECDIR "/e-addressbook-view.etspec"); + switch (info) { + case DND_TARGET_TYPE_VCARD: + value = eab_contact_list_to_string (contact_list); - factory = gal_view_factory_etable_new (spec); - gtk_object_unref (GTK_OBJECT (spec)); - gal_view_collection_add_factory (collection, factory); - gtk_object_unref (GTK_OBJECT (factory)); + gtk_selection_data_set ( + selection_data, target, 8, + (guchar *) value, strlen (value)); - factory = gal_view_factory_minicard_new (); - gal_view_collection_add_factory (collection, factory); - gtk_object_unref (GTK_OBJECT (factory)); + g_free (value); + break; - gal_view_collection_load(collection); - } -} + case DND_TARGET_TYPE_SOURCE_VCARD: + value = eab_book_and_contact_list_to_string ( + book_client, contact_list); -static void -display_view(GalViewInstance *instance, - GalView *view, - gpointer data) -{ - EAddressbookView *address_view = data; - if (GAL_IS_VIEW_ETABLE(view)) { - change_view_type (address_view, E_ADDRESSBOOK_VIEW_TABLE); - gal_view_etable_attach_table (GAL_VIEW_ETABLE(view), e_table_scrolled_get_table(E_TABLE_SCROLLED(address_view->widget))); - } else if (GAL_IS_VIEW_MINICARD(view)) { - change_view_type (address_view, E_ADDRESSBOOK_VIEW_MINICARD); - gal_view_minicard_attach (GAL_VIEW_MINICARD(view), E_MINICARD_VIEW_WIDGET (address_view->object)); + gtk_selection_data_set ( + selection_data, target, 8, + (guchar *) value, strlen (value)); + + g_free (value); + break; } - address_view->current_view = view; + + g_slist_free_full (contact_list, (GDestroyNotify) g_object_unref); } static void -setup_menus (EAddressbookView *view) +addressbook_view_create_table_view (EAddressbookView *view, + GalViewEtable *gal_view) { - if (view->book && view->view_instance == NULL) { - init_collection (); - view->view_instance = gal_view_instance_new (collection, e_book_get_uri (view->book)); - } + ETableModel *adapter; + ETableExtras *extras; + ETableSpecification *specification; + ECell *cell; + GtkWidget *widget; + gchar *etspecfile; + GError *local_error = NULL; - if (view->view_instance && view->uic) { - view->view_menus = gal_view_menus_new(view->view_instance); - gal_view_menus_apply(view->view_menus, view->uic, NULL); + adapter = e_addressbook_table_adapter_new (view->priv->model); - display_view (view->view_instance, gal_view_instance_get_current_view (view->view_instance), view); + extras = e_table_extras_new (); - gtk_signal_connect(GTK_OBJECT(view->view_instance), "display_view", - display_view, view); + /* Set proper format component for a default 'date' cell renderer. */ + cell = e_table_extras_get_cell (extras, "date"); + e_cell_date_set_format_component (E_CELL_DATE (cell), "addressbook"); + + etspecfile = g_build_filename ( + EVOLUTION_ETSPECDIR, "e-addressbook-view.etspec", NULL); + specification = e_table_specification_new (etspecfile, &local_error); + + /* Failure here is fatal. */ + if (local_error != NULL) { + g_error ("%s: %s", etspecfile, local_error->message); + g_assert_not_reached (); } -} -static void -e_addressbook_view_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) -{ - EAddressbookView *eav = E_ADDRESSBOOK_VIEW(object); + /* Here we create the table. We give it the three pieces of + * the table we've created, the header, the model, and the + * initial layout. It does the rest. */ + widget = e_table_new (adapter, extras, specification); + gtk_container_add (GTK_CONTAINER (view), widget); - switch (arg_id){ - case ARG_BOOK: - if (eav->book) { - gtk_object_unref(GTK_OBJECT(eav->book)); - } - if (GTK_VALUE_OBJECT(*arg)) { - eav->book = E_BOOK(GTK_VALUE_OBJECT(*arg)); - gtk_object_ref(GTK_OBJECT(eav->book)); - } - else - eav->book = NULL; + g_object_unref (specification); + g_free (etspecfile); - if (eav->view_instance) { - gtk_object_unref (GTK_OBJECT (eav->view_instance)); - eav->view_instance = NULL; - } + view->priv->object = G_OBJECT (adapter); - gtk_object_set(GTK_OBJECT(eav->model), - "book", eav->book, - NULL); + g_signal_connect ( + widget, "double_click", + G_CALLBACK (table_double_click), view); + g_signal_connect ( + widget, "right_click", + G_CALLBACK (table_right_click), view); + g_signal_connect ( + widget, "white_space_event", + G_CALLBACK (table_white_space_event), view); + g_signal_connect_swapped ( + widget, "selection_change", + G_CALLBACK (addressbook_view_emit_selection_change), view); - setup_menus (eav); + e_table_drag_source_set ( + E_TABLE (widget), GDK_BUTTON1_MASK, + drag_types, G_N_ELEMENTS (drag_types), + GDK_ACTION_MOVE | GDK_ACTION_COPY); - break; - case ARG_QUERY: -#if 0 /* This code will mess up ldap a bit. We need to think about the ramifications of this more. */ - if ((GTK_VALUE_STRING (*arg) == NULL && !strcmp (eav->query, SHOW_ALL_SEARCH)) || - (GTK_VALUE_STRING (*arg) != NULL && !strcmp (eav->query, GTK_VALUE_STRING (*arg)))) - break; -#endif - g_free(eav->query); - eav->query = g_strdup(GTK_VALUE_STRING(*arg)); - if (!eav->query) - eav->query = g_strdup (SHOW_ALL_SEARCH); - gtk_object_set(GTK_OBJECT(eav->model), - "query", eav->query, - NULL); - if (eav->current_alphabet_widget != NULL) { - GtkWidget *current = eav->current_alphabet_widget; - - eav->current_alphabet_widget = NULL; - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (current), FALSE); - } - break; - case ARG_TYPE: - change_view_type(eav, GTK_VALUE_ENUM(*arg)); - break; - default: - break; - } + g_signal_connect ( + E_TABLE (widget), "table_drag_data_get", + G_CALLBACK (table_drag_data_get), view); + + gtk_widget_show (widget); + + gal_view_etable_attach_table (gal_view, E_TABLE (widget)); } static void -e_addressbook_view_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +addressbook_view_create_minicard_view (EAddressbookView *view, + GalViewMinicard *gal_view) { - EAddressbookView *eav = E_ADDRESSBOOK_VIEW(object); + GtkWidget *minicard_view; + EAddressbookReflowAdapter *adapter; - switch (arg_id) { - case ARG_BOOK: - if (eav->book) - GTK_VALUE_OBJECT (*arg) = GTK_OBJECT(eav->book); - else - GTK_VALUE_OBJECT (*arg) = NULL; - break; - case ARG_QUERY: - GTK_VALUE_STRING (*arg) = eav->query; - break; - case ARG_TYPE: - GTK_VALUE_ENUM (*arg) = eav->view_type; - break; - default: - arg->type = GTK_TYPE_INVALID; - break; - } -} + adapter = E_ADDRESSBOOK_REFLOW_ADAPTER ( + e_addressbook_reflow_adapter_new (view->priv->model)); + minicard_view = e_minicard_view_widget_new (adapter); -static ESelectionModel* -get_selection_model (EAddressbookView *view) -{ - if (view->view_type == E_ADDRESSBOOK_VIEW_MINICARD) - return e_minicard_view_widget_get_selection_model (E_MINICARD_VIEW_WIDGET(view->object)); - else - return e_table_get_selection_model (e_table_scrolled_get_table (E_TABLE_SCROLLED(view->widget))); -} + g_signal_connect_swapped ( + adapter, "open-contact", + G_CALLBACK (addressbook_view_open_contact), view); -/* Popup menu stuff */ -typedef struct { - EAddressbookView *view; - EPopupMenu *submenu; - gpointer closure; -} CardAndBook; + g_signal_connect_swapped ( + minicard_view, "create-contact", + G_CALLBACK (addressbook_view_create_contact), view); -static ESelectionModel* -card_and_book_get_selection_model (CardAndBook *card_and_book) -{ - return get_selection_model (card_and_book->view); + g_signal_connect_swapped ( + minicard_view, "create-contact-list", + G_CALLBACK (addressbook_view_create_contact_list), view); + + g_signal_connect_swapped ( + minicard_view, "selection_change", + G_CALLBACK (addressbook_view_emit_selection_change), view); + + g_signal_connect_swapped ( + minicard_view, "right_click", + G_CALLBACK (addressbook_view_emit_popup_event), view); + + view->priv->object = G_OBJECT (minicard_view); + + gtk_container_add (GTK_CONTAINER (view), minicard_view); + gtk_widget_show (minicard_view); + + e_reflow_model_changed (E_REFLOW_MODEL (adapter)); + + gal_view_minicard_attach (gal_view, view); } static void -card_and_book_free (CardAndBook *card_and_book) +addressbook_view_display_view_cb (GalViewInstance *view_instance, + GalView *gal_view, + EAddressbookView *view) { - EAddressbookView *view = card_and_book->view; - ESelectionModel *selection; + EShellView *shell_view; + GtkWidget *child; - if (card_and_book->submenu) - gal_view_instance_free_popup_menu (view->view_instance, - card_and_book->submenu); + child = gtk_bin_get_child (GTK_BIN (view)); + if (child != NULL) + gtk_container_remove (GTK_CONTAINER (view), child); + view->priv->object = NULL; - selection = card_and_book_get_selection_model (card_and_book); - if (selection) - e_selection_model_right_click_up(selection); + if (GAL_IS_VIEW_ETABLE (gal_view)) + addressbook_view_create_table_view ( + view, GAL_VIEW_ETABLE (gal_view)); + else if (GAL_IS_VIEW_MINICARD (gal_view)) + addressbook_view_create_minicard_view ( + view, GAL_VIEW_MINICARD (gal_view)); - gtk_object_unref(GTK_OBJECT(view)); + shell_view = e_addressbook_view_get_shell_view (view); + e_shell_view_set_view_instance (shell_view, view_instance); + + command_state_change (view); } static void -get_card_list_1(gint model_row, - gpointer closure) +addressbook_view_set_shell_view (EAddressbookView *view, + EShellView *shell_view) { - CardAndBook *card_and_book; - GList **list; - EAddressbookView *view; - ECard *card; + g_return_if_fail (view->priv->shell_view == NULL); - card_and_book = closure; - list = card_and_book->closure; - view = card_and_book->view; + view->priv->shell_view = shell_view; - card = e_addressbook_model_get_card(view->model, model_row); - *list = g_list_prepend(*list, card); + g_object_add_weak_pointer ( + G_OBJECT (shell_view), + &view->priv->shell_view); } -static GList * -get_card_list (CardAndBook *card_and_book) +static void +addressbook_view_set_source (EAddressbookView *view, + ESource *source) { - GList *list = NULL; - ESelectionModel *selection; + g_return_if_fail (view->priv->source == NULL); - selection = card_and_book_get_selection_model (card_and_book); + view->priv->source = g_object_ref (source); +} + +static void +addressbook_view_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SHELL_VIEW: + addressbook_view_set_shell_view ( + E_ADDRESSBOOK_VIEW (object), + g_value_get_object (value)); + return; - if (selection) { - card_and_book->closure = &list; - e_selection_model_foreach (selection, get_card_list_1, card_and_book); + case PROP_SOURCE: + addressbook_view_set_source ( + E_ADDRESSBOOK_VIEW (object), + g_value_get_object (value)); + return; } - return list; + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -has_email_address_1(gint model_row, - gpointer closure) -{ - CardAndBook *card_and_book; - gboolean *has_email; - EAddressbookView *view; - const ECard *card; - EList *email; +addressbook_view_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_COPY_TARGET_LIST: + g_value_set_boxed ( + value, + e_addressbook_view_get_copy_target_list ( + E_ADDRESSBOOK_VIEW (object))); + return; - card_and_book = closure; - has_email = card_and_book->closure; - view = card_and_book->view; + case PROP_MODEL: + g_value_set_object ( + value, + e_addressbook_view_get_model ( + E_ADDRESSBOOK_VIEW (object))); + return; - if (*has_email) - return; + case PROP_PASTE_TARGET_LIST: + g_value_set_boxed ( + value, + e_addressbook_view_get_paste_target_list ( + E_ADDRESSBOOK_VIEW (object))); + return; - card = e_addressbook_model_peek_card(view->model, model_row); + case PROP_SHELL_VIEW: + g_value_set_object ( + value, + e_addressbook_view_get_shell_view ( + E_ADDRESSBOOK_VIEW (object))); + return; - gtk_object_get (GTK_OBJECT (card), - "email", &email, - NULL); + case PROP_SOURCE: + g_value_set_object ( + value, + e_addressbook_view_get_source ( + E_ADDRESSBOOK_VIEW (object))); + return; + } - if (e_list_length (email) > 0) - *has_email = TRUE; + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } -static gboolean -get_has_email_address (CardAndBook *card_and_book) +static void +addressbook_view_dispose (GObject *object) { - ESelectionModel *selection; - gboolean has_email = FALSE; + EAddressbookViewPrivate *priv; - selection = card_and_book_get_selection_model (card_and_book); + priv = E_ADDRESSBOOK_VIEW_GET_PRIVATE (object); - if (selection) { - card_and_book->closure = &has_email; - e_selection_model_foreach (selection, has_email_address_1, card_and_book); + if (priv->shell_view != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->shell_view), + &priv->shell_view); + priv->shell_view = NULL; } - return has_email; -} + if (priv->model != NULL) { + g_signal_handlers_disconnect_matched ( + priv->model, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, object); + g_object_unref (priv->model); + priv->model = NULL; + } -static void -save_as (GtkWidget *widget, CardAndBook *card_and_book) -{ - GList *cards = get_card_list (card_and_book); - if (cards) { - e_contact_list_save_as(_("Save as VCard"), cards, NULL); - e_free_object_list(cards); + if (priv->activity != NULL) { + /* XXX Activity is not cancellable. */ + e_activity_set_state (priv->activity, E_ACTIVITY_COMPLETED); + g_object_unref (priv->activity); + priv->activity = NULL; } -} -static void -send_as (GtkWidget *widget, CardAndBook *card_and_book) -{ - GList *cards = get_card_list (card_and_book); - if (cards) { - e_card_list_send(cards, E_CARD_DISPOSITION_AS_ATTACHMENT); - e_free_object_list(cards); + if (priv->source != NULL) { + g_object_unref (priv->source); + priv->source = NULL; } -} -static void -send_to (GtkWidget *widget, CardAndBook *card_and_book) + if (priv->view_instance != NULL) { + g_object_unref (priv->view_instance); + priv->view_instance = NULL; + } -{ - GList *cards = get_card_list (card_and_book); + priv->filter_id = 0; + priv->search_id = 0; - if (cards) { - e_card_list_send(cards, E_CARD_DISPOSITION_AS_TO); - e_free_object_list(cards); + if (priv->search_text) { + g_free (priv->search_text); + priv->search_text = NULL; } -} -static void -print (GtkWidget *widget, CardAndBook *card_and_book) -{ - GList *cards = get_card_list (card_and_book); - if (cards) { - if (cards->next) - gtk_widget_show(e_contact_print_card_list_dialog_new(cards)); - else - gtk_widget_show(e_contact_print_card_dialog_new(cards->data)); - e_free_object_list(cards); + if (priv->advanced_search) { + g_object_unref (priv->advanced_search); + priv->advanced_search = NULL; } -} -#if 0 /* Envelope printing is disabled for Evolution 1.0. */ -static void -print_envelope (GtkWidget *widget, CardAndBook *card_and_book) -{ - GList *cards = get_card_list (card_and_book); - if (cards) { - gtk_widget_show(e_contact_list_print_envelope_dialog_new(card_and_book->card)); - e_free_object_list(cards); + if (priv->copy_target_list != NULL) { + gtk_target_list_unref (priv->copy_target_list); + priv->copy_target_list = NULL; } -} -#endif -static void -copy (GtkWidget *widget, CardAndBook *card_and_book) -{ - e_addressbook_view_copy (card_and_book->view); -} + if (priv->paste_target_list != NULL) { + gtk_target_list_unref (priv->paste_target_list); + priv->paste_target_list = NULL; + } -static void -paste (GtkWidget *widget, CardAndBook *card_and_book) -{ - e_addressbook_view_paste (card_and_book->view); + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_addressbook_view_parent_class)->dispose (object); } static void -cut (GtkWidget *widget, CardAndBook *card_and_book) +addressbook_view_constructed (GObject *object) { - e_addressbook_view_cut (card_and_book->view); -} + EAddressbookView *view = E_ADDRESSBOOK_VIEW (object); + GalViewInstance *view_instance; + EShell *shell; + EShellView *shell_view; + EShellBackend *shell_backend; + EClientCache *client_cache; + ESource *source; + const gchar *uid; -static void -delete (GtkWidget *widget, CardAndBook *card_and_book) -{ - if (e_contact_editor_confirm_delete(GTK_WINDOW(gtk_widget_get_toplevel(card_and_book->view->widget)))) { - EBook *book; + shell_view = e_addressbook_view_get_shell_view (view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + shell = e_shell_backend_get_shell (shell_backend); + client_cache = e_shell_get_client_cache (shell); - GList *list = get_card_list(card_and_book); - GList *iterator; + source = e_addressbook_view_get_source (view); + uid = e_source_get_uid (source); - gtk_object_get(GTK_OBJECT(card_and_book->view->model), - "book", &book, - NULL); + view->priv->model = e_addressbook_model_new (client_cache); - for (iterator = list; iterator; iterator = iterator->next) { - ECard *card = iterator->data; - /* Remove the card. */ - e_book_remove_card (book, - card, - NULL, - NULL); - } - e_free_object_list(list); - } -} + view_instance = e_shell_view_new_view_instance (shell_view, uid); + g_signal_connect ( + view_instance, "display-view", + G_CALLBACK (addressbook_view_display_view_cb), view); + view->priv->view_instance = view_instance; -static void -copy_to_folder (GtkWidget *widget, CardAndBook *card_and_book) -{ - e_addressbook_view_copy_to_folder (card_and_book->view); -} + /* Do not call gal_view_instance_load() here. EBookShellContent + * must first obtain a reference to this EAddressbookView so that + * e_book_shell_content_get_current_view() returns the correct + * view in GalViewInstance::loaded signal handlers. */ -static void -move_to_folder (GtkWidget *widget, CardAndBook *card_and_book) -{ - e_addressbook_view_move_to_folder (card_and_book->view); + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_addressbook_view_parent_class)->constructed (object); } static void -free_popup_info (GtkWidget *w, CardAndBook *card_and_book) +addressbook_view_update_actions (ESelectable *selectable, + EFocusTracker *focus_tracker, + GdkAtom *clipboard_targets, + gint n_clipboard_targets) { - card_and_book_free (card_and_book); + EAddressbookView *view; + EAddressbookModel *model; + ESelectionModel *selection_model; + GtkAction *action; + GtkTargetList *target_list; + gboolean can_paste = FALSE; + gboolean source_is_editable; + gboolean sensitive; + const gchar *tooltip; + gint n_contacts; + gint n_selected; + gint ii; + + view = E_ADDRESSBOOK_VIEW (selectable); + model = e_addressbook_view_get_model (view); + selection_model = e_addressbook_view_get_selection_model (view); + + source_is_editable = e_addressbook_model_get_editable (model); + n_contacts = (selection_model != NULL) ? + e_selection_model_row_count (selection_model) : 0; + n_selected = (selection_model != NULL) ? + e_selection_model_selected_count (selection_model) : 0; + + target_list = e_selectable_get_paste_target_list (selectable); + for (ii = 0; ii < n_clipboard_targets && !can_paste; ii++) + can_paste = gtk_target_list_find ( + target_list, clipboard_targets[ii], NULL); + + action = e_focus_tracker_get_cut_clipboard_action (focus_tracker); + sensitive = source_is_editable && (n_selected > 0); + tooltip = _("Cut selected contacts to the clipboard"); + gtk_action_set_sensitive (action, sensitive); + gtk_action_set_tooltip (action, tooltip); + + action = e_focus_tracker_get_copy_clipboard_action (focus_tracker); + sensitive = (n_selected > 0); + tooltip = _("Copy selected contacts to the clipboard"); + gtk_action_set_sensitive (action, sensitive); + gtk_action_set_tooltip (action, tooltip); + + action = e_focus_tracker_get_paste_clipboard_action (focus_tracker); + sensitive = source_is_editable && can_paste; + tooltip = _("Paste contacts from the clipboard"); + gtk_action_set_sensitive (action, sensitive); + gtk_action_set_tooltip (action, tooltip); + + action = e_focus_tracker_get_delete_selection_action (focus_tracker); + sensitive = source_is_editable && (n_selected > 0); + tooltip = _("Delete selected contacts"); + gtk_action_set_sensitive (action, sensitive); + gtk_action_set_tooltip (action, tooltip); + + action = e_focus_tracker_get_select_all_action (focus_tracker); + sensitive = (n_contacts > 0); + tooltip = _("Select all visible contacts"); + gtk_action_set_sensitive (action, sensitive); + gtk_action_set_tooltip (action, tooltip); } static void -new_card (GtkWidget *widget, CardAndBook *card_and_book) +addressbook_view_cut_clipboard (ESelectable *selectable) { - EBook *book; - - gtk_object_get(GTK_OBJECT(card_and_book->view->model), - "book", &book, - NULL); - e_addressbook_show_contact_editor (book, e_card_new(""), TRUE, TRUE); -} + EAddressbookView *view; -static void -new_list (GtkWidget *widget, CardAndBook *card_and_book) -{ - EBook *book; + view = E_ADDRESSBOOK_VIEW (selectable); - gtk_object_get(GTK_OBJECT(card_and_book->view->model), - "book", &book, - NULL); - e_addressbook_show_contact_list_editor (book, e_card_new(""), TRUE, TRUE); + e_selectable_copy_clipboard (selectable); + e_addressbook_view_delete_selection (view, FALSE); } -#if 0 static void -sources (GtkWidget *widget, CardAndBook *card_and_book) +addressbook_view_copy_clipboard (ESelectable *selectable) { - BonoboControl *control; - GNOME_Evolution_ShellView shell_view; - CORBA_Environment ev; + EAddressbookView *view; + GtkClipboard *clipboard; + GSList *contact_list; + gchar *string; - control = gtk_object_get_data (GTK_OBJECT (gcal), "control"); - if (control == NULL) - return; + view = E_ADDRESSBOOK_VIEW (selectable); + clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); - shell_view = get_shell_view_interface (control); - if (shell_view == CORBA_OBJECT_NIL) - return; + contact_list = e_addressbook_view_get_selected (view); - CORBA_exception_init (&ev); - - GNOME_Evolution_ShellView_showSettings (shell_view, &ev); - - if (BONOBO_EX (&ev)) - g_message ("control_util_show_settings(): Could not show settings"); + string = eab_contact_list_to_string (contact_list); + e_clipboard_set_directory (clipboard, string, -1); + g_free (string); - CORBA_exception_free (&ev); + g_slist_free_full (contact_list, (GDestroyNotify) g_object_unref); } -#endif - -#define POPUP_READONLY_MASK 0x1 -#define POPUP_NOSELECTION_MASK 0x2 -#define POPUP_NOEMAIL_MASK 0x4 static void -do_popup_menu(EAddressbookView *view, GdkEvent *event) +addressbook_view_paste_clipboard (ESelectable *selectable) { - CardAndBook *card_and_book; - GtkMenu *popup; - EPopupMenu *submenu = NULL; - ESelectionModel *selection_model; - gboolean selection = FALSE; - - EPopupMenu menu[] = { - E_POPUP_ITEM (N_("New Contact..."), GTK_SIGNAL_FUNC(new_card), POPUP_READONLY_MASK), - E_POPUP_ITEM (N_("New Contact List..."), GTK_SIGNAL_FUNC(new_list), POPUP_READONLY_MASK), - E_POPUP_SEPARATOR, -#if 0 - E_POPUP_ITEM (N_("Go to Folder..."), GTK_SIGNAL_FUNC (goto_folder), 0), - E_POPUP_ITEM (N_("Import..."), GTK_SIGNAL_FUNC (import), POPUP_READONLY_MASK), - E_POPUP_SEPARATOR, - E_POPUP_ITEM (N_("Search for Contacts..."), GTK_SIGNAL_FUNC (search), 0), - E_POPUP_ITEM (N_("Addressbook Sources..."), GTK_SIGNAL_FUNC (sources), 0), - E_POPUP_SEPARATOR, - E_POPUP_ITEM (N_("Pilot Settings..."), GTK_SIGNAL_FUNC (pilot_settings), 0), -#endif - E_POPUP_SEPARATOR, - E_POPUP_ITEM (N_("Save as VCard"), GTK_SIGNAL_FUNC(save_as), POPUP_NOSELECTION_MASK), - E_POPUP_ITEM (N_("Forward Contact"), GTK_SIGNAL_FUNC(send_as), POPUP_NOSELECTION_MASK), - E_POPUP_ITEM (N_("Send Message to Contact"), GTK_SIGNAL_FUNC(send_to), POPUP_NOSELECTION_MASK | POPUP_NOEMAIL_MASK), - E_POPUP_ITEM (N_("Print"), GTK_SIGNAL_FUNC(print), POPUP_NOSELECTION_MASK), -#if 0 /* Envelope printing is disabled for Evolution 1.0. */ - E_POPUP_ITEM (N_("Print Envelope"), GTK_SIGNAL_FUNC(print_envelope), POPUP_NOSELECTION_MASK), -#endif - E_POPUP_SEPARATOR, + EBookClient *book_client; + EAddressbookView *view; + EAddressbookModel *model; + EClientCache *client_cache; + ESourceRegistry *registry; + GtkClipboard *clipboard; + GSList *contact_list, *iter; + gchar *string; - E_POPUP_ITEM (N_("Copy to folder..."), GTK_SIGNAL_FUNC(copy_to_folder), POPUP_NOSELECTION_MASK), - E_POPUP_ITEM (N_("Move to folder..."), GTK_SIGNAL_FUNC(move_to_folder), POPUP_READONLY_MASK | POPUP_NOSELECTION_MASK), - E_POPUP_SEPARATOR, + view = E_ADDRESSBOOK_VIEW (selectable); + clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); - E_POPUP_ITEM (N_("Cut"), GTK_SIGNAL_FUNC (cut), POPUP_READONLY_MASK | POPUP_NOSELECTION_MASK), - E_POPUP_ITEM (N_("Copy"), GTK_SIGNAL_FUNC (copy), POPUP_NOSELECTION_MASK), - E_POPUP_ITEM (N_("Paste"), GTK_SIGNAL_FUNC (paste), POPUP_READONLY_MASK), - E_POPUP_ITEM (N_("Delete"), GTK_SIGNAL_FUNC(delete), POPUP_READONLY_MASK | POPUP_NOSELECTION_MASK), - E_POPUP_SEPARATOR, + if (!e_clipboard_wait_is_directory_available (clipboard)) + return; -#if 0 - E_POPUP_SUBMENU (N_("Current View"), submenu = gal_view_instance_get_popup_menu (view->view_instance), 0), -#endif - E_POPUP_TERMINATOR - }; + model = e_addressbook_view_get_model (view); + client_cache = e_addressbook_model_get_client_cache (model); + book_client = e_addressbook_model_get_client (model); - card_and_book = g_new(CardAndBook, 1); - card_and_book->view = view; - card_and_book->submenu = submenu; + string = e_clipboard_wait_for_directory (clipboard); + contact_list = eab_contact_list_from_string (string); + g_free (string); - gtk_object_ref(GTK_OBJECT(card_and_book->view)); + registry = e_client_cache_ref_registry (client_cache); - selection_model = card_and_book_get_selection_model (card_and_book); - if (selection_model) - selection = e_selection_model_selected_count (selection_model) > 0; + for (iter = contact_list; iter != NULL; iter = iter->next) { + EContact *contact = iter->data; - popup = e_popup_menu_create (menu, - 0, - (e_addressbook_model_editable (view->model) ? 0 : POPUP_READONLY_MASK) + - (selection ? 0 : POPUP_NOSELECTION_MASK) + - (get_has_email_address (card_and_book) ? 0 : POPUP_NOEMAIL_MASK), - card_and_book); + eab_merging_book_add_contact ( + registry, book_client, contact, NULL, NULL); + } - gtk_signal_connect (GTK_OBJECT (popup), "selection-done", - GTK_SIGNAL_FUNC (free_popup_info), card_and_book); - e_popup_menu (popup, event); + g_object_unref (registry); + g_slist_free_full (contact_list, (GDestroyNotify) g_object_unref); } +static void +addressbook_view_delete_selection (ESelectable *selectable) +{ + EAddressbookView *view; -/* Minicard view stuff */ - -/* Translators: put here a list of labels you want to see on buttons in - addressbook. You may use any character to separate labels but it must - also be placed at the begining ot the string */ -const char *button_labels = N_(",123,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"); -/* Translators: put here a list of characters that correspond to buttons - in addressbook. You may use any character to separate labels but it - must also be placed at the begining ot the string. - Use lower case letters if possible. */ -const char *button_letters = N_(",0,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"); + view = E_ADDRESSBOOK_VIEW (selectable); -typedef struct { - EAddressbookView *view; - GtkWidget *button; - GtkWidget *vbox; - gunichar letter; -} LetterClosure; + e_addressbook_view_delete_selection (view, TRUE); +} -static char ** -e_utf8_split (const char *utf8_str, gunichar delim) +static void +addressbook_view_select_all (ESelectable *selectable) { - GSList *str_list = NULL, *sl; - int n = 0; - const char *str, *s; - char **str_array; - - g_return_val_if_fail (utf8_str != NULL, NULL); - - str = utf8_str; - while (*str != '\0') { - int len; - char *new_str; - - for (s = str; *s != '\0' && g_utf8_get_char (s) != delim; s = g_utf8_next_char (s)) - ; - len = s - str; - new_str = g_new (char, len + 1); - if (len > 0) { - memcpy (new_str, str, len); - } - new_str[len] = '\0'; - str_list = g_slist_prepend (str_list, new_str); - n++; - if (*s != '\0') { - str = g_utf8_next_char (s); - } else { - str = s; - } - } + EAddressbookView *view; + ESelectionModel *selection_model; - str_array = g_new (char *, n + 1); - str_array[n--] = NULL; - for (sl = str_list; sl != NULL; sl = sl->next) { - str_array[n--] = sl->data; - } - g_slist_free (str_list); + view = E_ADDRESSBOOK_VIEW (selectable); + selection_model = e_addressbook_view_get_selection_model (view); - return str_array; + if (selection_model != NULL) + e_selection_model_select_all (selection_model); } static void -jump_to_letter(EAddressbookView *view, gunichar letter) -{ - char *query; - - if (g_unichar_isdigit (letter)) { - const char *letters = U_(button_letters); - char **letter_v; - GString *gstr; - char **p; - - letter_v = e_utf8_split (g_utf8_next_char (letters), - g_utf8_get_char (letters)); - g_assert (letter_v != NULL && letter_v[0] != NULL); - gstr = g_string_new ("(not (or "); - for (p = letter_v + 1; *p != NULL; p++) { - g_string_sprintfa (gstr, "(beginswith \"file_as\" \"%s\")", *p); - } - g_string_append (gstr, "))"); - query = gstr->str; - g_strfreev (letter_v); - g_string_free (gstr, FALSE); - } else { - char s[6 + 1]; - - s [g_unichar_to_utf8 (letter, s)] = '\0'; - query = g_strdup_printf ("(beginswith \"file_as\" \"%s\")", s); - } - gtk_object_set (GTK_OBJECT (view), - "query", query, - NULL); - g_free (query); +e_addressbook_view_class_init (EAddressbookViewClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (EAddressbookViewPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = addressbook_view_set_property; + object_class->get_property = addressbook_view_get_property; + object_class->dispose = addressbook_view_dispose; + object_class->constructed = addressbook_view_constructed; + + /* Inherited from ESelectableInterface */ + g_object_class_override_property ( + object_class, + PROP_COPY_TARGET_LIST, + "copy-target-list"); + + g_object_class_install_property ( + object_class, + PROP_MODEL, + g_param_spec_object ( + "model", + "Model", + NULL, + E_TYPE_ADDRESSBOOK_MODEL, + G_PARAM_READABLE)); + + /* Inherited from ESelectableInterface */ + g_object_class_override_property ( + object_class, + PROP_PASTE_TARGET_LIST, + "paste-target-list"); + + g_object_class_install_property ( + object_class, + PROP_SHELL_VIEW, + g_param_spec_object ( + "shell-view", + "Shell View", + NULL, + E_TYPE_SHELL_VIEW, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property ( + object_class, + PROP_SOURCE, + g_param_spec_object ( + "source", + "Source", + NULL, + E_TYPE_SOURCE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + signals[OPEN_CONTACT] = g_signal_new ( + "open-contact", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookViewClass, open_contact), + NULL, NULL, + e_marshal_VOID__OBJECT_BOOLEAN, + G_TYPE_NONE, 2, + E_TYPE_CONTACT, + G_TYPE_BOOLEAN); + + signals[POPUP_EVENT] = g_signal_new ( + "popup-event", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookViewClass, popup_event), + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + + signals[COMMAND_STATE_CHANGE] = g_signal_new ( + "command-state-change", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookViewClass, command_state_change), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[SELECTION_CHANGE] = g_signal_new ( + "selection-change", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookViewClass, selection_change), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /* init the accessibility support for e_addressbook_view */ + eab_view_a11y_init (); } static void -button_toggled(GtkWidget *button, LetterClosure *closure) +e_addressbook_view_init (EAddressbookView *view) { - EAddressbookView *view = closure->view; + GtkTargetList *target_list; - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) { - GtkWidget *current = view->current_alphabet_widget; + view->priv = E_ADDRESSBOOK_VIEW_GET_PRIVATE (view); - view->current_alphabet_widget = NULL; - if (current && current != button) - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (current), FALSE); - jump_to_letter (view, closure->letter); - view->current_alphabet_widget = button; - alphabet_state_change (view, closure->letter); - } else { - if (view->current_alphabet_widget != NULL && - view->current_alphabet_widget == button) { - view->current_alphabet_widget = NULL; - gtk_object_set (GTK_OBJECT (view), - "query", NULL, - NULL); - alphabet_state_change (view, 0); - } - } + target_list = gtk_target_list_new (NULL, 0); + e_target_list_add_directory_targets (target_list, 0); + view->priv->copy_target_list = target_list; + + target_list = gtk_target_list_new (NULL, 0); + e_target_list_add_directory_targets (target_list, 0); + view->priv->paste_target_list = target_list; + + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (view), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (view), GTK_SHADOW_IN); } static void -free_closure(GtkWidget *button, LetterClosure *closure) +e_addressbook_view_selectable_init (ESelectableInterface *interface) { - if (button != NULL && - button == closure->view->current_alphabet_widget) { - closure->view->current_alphabet_widget = NULL; - } - g_free(closure); + interface->update_actions = addressbook_view_update_actions; + interface->cut_clipboard = addressbook_view_cut_clipboard; + interface->copy_clipboard = addressbook_view_copy_clipboard; + interface->paste_clipboard = addressbook_view_paste_clipboard; + interface->delete_selection = addressbook_view_delete_selection; + interface->select_all = addressbook_view_select_all; } -static GtkWidget * -create_alphabet (EAddressbookView *view) +GtkWidget * +e_addressbook_view_new (EShellView *shell_view, + ESource *source) { - GtkWidget *widget, *viewport, *vbox; - const char *labels, *letters; - char **label_v, **letter_v; - char **pl, **pc; - gunichar sep; - - widget = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget), - GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - - viewport = gtk_viewport_new (NULL, NULL); - gtk_container_add (GTK_CONTAINER (widget), viewport); - gtk_container_set_border_width (GTK_CONTAINER (viewport), 4); - gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), GTK_SHADOW_NONE); - - vbox = gtk_vbox_new (FALSE, 4); - gtk_container_add (GTK_CONTAINER (viewport), vbox); - gtk_widget_set_usize (vbox, 27, 0); - - labels = U_(button_labels); - sep = g_utf8_get_char (labels); - label_v = e_utf8_split (g_utf8_next_char (labels), sep); - letters = U_(button_letters); - sep = g_utf8_get_char (letters); - letter_v = e_utf8_split (g_utf8_next_char (letters), sep); - g_assert (label_v != NULL && letter_v != NULL); - for (pl = label_v, pc = letter_v; *pl != NULL && *pc != NULL; pl++, pc++) { - GtkWidget *button; - LetterClosure *closure; - char *label; - - label = e_utf8_to_locale_string (*pl); - button = gtk_toggle_button_new_with_label (label); - g_free (label); - gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); - - closure = g_new (LetterClosure, 1); - closure->view = view; - closure->letter = g_utf8_get_char (*pc); - closure->button = button; - closure->vbox = vbox; - gtk_signal_connect(GTK_OBJECT(button), "toggled", - GTK_SIGNAL_FUNC (button_toggled), closure); - gtk_signal_connect(GTK_OBJECT(button), "destroy", - GTK_SIGNAL_FUNC (free_closure), closure); - - } - g_strfreev (label_v); - g_strfreev (letter_v); + GtkWidget *widget; + EAddressbookView *view; - gtk_widget_show_all (widget); + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + widget = g_object_new ( + E_TYPE_ADDRESSBOOK_VIEW, "shell-view", + shell_view, "source", source, NULL); + + view = E_ADDRESSBOOK_VIEW (widget); + + g_signal_connect_swapped ( + view->priv->model, "status_message", + G_CALLBACK (status_message), view); + g_signal_connect_swapped ( + view->priv->model, "search_result", + G_CALLBACK (search_result), view); + g_signal_connect_swapped ( + view->priv->model, "folder_bar_message", + G_CALLBACK (folder_bar_message), view); + g_signal_connect ( + view->priv->model, "stop_state_changed", + G_CALLBACK (stop_state_changed), view); + g_signal_connect_swapped ( + view->priv->model, "writable-status", + G_CALLBACK (command_state_change), view); return widget; } -static void -minicard_selection_change (EMinicardViewWidget *widget, EAddressbookView *view) +EAddressbookModel * +e_addressbook_view_get_model (EAddressbookView *view) { - command_state_change (view); -} + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); -static void -minicard_button_press (GtkWidget *widget, GdkEventButton *event, EAddressbookView *view) -{ - d(g_print ("Button %d pressed with event type %d\n", event->button, event->type)); + return view->priv->model; } -static void -minicard_right_click (EMinicardView *minicard_view_item, GdkEvent *event, EAddressbookView *view) +GalViewInstance * +e_addressbook_view_get_view_instance (EAddressbookView *view) { - do_popup_menu(view, event); + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); + + return view->priv->view_instance; } -static void -create_minicard_view (EAddressbookView *view) +GObject * +e_addressbook_view_get_view_object (EAddressbookView *view) { - GtkWidget *scrollframe; - GtkWidget *alphabet; - GtkWidget *minicard_view; - GtkWidget *minicard_hbox; - EAddressbookReflowAdapter *adapter; + /* XXX Find a more descriptive name for this. */ - gtk_widget_push_visual (gdk_rgb_get_visual ()); - gtk_widget_push_colormap (gdk_rgb_get_cmap ()); + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); - minicard_hbox = gtk_hbox_new(FALSE, 0); + return view->priv->object; +} - adapter = E_ADDRESSBOOK_REFLOW_ADAPTER(e_addressbook_reflow_adapter_new (view->model)); - minicard_view = e_minicard_view_widget_new(adapter); +/* Helper for e_addressbook_view_get_selected() */ +static void +add_to_list (gint model_row, + gpointer closure) +{ + GSList **list = closure; + *list = g_slist_prepend (*list, GINT_TO_POINTER (model_row)); +} - /* A hack */ - gtk_object_set_data (GTK_OBJECT (adapter), "view", view); +GSList * +e_addressbook_view_get_selected (EAddressbookView *view) +{ + GSList *list, *iter; + ESelectionModel *selection; - gtk_signal_connect(GTK_OBJECT(minicard_view), "selection_change", - GTK_SIGNAL_FUNC(minicard_selection_change), view); + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); - gtk_signal_connect(GTK_OBJECT(minicard_view), "button_press_event", - GTK_SIGNAL_FUNC(minicard_button_press), view); + list = NULL; + selection = e_addressbook_view_get_selection_model (view); + e_selection_model_foreach (selection, add_to_list, &list); - gtk_signal_connect(GTK_OBJECT(minicard_view), "right_click", - GTK_SIGNAL_FUNC(minicard_right_click), view); + for (iter = list; iter != NULL; iter = iter->next) + iter->data = e_addressbook_model_get_contact ( + view->priv->model, GPOINTER_TO_INT (iter->data)); + return g_slist_reverse (list); +} +ESelectionModel * +e_addressbook_view_get_selection_model (EAddressbookView *view) +{ + GalView *gal_view; + GalViewInstance *view_instance; + ESelectionModel *model = NULL; - view->object = GTK_OBJECT(minicard_view); - view->widget = minicard_hbox; + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); - scrollframe = e_scroll_frame_new (NULL, NULL); - e_scroll_frame_set_policy (E_SCROLL_FRAME (scrollframe), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); + view_instance = e_addressbook_view_get_view_instance (view); + gal_view = gal_view_instance_get_current_view (view_instance); - gtk_container_add (GTK_CONTAINER (scrollframe), minicard_view); + if (GAL_IS_VIEW_ETABLE (gal_view)) { + GtkWidget *child; + child = gtk_bin_get_child (GTK_BIN (view)); + model = e_table_get_selection_model (E_TABLE (child)); - gtk_box_pack_start(GTK_BOX(minicard_hbox), scrollframe, TRUE, TRUE, 0); + } else if (GAL_IS_VIEW_MINICARD (gal_view)) { + EMinicardViewWidget *widget; - alphabet = create_alphabet(view); - if (alphabet) { - gtk_object_ref(GTK_OBJECT(alphabet)); - gtk_widget_unparent(alphabet); - gtk_box_pack_start(GTK_BOX(minicard_hbox), alphabet, FALSE, FALSE, 0); - gtk_object_unref(GTK_OBJECT(alphabet)); + widget = E_MINICARD_VIEW_WIDGET (view->priv->object); + model = e_minicard_view_widget_get_selection_model (widget); } - gtk_table_attach(GTK_TABLE(view), minicard_hbox, - 0, 1, - 0, 1, - GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, - 0, 0); - - gtk_widget_show_all( GTK_WIDGET(minicard_hbox) ); - - gtk_widget_pop_visual (); - gtk_widget_pop_colormap (); - - e_reflow_model_changed (E_REFLOW_MODEL (adapter)); - - gtk_object_unref (GTK_OBJECT (adapter)); + return model; } -static void -table_double_click(ETableScrolled *table, gint row, gint col, GdkEvent *event, EAddressbookView *view) +EShellView * +e_addressbook_view_get_shell_view (EAddressbookView *view) { - if (E_IS_ADDRESSBOOK_TABLE_ADAPTER(view->object)) { - EAddressbookModel *model = view->model; - ECard *card = e_addressbook_model_get_card(model, row); - EBook *book; - - gtk_object_get(GTK_OBJECT(model), - "book", &book, - NULL); - - g_assert (E_IS_BOOK (book)); - - if (e_card_evolution_list (card)) - e_addressbook_show_contact_list_editor (book, card, FALSE, view->editable); - else - e_addressbook_show_contact_editor (book, card, FALSE, view->editable); - } -} + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); -static gint -table_right_click(ETableScrolled *table, gint row, gint col, GdkEvent *event, EAddressbookView *view) -{ - do_popup_menu(view, event); - return TRUE; + return view->priv->shell_view; } -static gint -table_white_space_event(ETableScrolled *table, GdkEvent *event, EAddressbookView *view) +ESource * +e_addressbook_view_get_source (EAddressbookView *view) { - if (event->type == GDK_BUTTON_PRESS && ((GdkEventButton *)event)->button == 3) { - do_popup_menu(view, event); - return TRUE; - } else { - return FALSE; - } + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); + + return view->priv->source; } -static void -table_selection_change(ETableScrolled *table, EAddressbookView *view) +GtkTargetList * +e_addressbook_view_get_copy_target_list (EAddressbookView *view) { - command_state_change (view); + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); + + return view->priv->copy_target_list; } -static void -table_drag_data_get (ETable *table, - int row, - int col, - GdkDragContext *context, - GtkSelectionData *selection_data, - guint info, - guint time, - gpointer user_data) +GtkTargetList * +e_addressbook_view_get_paste_target_list (EAddressbookView *view) { - EAddressbookView *view = user_data; - - if (!E_IS_ADDRESSBOOK_TABLE_ADAPTER(view->object)) - return; + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); - switch (info) { - case DND_TARGET_TYPE_VCARD: { - char *value; + return view->priv->paste_target_list; +} - row = e_table_view_to_model_row (table, row); - value = e_card_get_vcard(view->model->data[row]); +static void +status_message (EAddressbookView *view, + const gchar *status, + gint percent) +{ + EActivity *activity; + EShellView *shell_view; + EShellBackend *shell_backend; + + activity = view->priv->activity; + shell_view = e_addressbook_view_get_shell_view (view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + if (status == NULL || *status == '\0') { + if (activity != NULL) { + view->priv->activity = NULL; + e_activity_set_state (activity, E_ACTIVITY_COMPLETED); + g_object_unref (activity); + } - gtk_selection_data_set (selection_data, - selection_data->target, - 8, - value, strlen (value)); - break; - } + } else if (activity == NULL) { + activity = e_activity_new (); + view->priv->activity = activity; + e_activity_set_text (activity, status); + if (percent >= 0) + e_activity_set_percent (activity, percent); + e_shell_backend_add_activity (shell_backend, activity); + } else { + e_activity_set_text (activity, status); + if (percent >= 0) + e_activity_set_percent (activity, percent); } } static void -emit_status_message (EAddressbookView *eav, const gchar *status) +search_result (EAddressbookView *view, + const GError *error) { - gtk_signal_emit (GTK_OBJECT (eav), - e_addressbook_view_signals [STATUS_MESSAGE], - status); -} + EShellView *shell_view; + EAlertSink *alert_sink; -static void -emit_search_result (EAddressbookView *eav, EBookViewStatus status) -{ - gtk_signal_emit (GTK_OBJECT (eav), - e_addressbook_view_signals [SEARCH_RESULT], - status); -} + shell_view = e_addressbook_view_get_shell_view (view); + alert_sink = E_ALERT_SINK (e_shell_view_get_shell_content (shell_view)); -static void -emit_folder_bar_message (EAddressbookView *eav, const gchar *message) -{ - gtk_signal_emit (GTK_OBJECT (eav), - e_addressbook_view_signals [FOLDER_BAR_MESSAGE], - message); + eab_search_result_dialog (alert_sink, error); } static void -status_message (GtkObject *object, const gchar *status, EAddressbookView *eav) +folder_bar_message (EAddressbookView *view, + const gchar *message) { - emit_status_message (eav, status); -} + EShellView *shell_view; + EShellSidebar *shell_sidebar; + const gchar *display_name; -static void -search_result (GtkObject *object, EBookViewStatus status, EAddressbookView *eav) -{ - emit_search_result (eav, status); -} + shell_view = e_addressbook_view_get_shell_view (view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); -static void -folder_bar_message (GtkObject *object, const gchar *status, EAddressbookView *eav) -{ - emit_folder_bar_message (eav, status); -} + if (view->priv->source == NULL) + return; -static void -stop_state_changed (GtkObject *object, EAddressbookView *eav) -{ - command_state_change (eav); + display_name = e_source_get_display_name (view->priv->source); + e_shell_sidebar_set_primary_text (shell_sidebar, display_name); + e_shell_sidebar_set_secondary_text (shell_sidebar, message); } static void -command_state_change (EAddressbookView *eav) +stop_state_changed (GObject *object, + EAddressbookView *view) { - /* Reffing during emission is unnecessary. Gtk automatically refs during an emission. */ - gtk_signal_emit (GTK_OBJECT (eav), e_addressbook_view_signals [COMMAND_STATE_CHANGE]); + command_state_change (view); } static void -alphabet_state_change (EAddressbookView *eav, gunichar letter) +command_state_change (EAddressbookView *view) { - gtk_signal_emit (GTK_OBJECT (eav), e_addressbook_view_signals [ALPHABET_STATE_CHANGE], letter); + g_signal_emit (view, signals[COMMAND_STATE_CHANGE], 0); } static void -backend_died (GtkObject *object, EAddressbookView *eav) +contact_print_button_draw_page (GtkPrintOperation *operation, + GtkPrintContext *context, + gint page_nr, + EPrintable *printable) { - char *message = g_strdup_printf (_("The addressbook backend for\n%s\nhas crashed. " - "You will have to restart Evolution in order " - "to use it again"), - e_book_get_uri (eav->book)); - gnome_error_dialog_parented (message, GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (eav)))); - g_free (message); -} + GtkPageSetup *setup; + gdouble top_margin, page_width; + cairo_t *cr; -static void -create_table_view (EAddressbookView *view) -{ - ETableModel *adapter; - ECardSimple *simple; - GtkWidget *table; - - simple = e_card_simple_new(NULL); + setup = gtk_print_context_get_page_setup (context); + top_margin = gtk_page_setup_get_top_margin (setup, GTK_UNIT_POINTS); + page_width = gtk_page_setup_get_page_width (setup, GTK_UNIT_POINTS); - adapter = e_addressbook_table_adapter_new(view->model); + cr = gtk_print_context_get_cairo_context (context); - /* Here we create the table. We give it the three pieces of - the table we've created, the header, the model, and the - initial layout. It does the rest. */ - table = e_table_scrolled_new_from_spec_file (adapter, NULL, EVOLUTION_ETSPECDIR "/e-addressbook-view.etspec", NULL); - - view->object = GTK_OBJECT(adapter); - view->widget = table; - - gtk_signal_connect(GTK_OBJECT(e_table_scrolled_get_table(E_TABLE_SCROLLED(table))), "double_click", - GTK_SIGNAL_FUNC(table_double_click), view); - gtk_signal_connect(GTK_OBJECT(e_table_scrolled_get_table(E_TABLE_SCROLLED(table))), "right_click", - GTK_SIGNAL_FUNC(table_right_click), view); - gtk_signal_connect(GTK_OBJECT(e_table_scrolled_get_table(E_TABLE_SCROLLED(table))), "white_space_event", - GTK_SIGNAL_FUNC(table_white_space_event), view); - gtk_signal_connect(GTK_OBJECT(e_table_scrolled_get_table(E_TABLE_SCROLLED(table))), "selection_change", - GTK_SIGNAL_FUNC(table_selection_change), view); - - /* drag & drop signals */ - e_table_drag_source_set (E_TABLE(E_TABLE_SCROLLED(table)->table), GDK_BUTTON1_MASK, - drag_types, num_drag_types, GDK_ACTION_MOVE); - - gtk_signal_connect (GTK_OBJECT (E_TABLE_SCROLLED(table)->table), - "table_drag_data_get", - GTK_SIGNAL_FUNC (table_drag_data_get), - view); - - gtk_table_attach(GTK_TABLE(view), table, - 0, 1, - 0, 1, - GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, - 0, 0); - - gtk_widget_show( GTK_WIDGET(table) ); - - gtk_object_unref(GTK_OBJECT(simple)); -} + e_printable_reset (printable); + while (e_printable_data_left (printable)) { + cairo_save (cr); + contact_page_draw_footer (operation,context,page_nr++); + e_printable_print_page ( + printable, context, page_width - 16, top_margin + 10, TRUE); + cairo_restore (cr); + } +} static void -change_view_type (EAddressbookView *view, EAddressbookViewType view_type) +e_contact_print_button (EPrintable *printable, + GtkPrintOperationAction action) { - if (view_type == view->view_type) - return; + GtkPrintOperation *operation; - if (view->widget) { - gtk_widget_destroy (view->widget); - view->widget = NULL; - } - view->object = NULL; - - switch (view_type) { - case E_ADDRESSBOOK_VIEW_MINICARD: - create_minicard_view (view); - break; - case E_ADDRESSBOOK_VIEW_TABLE: - create_table_view (view); - break; - default: - g_warning ("view_type must be either TABLE or MINICARD\n"); - return; - } + operation = e_print_operation_new (); + gtk_print_operation_set_n_pages (operation, 1); - view->view_type = view_type; + g_signal_connect ( + operation, "draw_page", + G_CALLBACK (contact_print_button_draw_page), printable); - command_state_change (view); -} + gtk_print_operation_run (operation, action, NULL, NULL); -static void -e_contact_print_destroy(GnomeDialog *dialog, gpointer data) -{ - ETableScrolled *table = gtk_object_get_data(GTK_OBJECT(dialog), "table"); - EPrintable *printable = gtk_object_get_data(GTK_OBJECT(dialog), "printable"); - gtk_object_unref(GTK_OBJECT(printable)); - gtk_object_unref(GTK_OBJECT(table)); -} - -static void -e_contact_print_button(GnomeDialog *dialog, gint button, gpointer data) -{ - GnomePrintMaster *master; - GnomePrintContext *pc; - EPrintable *printable = gtk_object_get_data(GTK_OBJECT(dialog), "printable"); - GtkWidget *preview; - switch( button ) { - case GNOME_PRINT_PRINT: - master = gnome_print_master_new_from_dialog( GNOME_PRINT_DIALOG(dialog) ); - pc = gnome_print_master_get_context( master ); - e_printable_reset(printable); - while (e_printable_data_left(printable)) { - if (gnome_print_gsave(pc) == -1) - /* FIXME */; - if (gnome_print_translate(pc, 72, 72) == -1) - /* FIXME */; - e_printable_print_page(printable, - pc, - 6.5 * 72, - 5 * 72, - TRUE); - if (gnome_print_grestore(pc) == -1) - /* FIXME */; - if (gnome_print_showpage(pc) == -1) - /* FIXME */; - } - gnome_print_master_close(master); - gnome_print_master_print(master); - gtk_object_unref(GTK_OBJECT(master)); - gnome_dialog_close(dialog); - break; - case GNOME_PRINT_PREVIEW: - master = gnome_print_master_new_from_dialog( GNOME_PRINT_DIALOG(dialog) ); - pc = gnome_print_master_get_context( master ); - e_printable_reset(printable); - while (e_printable_data_left(printable)) { - if (gnome_print_gsave(pc) == -1) - /* FIXME */; - if (gnome_print_translate(pc, 72, 72) == -1) - /* FIXME */; - e_printable_print_page(printable, - pc, - 6.5 * 72, - 9 * 72, - TRUE); - if (gnome_print_grestore(pc) == -1) - /* FIXME */; - if (gnome_print_showpage(pc) == -1) - /* FIXME */; - } - gnome_print_master_close(master); - preview = GTK_WIDGET(gnome_print_master_preview_new(master, "Print Preview")); - gtk_widget_show_all(preview); - gtk_object_unref(GTK_OBJECT(master)); - break; - case GNOME_PRINT_CANCEL: - gnome_dialog_close(dialog); - break; - } + g_object_unref (operation); } void -e_addressbook_view_setup_menus (EAddressbookView *view, - BonoboUIComponent *uic) +e_addressbook_view_print (EAddressbookView *view, + gboolean selection_only, + GtkPrintOperationAction action) { + GalView *gal_view; + GalViewInstance *view_instance; - g_return_if_fail (view != NULL); g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - g_return_if_fail (uic != NULL); - g_return_if_fail (BONOBO_IS_UI_COMPONENT (uic)); - init_collection (); + view_instance = e_addressbook_view_get_view_instance (view); + gal_view = gal_view_instance_get_current_view (view_instance); - view->uic = uic; + /* Print the selected contacts. */ + if (GAL_IS_VIEW_MINICARD (gal_view) && selection_only) { + GSList *contact_list; - setup_menus (view); -} + contact_list = e_addressbook_view_get_selected (view); + e_contact_print (NULL, NULL, contact_list, action); + g_slist_free_full ( + contact_list, + (GDestroyNotify) g_object_unref); -/** - * e_addressbook_view_discard_menus: - * @view: An addressbook view. - * - * Makes an addressbook view discard its GAL view menus and its views instance - * objects. This should be called when the corresponding Bonobo component is - * deactivated. - **/ -void -e_addressbook_view_discard_menus (EAddressbookView *view) -{ - g_return_if_fail (view != NULL); - g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - g_return_if_fail (view->view_instance); + /* Print the latest query results. */ + } else if (GAL_IS_VIEW_MINICARD (gal_view)) { + EAddressbookModel *model; + EBookClient *book_client; + EBookQuery *query; + const gchar *query_string; - if (view->view_menus) { - gal_view_menus_unmerge (view->view_menus, NULL); + model = e_addressbook_view_get_model (view); + book_client = e_addressbook_model_get_client (model); + query_string = e_addressbook_model_get_query (model); - gtk_object_unref (GTK_OBJECT (view->view_menus)); - view->view_menus = NULL; - } + if (query_string != NULL) + query = e_book_query_from_string (query_string); + else + query = NULL; - if (view->view_instance) { - gtk_object_unref (GTK_OBJECT (view->view_instance)); - view->view_instance = NULL; - } + e_contact_print (book_client, query, NULL, action); - view->uic = NULL; -} + if (query != NULL) + e_book_query_unref (query); -void -e_addressbook_view_print(EAddressbookView *view) -{ - if (view->view_type == E_ADDRESSBOOK_VIEW_MINICARD) { - char *query; - EBook *book; - GtkWidget *print; - - gtk_object_get (GTK_OBJECT(view->model), - "query", &query, - "book", &book, - NULL); - print = e_contact_print_dialog_new(book, query); - g_free(query); - gtk_widget_show_all(print); - } else if (view->view_type == E_ADDRESSBOOK_VIEW_TABLE) { - GtkWidget *dialog; + /* XXX Does this print the entire table or just selected? */ + } else if (GAL_IS_VIEW_ETABLE (gal_view)) { EPrintable *printable; - ETable *etable; - - dialog = gnome_print_dialog_new("Print cards", GNOME_PRINT_DIALOG_RANGE | GNOME_PRINT_DIALOG_COPIES); - gnome_print_dialog_construct_range_any(GNOME_PRINT_DIALOG(dialog), GNOME_PRINT_RANGE_ALL | GNOME_PRINT_RANGE_SELECTION, - NULL, NULL, NULL); + GtkWidget *widget; - gtk_object_get(GTK_OBJECT(view->widget), "table", &etable, NULL); - printable = e_table_get_printable(etable); + widget = gtk_bin_get_child (GTK_BIN (view)); + printable = e_table_get_printable (E_TABLE (widget)); + g_object_ref_sink (printable); - gtk_object_ref(GTK_OBJECT(view->widget)); - - gtk_object_set_data(GTK_OBJECT(dialog), "table", view->widget); - gtk_object_set_data(GTK_OBJECT(dialog), "printable", printable); - - gtk_signal_connect(GTK_OBJECT(dialog), - "clicked", GTK_SIGNAL_FUNC(e_contact_print_button), NULL); - gtk_signal_connect(GTK_OBJECT(dialog), - "destroy", GTK_SIGNAL_FUNC(e_contact_print_destroy), NULL); - gtk_widget_show(dialog); - } -} - -void -e_addressbook_view_print_preview(EAddressbookView *view) -{ - if (view->view_type == E_ADDRESSBOOK_VIEW_MINICARD) { - char *query; - EBook *book; - - gtk_object_get (GTK_OBJECT(view->model), - "query", &query, - "book", &book, - NULL); - e_contact_print_preview(book, query); - g_free(query); - } else if (view->view_type == E_ADDRESSBOOK_VIEW_TABLE) { - EPrintable *printable; - ETable *etable; - GnomePrintMaster *master; - GnomePrintContext *pc; - GtkWidget *preview; - - gtk_object_get(GTK_OBJECT(view->widget), "table", &etable, NULL); - printable = e_table_get_printable(etable); - - master = gnome_print_master_new(); - gnome_print_master_set_copies (master, 1, FALSE); - pc = gnome_print_master_get_context( master ); - e_printable_reset(printable); - while (e_printable_data_left(printable)) { - if (gnome_print_gsave(pc) == -1) - /* FIXME */; - if (gnome_print_translate(pc, 72, 72) == -1) - /* FIXME */; - e_printable_print_page(printable, - pc, - 6.5 * 72, - 9 * 72, - TRUE); - if (gnome_print_grestore(pc) == -1) - /* FIXME */; - if (gnome_print_showpage(pc) == -1) - /* FIXME */; - } - gnome_print_master_close(master); - preview = GTK_WIDGET(gnome_print_master_preview_new(master, "Print Preview")); - gtk_widget_show_all(preview); - gtk_object_unref(GTK_OBJECT(master)); - gtk_object_unref(GTK_OBJECT(printable)); - } -} + e_contact_print_button (printable, action); -static void -card_deleted_cb (EBook* book, EBookStatus status, gpointer user_data) -{ - if (status != E_BOOK_STATUS_SUCCESS) { - e_addressbook_error_dialog (_("Error removing card"), status); + g_object_unref (printable); } } static void -do_remove (int i, gpointer user_data) +report_and_free_error_if_any (GError *error) { - EBook *book; - ECard *card; - EAddressbookView *view = user_data; - - gtk_object_get (GTK_OBJECT(view->model), - "book", &book, - NULL); + if (!error) + return; - card = e_addressbook_model_get_card (view->model, i); + if (g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED) || + g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_error_free (error); + return; + } - e_book_remove_card(book, card, card_deleted_cb, view); + if (g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_PERMISSION_DENIED)) { + e_alert_run_dialog_for_args ( + e_shell_get_active_window (NULL), + "addressbook:contact-delete-error-perm", NULL); + } else { + eab_error_dialog (NULL, NULL, _("Failed to delete contact"), error); + } - gtk_object_unref (GTK_OBJECT (card)); + g_error_free (error); } -void -e_addressbook_view_delete_selection(EAddressbookView *view) +/* callback function to handle removal of contacts for + * which a user doesnt have write permission + */ +static void +remove_contacts_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - ESelectionModel *model = get_selection_model (view); + EBookClient *book_client = E_BOOK_CLIENT (source_object); + GError *error = NULL; - g_return_if_fail (model); + e_book_client_remove_contacts_finish (book_client, result, &error); - e_selection_model_foreach (model, - do_remove, - view); -} - -static void -invisible_destroyed (GtkWidget *invisible, EAddressbookView *view) -{ - view->invisible = NULL; + report_and_free_error_if_any (error); } static void -selection_get (GtkWidget *invisible, - GtkSelectionData *selection_data, - guint info, - guint time_stamp, - EAddressbookView *view) +remove_contact_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - char *value; + EBookClient *book_client = E_BOOK_CLIENT (source_object); + GError *error = NULL; - value = e_card_list_get_vcard(view->clipboard_cards); + e_book_client_remove_contact_finish (book_client, result, &error); - gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING, - 8, value, strlen (value)); - + report_and_free_error_if_any (error); } -static void -selection_clear_event (GtkWidget *invisible, - GdkEventSelection *event, - EAddressbookView *view) -{ - if (view->clipboard_cards) { - g_list_foreach (view->clipboard_cards, (GFunc)gtk_object_unref, NULL); - g_list_free (view->clipboard_cards); - view->clipboard_cards = NULL; - } -} - -static void -selection_received (GtkWidget *invisible, - GtkSelectionData *selection_data, - guint time, - EAddressbookView *view) -{ - if (selection_data->length < 0 || selection_data->type != GDK_SELECTION_TYPE_STRING) { - return; +static gboolean +addressbook_view_confirm_delete (GtkWindow *parent, + gboolean plural, + gboolean is_list, + const gchar *name) +{ + GtkWidget *dialog; + gchar *message; + gint response; + + if (is_list) { + if (plural) { + message = g_strdup ( + _("Are you sure you want to " + "delete these contact lists?")); + } else if (name == NULL) { + message = g_strdup ( + _("Are you sure you want to " + "delete this contact list?")); + } else { + message = g_strdup_printf ( + _("Are you sure you want to delete " + "this contact list (%s)?"), name); + } + } else { + if (plural) { + message = g_strdup ( + _("Are you sure you want to " + "delete these contacts?")); + } else if (name == NULL) { + message = g_strdup ( + _("Are you sure you want to " + "delete this contact?")); + } else { + message = g_strdup_printf ( + _("Are you sure you want to delete " + "this contact (%s)?"), name); + } } - else { - /* XXX make sure selection_data->data = \0 terminated */ - GList *card_list = e_card_load_cards_from_string_with_default_charset (selection_data->data, "ISO-8859-1"); - GList *l; - - if (!card_list /* it wasn't a vcard list */) - return; - for (l = card_list; l; l = l->next) { - ECard *card = l->data; + dialog = gtk_message_dialog_new ( + parent, 0, GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, "%s", message); + gtk_dialog_add_buttons ( + GTK_DIALOG (dialog), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT, + NULL); + response = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); - e_card_merging_book_add_card (view->book, card, NULL /* XXX */, NULL); - } + g_free (message); - g_list_foreach (card_list, (GFunc)gtk_object_unref, NULL); - g_list_free (card_list); - } + return (response == GTK_RESPONSE_ACCEPT); } -static void -add_to_list (int model_row, gpointer closure) -{ - GList **list = closure; - *list = g_list_prepend (*list, GINT_TO_POINTER (model_row)); -} +void +e_addressbook_view_delete_selection (EAddressbookView *view, + gboolean is_delete) +{ + GSList *list, *l; + gboolean plural = FALSE, is_list = FALSE; + EContact *contact; + ETable *etable = NULL; + EAddressbookModel *model; + EBookClient *book_client; + ESelectionModel *selection_model = NULL; + GalViewInstance *view_instance; + GalView *gal_view; + GtkWidget *widget; + gchar *name = NULL; + gint row = 0, select; + + model = e_addressbook_view_get_model (view); + book_client = e_addressbook_model_get_client (model); + + view_instance = e_addressbook_view_get_view_instance (view); + gal_view = gal_view_instance_get_current_view (view_instance); + + list = e_addressbook_view_get_selected (view); + contact = list->data; + + if (g_slist_next (list)) + plural = TRUE; + else + name = e_contact_get (contact, E_CONTACT_FILE_AS); -static GList * -get_selected_cards (EAddressbookView *view) -{ - GList *list; - GList *iterator; - ESelectionModel *selection = get_selection_model (view); + if (e_contact_get (contact, E_CONTACT_IS_LIST)) + is_list = TRUE; - list = NULL; - e_selection_model_foreach (selection, add_to_list, &list); + widget = gtk_bin_get_child (GTK_BIN (view)); - for (iterator = list; iterator; iterator = iterator->next) { - iterator->data = e_addressbook_model_card_at (view->model, GPOINTER_TO_INT (iterator->data)); - if (iterator->data) - gtk_object_ref (iterator->data); + if (GAL_IS_VIEW_MINICARD (gal_view)) { + selection_model = e_addressbook_view_get_selection_model (view); + row = e_selection_model_cursor_row (selection_model); } - list = g_list_reverse (list); - return list; -} -#if 0 -void -e_addressbook_view_save_state (EAddressbookView *view, const char *filename) -{ - xmlDoc *doc; - xmlNode *node; - - doc = xmlNewDoc ("1.0"); - node = xmlNewDocNode (doc, NULL, "addressbook-view", NULL); - xmlDocSetRootElement (doc, node); - - switch (view->view_type) { - case E_ADDRESSBOOK_VIEW_MINICARD: { - int column_width; - e_xml_set_string_prop_by_name (node, "style", "minicard"); - gtk_object_get (GTK_OBJECT (view->object), - "column_width", &column_width, - NULL); - e_xml_set_integer_prop_by_name (node, "column-width", column_width); - break; - } - case E_ADDRESSBOOK_VIEW_TABLE: { - ETableState *state; - state = e_table_get_state_object (E_TABLE (view->widget)); - - e_xml_set_string_prop_by_name (node, "style", "table"); - e_table_state_save_to_node (state, node); - gtk_object_unref (GTK_OBJECT (state)); - break; + else if (GAL_IS_VIEW_ETABLE (gal_view)) { + etable = E_TABLE (widget); + row = e_table_get_cursor_row (E_TABLE (etable)); } - default: - xmlFreeDoc(doc); + + /* confirm delete */ + if (is_delete && !addressbook_view_confirm_delete ( + GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))), + plural, is_list, name)) { + g_free (name); + g_slist_free_full (list, (GDestroyNotify) g_object_unref); return; } - xmlSaveFile (filename, doc); - xmlFreeDoc(doc); -} -void -e_addressbook_view_load_state (EAddressbookView *view, const char *filename) -{ - xmlDoc *doc; + if (e_client_check_capability (E_CLIENT (book_client), "bulk-remove")) { + GSList *ids = NULL; - doc = xmlParseFile (filename); - if (doc) { - xmlNode *node; - char *type; + for (l = list; l; l = g_slist_next (l)) { + const gchar *uid; - node = xmlDocGetRootElement (doc); - type = e_xml_get_string_prop_by_name (node, "style"); + contact = l->data; - if (!strcmp (type, "minicard")) { - int column_width; - - change_view_type (view, E_ADDRESSBOOK_VIEW_MINICARD); + uid = e_contact_get_const (contact, E_CONTACT_UID); + ids = g_slist_prepend (ids, (gpointer) uid); + } - column_width = e_xml_get_integer_prop_by_name (node, "column-width"); - gtk_object_set (GTK_OBJECT (view->object), - "column_width", column_width, - NULL); - } else if (!strcmp (type, "table")) { - ETableState *state; + /* Remove the cards all at once. */ + e_book_client_remove_contacts ( + book_client, ids, NULL, remove_contacts_cb, NULL); - change_view_type (view, E_ADDRESSBOOK_VIEW_TABLE); + g_slist_free (ids); + } else { + for (l = list; l; l = g_slist_next (l)) { + contact = l->data; - state = e_table_state_new(); - e_table_state_load_from_node (state, node->xmlChildrenNode); - e_table_set_state_object (E_TABLE (view->widget), state); - gtk_object_unref (GTK_OBJECT (state)); + /* Remove the card. */ + e_book_client_remove_contact ( + book_client, contact, NULL, + remove_contact_cb, NULL); } - xmlFreeDoc(doc); } -} -#endif -void -e_addressbook_view_save_as (EAddressbookView *view) -{ - GList *list = get_selected_cards (view); - if (list) - e_contact_list_save_as (_("Save as VCard"), list, NULL); - e_free_object_list(list); -} + /* Sets the cursor, at the row after the deleted row */ + if (GAL_IS_VIEW_MINICARD (gal_view) && row != 0 && selection_model) { + select = e_sorter_model_to_sorted (selection_model->sorter, row); -void -e_addressbook_view_view (EAddressbookView *view) -{ - GList *list = get_selected_cards (view); - e_addressbook_show_multiple_cards (view->book, list, view->editable); - e_free_object_list(list); -} + /* Sets the cursor, before the deleted row if its the last row */ + if (select == e_selection_model_row_count (selection_model) - 1) + select = select - 1; + else + select = select + 1; -void -e_addressbook_view_send (EAddressbookView *view) -{ - GList *list = get_selected_cards (view); - if (list) - e_card_list_send (list, E_CARD_DISPOSITION_AS_ATTACHMENT); - e_free_object_list(list); -} + row = e_sorter_sorted_to_model (selection_model->sorter, select); + e_selection_model_cursor_changed (selection_model, row, 0); + } -void -e_addressbook_view_send_to (EAddressbookView *view) -{ - GList *list = get_selected_cards (view); - if (list) - e_card_list_send (list, E_CARD_DISPOSITION_AS_TO); - e_free_object_list(list); -} + /* Sets the cursor, at the row after the deleted row */ + else if (GAL_IS_VIEW_ETABLE (gal_view) && row != 0) { + select = e_table_model_to_view_row (E_TABLE (etable), row); -void -e_addressbook_view_cut (EAddressbookView *view) -{ - e_addressbook_view_copy (view); - e_addressbook_view_delete_selection (view); + /* Sets the cursor, before the deleted row if its the last row */ + if (select == e_table_model_row_count (E_TABLE (etable)->model) - 1) + select = select - 1; + else + select = select + 1; + + row = e_table_view_to_model_row (E_TABLE (etable), select); + e_table_set_cursor_row (E_TABLE (etable), row); + } + g_slist_free_full (list, (GDestroyNotify) g_object_unref); } void -e_addressbook_view_copy (EAddressbookView *view) +e_addressbook_view_view (EAddressbookView *view) { - view->clipboard_cards = get_selected_cards (view); + GSList *list, *iter; + gint response; + guint length; - gtk_selection_owner_set (view->invisible, clipboard_atom, GDK_CURRENT_TIME); -} + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); -void -e_addressbook_view_paste (EAddressbookView *view) -{ - gtk_selection_convert (view->invisible, clipboard_atom, - GDK_SELECTION_TYPE_STRING, - GDK_CURRENT_TIME); -} + list = e_addressbook_view_get_selected (view); + length = g_slist_length (list); + response = GTK_RESPONSE_YES; -void -e_addressbook_view_select_all (EAddressbookView *view) -{ - ESelectionModel *model = get_selection_model (view); + if (length > 5) { + GtkWidget *dialog; + + /* XXX Use e_alert_new(). */ + /* XXX Provide a parent window. */ + dialog = gtk_message_dialog_new ( + NULL, 0, + GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, ngettext ( + /* Translators: This is shown for > 5 contacts. */ + "Opening %d contacts will open %d new windows " + "as well.\nDo you really want to display all of " + "these contacts?", + "Opening %d contacts will open %d new windows " + "as well.\nDo you really want to display all of " + "these contacts?", length), length, length); + gtk_dialog_add_buttons ( + GTK_DIALOG (dialog), + _("_Don't Display"), GTK_RESPONSE_NO, + _("Display _All Contacts"), GTK_RESPONSE_YES, + NULL); + response = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + } - g_return_if_fail (model); + if (response == GTK_RESPONSE_YES) + for (iter = list; iter != NULL; iter = iter->next) + addressbook_view_emit_open_contact ( + view, iter->data, FALSE); - e_selection_model_select_all (model); + g_slist_free_full (list, (GDestroyNotify) g_object_unref); } void -e_addressbook_view_show_all(EAddressbookView *view) +e_addressbook_view_show_all (EAddressbookView *view) { - gtk_object_set(GTK_OBJECT(view), - "query", NULL, - NULL); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); + + e_addressbook_model_set_query (view->priv->model, ""); } void -e_addressbook_view_stop(EAddressbookView *view) +e_addressbook_view_stop (EAddressbookView *view) { - if (view) - e_addressbook_model_stop (view->model); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); + + e_addressbook_model_stop (view->priv->model); } -static void -view_transfer_cards (EAddressbookView *view, gboolean delete_from_source) +struct TransferContactsData { - EBook *book; - GList *cards; - GtkWindow *parent_window; - - gtk_object_get(GTK_OBJECT(view->model), - "book", &book, - NULL); - cards = get_selected_cards (view); - parent_window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))); + gboolean delete_from_source; + EAddressbookView *view; +}; - e_addressbook_transfer_cards (book, cards, delete_from_source, parent_window); -} +static void +all_contacts_ready_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + EBookClient *book_client = E_BOOK_CLIENT (source_object); + struct TransferContactsData *tcd = user_data; + EAddressbookModel *model; + EClientCache *client_cache; + EShellView *shell_view; + EShellContent *shell_content; + EAlertSink *alert_sink; + GSList *contacts = NULL; + GError *error = NULL; + + g_return_if_fail (book_client != NULL); + g_return_if_fail (tcd != NULL); + + if (!e_book_client_get_contacts_finish (book_client, result, &contacts, &error)) + contacts = NULL; + + shell_view = e_addressbook_view_get_shell_view (tcd->view); + shell_content = e_shell_view_get_shell_content (shell_view); + alert_sink = E_ALERT_SINK (shell_content); + + model = e_addressbook_view_get_model (tcd->view); + client_cache = e_addressbook_model_get_client_cache (model); + + if (error) { + e_alert_submit ( + alert_sink, "addressbook:search-error", + error->message, NULL); + g_error_free (error); + } else if (contacts) { + ESourceRegistry *registry; + + registry = e_client_cache_ref_registry (client_cache); + + eab_transfer_contacts ( + registry, book_client, contacts, + tcd->delete_from_source, alert_sink); + + g_object_unref (registry); + } -void -e_addressbook_view_copy_to_folder (EAddressbookView *view) -{ - view_transfer_cards (view, FALSE); + g_object_unref (tcd->view); + g_free (tcd); } -void -e_addressbook_view_move_to_folder (EAddressbookView *view) -{ - view_transfer_cards (view, TRUE); -} +static void +view_transfer_contacts (EAddressbookView *view, + gboolean delete_from_source, + gboolean all) +{ + EAddressbookModel *model; + EBookClient *book_client; + EClientCache *client_cache; + + model = e_addressbook_view_get_model (view); + book_client = e_addressbook_model_get_client (model); + client_cache = e_addressbook_model_get_client_cache (model); + + if (all) { + EBookQuery *query; + gchar *query_str; + struct TransferContactsData *tcd; + + query = e_book_query_any_field_contains (""); + query_str = e_book_query_to_string (query); + e_book_query_unref (query); + + tcd = g_new0 (struct TransferContactsData, 1); + tcd->delete_from_source = delete_from_source; + tcd->view = g_object_ref (view); + + e_book_client_get_contacts ( + book_client, query_str, NULL, + all_contacts_ready_cb, tcd); + } else { + GSList *contacts = NULL; + EShellView *shell_view; + EShellContent *shell_content; + EAlertSink *alert_sink; + ESourceRegistry *registry; + shell_view = e_addressbook_view_get_shell_view (view); + shell_content = e_shell_view_get_shell_content (shell_view); + alert_sink = E_ALERT_SINK (shell_content); -static gboolean -e_addressbook_view_selection_nonempty (EAddressbookView *view) -{ - ESelectionModel *selection_model; + contacts = e_addressbook_view_get_selected (view); - selection_model = get_selection_model (view); - if (selection_model == NULL) - return FALSE; + registry = e_client_cache_ref_registry (client_cache); - return e_selection_model_selected_count (selection_model) != 0; -} + eab_transfer_contacts ( + registry, book_client, contacts, + delete_from_source, alert_sink); -gboolean -e_addressbook_view_can_create (EAddressbookView *view) -{ - return view ? e_addressbook_model_editable (view->model) : FALSE; + g_object_unref (registry); + } } -gboolean -e_addressbook_view_can_print (EAddressbookView *view) +void +e_addressbook_view_copy_to_folder (EAddressbookView *view, + gboolean all) { - return view && view->model ? e_addressbook_model_card_count (view->model) : FALSE; + view_transfer_contacts (view, FALSE, all); } -gboolean -e_addressbook_view_can_save_as (EAddressbookView *view) +void +e_addressbook_view_move_to_folder (EAddressbookView *view, + gboolean all) { - return view ? e_addressbook_view_selection_nonempty (view) : FALSE; + view_transfer_contacts (view, TRUE, all); } -gboolean -e_addressbook_view_can_view (EAddressbookView *view) +void +e_addressbook_view_set_search (EAddressbookView *view, + gint filter_id, + gint search_id, + const gchar *search_text, + EFilterRule *advanced_search) { - return view ? e_addressbook_view_selection_nonempty (view) : FALSE; -} + EAddressbookViewPrivate *priv; -gboolean -e_addressbook_view_can_send (EAddressbookView *view) -{ - return view ? e_addressbook_view_selection_nonempty (view) : FALSE; -} + g_return_if_fail (view != NULL); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); -gboolean -e_addressbook_view_can_send_to (EAddressbookView *view) -{ - return view ? e_addressbook_view_selection_nonempty (view) : FALSE; -} + priv = view->priv; -gboolean -e_addressbook_view_can_delete (EAddressbookView *view) -{ - return view ? e_addressbook_view_selection_nonempty (view) && e_addressbook_model_editable (view->model) : FALSE; -} + if (priv->search_text) + g_free (priv->search_text); + if (priv->advanced_search) + g_object_unref (priv->advanced_search); -gboolean -e_addressbook_view_can_cut (EAddressbookView *view) -{ - return view ? e_addressbook_view_selection_nonempty (view) && e_addressbook_model_editable (view->model) : FALSE; -} + priv->filter_id = filter_id; + priv->search_id = search_id; + priv->search_text = g_strdup (search_text); -gboolean -e_addressbook_view_can_copy (EAddressbookView *view) -{ - return view ? e_addressbook_view_selection_nonempty (view) : FALSE; + if (advanced_search != NULL) + priv->advanced_search = e_filter_rule_clone (advanced_search); + else + priv->advanced_search = NULL; } -gboolean -e_addressbook_view_can_paste (EAddressbookView *view) +/* Free returned values for search_text and advanced_search, + * if not NULL, as these are new copies. */ +void +e_addressbook_view_get_search (EAddressbookView *view, + gint *filter_id, + gint *search_id, + gchar **search_text, + EFilterRule **advanced_search) { - return view ? e_addressbook_model_editable (view->model) : FALSE; -} + EAddressbookViewPrivate *priv; -gboolean -e_addressbook_view_can_select_all (EAddressbookView *view) -{ - return view ? e_addressbook_model_card_count (view->model) != 0 : FALSE; -} + g_return_if_fail (view != NULL); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); + g_return_if_fail (filter_id != NULL); + g_return_if_fail (search_id != NULL); + g_return_if_fail (search_text != NULL); + g_return_if_fail (advanced_search != NULL); -gboolean -e_addressbook_view_can_stop (EAddressbookView *view) -{ - return view ? e_addressbook_model_can_stop (view->model) : FALSE; -} + priv = view->priv; -gboolean -e_addressbook_view_can_copy_to_folder (EAddressbookView *view) -{ - return view ? e_addressbook_view_selection_nonempty (view) : FALSE; -} + *filter_id = priv->filter_id; + *search_id = priv->search_id; + *search_text = g_strdup (priv->search_text); -gboolean -e_addressbook_view_can_move_to_folder (EAddressbookView *view) -{ - return view ? e_addressbook_view_selection_nonempty (view) && e_addressbook_model_editable (view->model) : FALSE; + if (priv->advanced_search != NULL) + *advanced_search = e_filter_rule_clone (priv->advanced_search); + else + *advanced_search = NULL; } diff --git a/addressbook/gui/widgets/e-addressbook-view.etspec b/addressbook/gui/widgets/e-addressbook-view.etspec index a0a0015d75..45eaea1df3 100644 --- a/addressbook/gui/widgets/e-addressbook-view.etspec +++ b/addressbook/gui/widgets/e-addressbook-view.etspec @@ -1,51 +1,65 @@ -<ETableSpecification click-to-add="true" draw-grid="true" _click-to-add-message="* Click here to add a contact *"> - <ETableColumn model_col= "0" _title="File As" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col= "1" _title="Full Name" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col= "2" _title="Email" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col= "3" _title="Primary Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col= "4" _title="Assistant Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col= "5" _title="Business Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col= "6" _title="Callback Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col= "7" _title="Company Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col= "8" _title="Home Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col= "9" _title="Organization" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="10" _title="Business Address" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="11" _title="Home Address" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="12" _title="Mobile Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="13" _title="Car Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="14" _title="Business Fax" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="15" _title="Home Fax" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="16" _title="Business Phone 2" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="17" _title="Home Phone 2" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="18" _title="ISDN" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="19" _title="Other Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="20" _title="Other Fax" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="21" _title="Pager" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="22" _title="Radio" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="23" _title="Telex" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="24" _title="TTY" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="25" _title="Other Address" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="26" _title="Email 2" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="27" _title="Email 3" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="28" _title="Web Site" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="29" _title="Department" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="30" _title="Office" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="31" _title="Title" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="32" _title="Profession" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="33" _title="Manager" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="34" _title="Assistant" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="35" _title="Nickname" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="36" _title="Spouse" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="37" _title="Note" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> - <ETableColumn model_col="38" _title="Free-busy URL" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="string"/> +<ETableSpecification draw-grid="true" cursor-mode="line"> + <ETableColumn model_col= "2" _title="File As" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col= "4" _title="Full Name" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col= "5" _title="Given Name" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col= "6" _title="Family Name" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col= "7" _title="Nickname" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + + <ETableColumn model_col= "8" _title="Email" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col= "9" _title="Email 2" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col= "10" _title="Email 3" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + + <ETableColumn model_col= "16" _title="Assistant Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col= "17" _title="Business Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col= "18" _title="Business Phone 2" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="19" _title="Business Fax" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="20" _title="Callback Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="21" _title="Car Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="22" _title="Company Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="23" _title="Home Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="24" _title="Home Phone 2" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="25" _title="Home Fax" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="26" _title="ISDN Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="27" _title="Mobile Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="28" _title="Other Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="29" _title="Other Fax" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="30" _title="Pager" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="31" _title="Primary Phone" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="32" _title="Radio" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="33" _title="Telex" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + +<!-- Translators: This is a vcard standard and stands for the type of + phone used by the hearing impaired. TTY stands for "teletype" + (familiar from Unix device names), and TDD is "Telecommunications + Device for Deaf". However, you probably want to leave this + abbreviation unchanged unless you know that there is actually a + different and established translation for this in your language. --> + <ETableColumn model_col="34" _title="TTYTDD" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + + <ETableColumn model_col="35" _title="Company" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="stringcase"/> + <ETableColumn model_col="36" _title="Unit" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="37" _title="Office" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="38" _title="Title" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="39" _title="Role" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="40" _title="Manager" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="41" _title="Assistant" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + + <ETableColumn model_col="42" _title="Web Site" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="43" _title="Journal" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + + <ETableColumn model_col="44" _title="Categories" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + + <ETableColumn model_col="49" _title="Spouse" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableColumn model_col="50" _title="Note" expansion="1.0" minimum_width="75" resizable="true" cell="string" compare="collate"/> + <ETableState> <column source="0"/> <column source="1"/> <column source="5"/> - <column source="2"/> - <column source="3"/> + <column source="23"/> + <column source="36"/> <grouping> - <leaf column="0" ascending="true"/> + <leaf column="2" ascending="true"/> </grouping> </ETableState> </ETableSpecification> diff --git a/addressbook/gui/widgets/e-addressbook-view.h b/addressbook/gui/widgets/e-addressbook-view.h index 897c37d420..94668d6ace 100644 --- a/addressbook/gui/widgets/e-addressbook-view.h +++ b/addressbook/gui/widgets/e-addressbook-view.h @@ -1,147 +1,129 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* e-addressbook-view.h - * Copyright (C) 2000 Ximian, Inc. - * Author: Chris Lahey <clahey@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. * * 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. + * Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#ifndef __E_ADDRESSBOOK_VIEW_H__ -#define __E_ADDRESSBOOK_VIEW_H__ - -#include <gtk/gtktable.h> -#include <bonobo/bonobo-ui-component.h> -#include <gal/menus/gal-view-instance.h> -#include "e-addressbook-model.h" -#include "widgets/menus/gal-view-menus.h" -#include "addressbook/backend/ebook/e-book.h" -#include <gal/unicode/gunicode.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -/* EAddressbookView - A card displaying information about a contact. + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Chris Lahey <clahey@ximian.com> * - * The following arguments are available: + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * - * name type read/write description - * -------------------------------------------------------------------------------- */ -#define E_ADDRESSBOOK_VIEW_TYPE (e_addressbook_view_get_type ()) -#define E_ADDRESSBOOK_VIEW(obj) (GTK_CHECK_CAST ((obj), E_ADDRESSBOOK_VIEW_TYPE, EAddressbookView)) -#define E_ADDRESSBOOK_VIEW_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_ADDRESSBOOK_VIEW_TYPE, EAddressbookViewClass)) -#define E_IS_ADDRESSBOOK_VIEW(obj) (GTK_CHECK_TYPE ((obj), E_ADDRESSBOOK_VIEW_TYPE)) -#define E_IS_ADDRESSBOOK_VIEW_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_ADDRESSBOOK_VIEW_TYPE)) +#ifndef E_ADDRESSBOOK_VIEW_H +#define E_ADDRESSBOOK_VIEW_H -typedef enum { - E_ADDRESSBOOK_VIEW_NONE, /* initialized to this */ - E_ADDRESSBOOK_VIEW_TABLE, - E_ADDRESSBOOK_VIEW_MINICARD -} EAddressbookViewType; +#include <libebook/libebook.h> +#include <shell/e-shell-view.h> -typedef struct _EAddressbookView EAddressbookView; -typedef struct _EAddressbookViewClass EAddressbookViewClass; - -struct _EAddressbookView -{ - GtkTable parent; - - /* item specific fields */ - EAddressbookViewType view_type; - - EAddressbookModel *model; - - GtkWidget *invisible; - GList *clipboard_cards; - - EBook *book; - char *query; - guint editable : 1; - - GtkObject *object; - GtkWidget *widget; - GtkWidget *current_alphabet_widget; - - GtkWidget *vbox; - - /* Menus handler and the view instance */ - GalViewInstance *view_instance; - GalViewMenus *view_menus; - GalView *current_view; - BonoboUIComponent *uic; +#include "e-addressbook-model.h" +#include "eab-contact-display.h" + +/* Standard GObject macros */ +#define E_TYPE_ADDRESSBOOK_VIEW \ + (e_addressbook_view_get_type ()) +#define E_ADDRESSBOOK_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_ADDRESSBOOK_VIEW, EAddressbookView)) +#define E_ADDRESSBOOK_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_ADDRESSBOOK_VIEW, EAddressbookViewClass)) +#define E_IS_ADDRESSBOOK_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_ADDRESSBOOK_VIEW)) +#define E_IS_ADDRESSBOOK_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((obj), E_TYPE_ADDRESSBOOK_VIEW)) +#define E_ADDRESSBOOK_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_ADDRESSBOOK_VIEW, EAddressbookViewClass)) + +G_BEGIN_DECLS + +typedef struct _EAddressbookView EAddressbookView; +typedef struct _EAddressbookViewClass EAddressbookViewClass; +typedef struct _EAddressbookViewPrivate EAddressbookViewPrivate; + +struct _EAddressbookView { + GtkScrolledWindow parent; + EAddressbookViewPrivate *priv; }; -struct _EAddressbookViewClass -{ - GtkTableClass parent_class; - - /* - * Signals - */ - void (*status_message) (EAddressbookView *view, const gchar *message); - void (*search_result) (EAddressbookView *view, EBookViewStatus status); - void (*folder_bar_message) (EAddressbookView *view, const gchar *message); - void (*command_state_change) (EAddressbookView *view); - void (*alphabet_state_change) (EAddressbookView *view, gunichar letter); +struct _EAddressbookViewClass { + GtkScrolledWindowClass parent_class; + + /* Signals */ + void (*open_contact) (EAddressbookView *view, + EContact *contact, + gboolean is_new_contact); + void (*popup_event) (EAddressbookView *view, + GdkEvent *event); + void (*command_state_change) (EAddressbookView *view); + void (*selection_change) (EAddressbookView *view); }; -GtkWidget *e_addressbook_view_new (void); -GtkType e_addressbook_view_get_type (void); - -void e_addressbook_view_setup_menus (EAddressbookView *view, - BonoboUIComponent *uic); - -void e_addressbook_view_discard_menus (EAddressbookView *view); - -void e_addressbook_view_save_as (EAddressbookView *view); -void e_addressbook_view_view (EAddressbookView *view); -void e_addressbook_view_send (EAddressbookView *view); -void e_addressbook_view_send_to (EAddressbookView *view); -void e_addressbook_view_print (EAddressbookView *view); -void e_addressbook_view_print_preview (EAddressbookView *view); -void e_addressbook_view_delete_selection (EAddressbookView *view); -void e_addressbook_view_cut (EAddressbookView *view); -void e_addressbook_view_copy (EAddressbookView *view); -void e_addressbook_view_paste (EAddressbookView *view); -void e_addressbook_view_select_all (EAddressbookView *view); -void e_addressbook_view_show_all (EAddressbookView *view); -void e_addressbook_view_stop (EAddressbookView *view); -void e_addressbook_view_copy_to_folder (EAddressbookView *view); -void e_addressbook_view_move_to_folder (EAddressbookView *view); - -gboolean e_addressbook_view_can_create (EAddressbookView *view); -gboolean e_addressbook_view_can_print (EAddressbookView *view); -gboolean e_addressbook_view_can_save_as (EAddressbookView *view); -gboolean e_addressbook_view_can_view (EAddressbookView *view); -gboolean e_addressbook_view_can_send (EAddressbookView *view); -gboolean e_addressbook_view_can_send_to (EAddressbookView *view); -gboolean e_addressbook_view_can_delete (EAddressbookView *view); -gboolean e_addressbook_view_can_cut (EAddressbookView *view); -gboolean e_addressbook_view_can_copy (EAddressbookView *view); -gboolean e_addressbook_view_can_paste (EAddressbookView *view); -gboolean e_addressbook_view_can_select_all (EAddressbookView *view); -gboolean e_addressbook_view_can_stop (EAddressbookView *view); -gboolean e_addressbook_view_can_copy_to_folder (EAddressbookView *view); -gboolean e_addressbook_view_can_move_to_folder (EAddressbookView *view); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -#endif /* __E_ADDRESSBOOK_VIEW_H__ */ +GType e_addressbook_view_get_type (void); +GtkWidget * e_addressbook_view_new (EShellView *shell_view, + ESource *source); +EAddressbookModel * + e_addressbook_view_get_model (EAddressbookView *view); +GalViewInstance * + e_addressbook_view_get_view_instance + (EAddressbookView *view); +GObject * e_addressbook_view_get_view_object + (EAddressbookView *view); +GSList * e_addressbook_view_get_selected (EAddressbookView *view); +ESelectionModel * + e_addressbook_view_get_selection_model + (EAddressbookView *view); +EShellView * e_addressbook_view_get_shell_view + (EAddressbookView *view); +ESource * e_addressbook_view_get_source (EAddressbookView *view); +GtkTargetList * e_addressbook_view_get_copy_target_list + (EAddressbookView *view); +GtkTargetList * e_addressbook_view_get_paste_target_list + (EAddressbookView *view); +void e_addressbook_view_view (EAddressbookView *view); +void e_addressbook_view_print (EAddressbookView *view, + gboolean selection_only, + GtkPrintOperationAction action); +void e_addressbook_view_delete_selection + (EAddressbookView *view, + gboolean is_delete); +void e_addressbook_view_show_all (EAddressbookView *view); +void e_addressbook_view_stop (EAddressbookView *view); +void e_addressbook_view_copy_to_folder + (EAddressbookView *view, + gboolean all); +void e_addressbook_view_move_to_folder + (EAddressbookView *view, + gboolean all); + +gboolean e_addressbook_view_can_create (EAddressbookView *view); + +void e_addressbook_view_set_search (EAddressbookView *view, + gint filter_id, + gint search_id, + const gchar *search_text, + EFilterRule *advanced_search); + +void e_addressbook_view_get_search (EAddressbookView *view, + gint *filter_id, + gint *search_id, + gchar **search_text, + EFilterRule **advanced_search); + +G_END_DECLS + +#endif /* E_ADDRESSBOOK_VIEW_H */ diff --git a/addressbook/gui/widgets/e-contact-map-window.c b/addressbook/gui/widgets/e-contact-map-window.c new file mode 100644 index 0000000000..1dbe694d50 --- /dev/null +++ b/addressbook/gui/widgets/e-contact-map-window.c @@ -0,0 +1,500 @@ +/* + * e-contact-map-window.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * Copyright (C) 2011 Dan Vratil <dvratil@redhat.com> + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef WITH_CONTACT_MAPS + +#include "e-contact-map.h" +#include "e-contact-map-window.h" +#include "e-contact-marker.h" + +#include <champlain/champlain.h> + +#include <string.h> + +#include <glib/gi18n.h> +#include <glib-object.h> + +#define E_CONTACT_MAP_WINDOW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_CONTACT_MAP_WINDOW, EContactMapWindowPrivate)) + +G_DEFINE_TYPE (EContactMapWindow, e_contact_map_window, GTK_TYPE_WINDOW) + +struct _EContactMapWindowPrivate { + EContactMap *map; + + GtkWidget *zoom_in_btn; + GtkWidget *zoom_out_btn; + + GtkWidget *search_entry; + GtkListStore *completion_model; + + GHashTable *hash_table; /* Hash table contact-name -> marker */ + + GtkWidget *spinner; + gint tasks_cnt; +}; + +enum { + SHOW_CONTACT_EDITOR, + LAST_SIGNAL +}; + +static gint signals[LAST_SIGNAL] = {0}; + +static void +marker_doubleclick_cb (ClutterActor *actor, + gpointer user_data) +{ + EContactMapWindow *window = user_data; + EContactMarker *marker; + const gchar *contact_uid; + + marker = E_CONTACT_MARKER (actor); + contact_uid = e_contact_marker_get_contact_uid (marker); + + g_signal_emit (window, signals[SHOW_CONTACT_EDITOR], 0, contact_uid); +} + +static void +book_contacts_received_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + EContactMapWindow *window = user_data; + EBookClient *client = E_BOOK_CLIENT (source_object); + GSList *contacts = NULL, *p; + GError *error = NULL; + + if (!e_book_client_get_contacts_finish (client, result, &contacts, &error)) + contacts = NULL; + + if (error != NULL) { + g_warning ( + "%s: Failed to get contacts: %s", + G_STRFUNC, error->message); + g_error_free (error); + } + + for (p = contacts; p; p = p->next) + e_contact_map_add_contact ( + window->priv->map, (EContact *) p->data); + + g_slist_free_full (contacts, (GDestroyNotify) g_object_unref); + g_object_unref (client); +} + +static void +contact_map_window_zoom_in_cb (GtkButton *button, + gpointer user_data) +{ + EContactMapWindow *window = user_data; + ChamplainView *view; + + view = e_contact_map_get_view (window->priv->map); + + champlain_view_zoom_in (view); +} + +static void +contact_map_window_zoom_out_cb (GtkButton *button, + gpointer user_data) +{ + EContactMapWindow *window = user_data; + ChamplainView *view; + + view = e_contact_map_get_view (window->priv->map); + + champlain_view_zoom_out (view); +} +static void +zoom_level_changed_cb (ChamplainView *view, + GParamSpec *pspec, + gpointer user_data) +{ + EContactMapWindow *window = user_data; + gint zoom_level = champlain_view_get_zoom_level (view); + + gtk_widget_set_sensitive ( + window->priv->zoom_in_btn, + (zoom_level < champlain_view_get_max_zoom_level (view))); + + gtk_widget_set_sensitive ( + window->priv->zoom_out_btn, + (zoom_level > champlain_view_get_min_zoom_level (view))); +} + +/** + * Add contact to hash_table only when EContactMap tells us + * that the contact has really been added to map. + */ +static void +map_contact_added_cb (EContactMap *map, + ClutterActor *marker, + gpointer user_data) +{ + EContactMapWindowPrivate *priv = E_CONTACT_MAP_WINDOW (user_data)->priv; + const gchar *name; + GtkTreeIter iter; + + name = champlain_label_get_text (CHAMPLAIN_LABEL (marker)); + + g_hash_table_insert ( + priv->hash_table, + g_strdup (name), marker); + + gtk_list_store_append (priv->completion_model, &iter); + gtk_list_store_set ( + priv->completion_model, &iter, + 0, name, -1); + + g_signal_connect ( + marker, "double-clicked", + G_CALLBACK (marker_doubleclick_cb), user_data); + + priv->tasks_cnt--; + if (priv->tasks_cnt == 0) { + gtk_spinner_stop (GTK_SPINNER (priv->spinner)); + gtk_widget_hide (priv->spinner); + } +} + +static void +map_contact_removed_cb (EContactMap *map, + const gchar *name, + gpointer user_data) +{ + EContactMapWindowPrivate *priv = E_CONTACT_MAP_WINDOW (user_data)->priv; + GtkTreeIter iter; + GtkTreeModel *model = GTK_TREE_MODEL (priv->completion_model); + + g_hash_table_remove (priv->hash_table, name); + + if (gtk_tree_model_get_iter_first (model, &iter)) { + do { + gchar *name_str; + gtk_tree_model_get (model, &iter, 0, &name_str, -1); + if (g_ascii_strcasecmp (name_str, name) == 0) { + g_free (name_str); + gtk_list_store_remove (priv->completion_model, &iter); + break; + } + g_free (name_str); + } while (gtk_tree_model_iter_next (model, &iter)); + } +} + +static void +map_contact_geocoding_started_cb (EContactMap *map, + ClutterActor *marker, + gpointer user_data) +{ + EContactMapWindowPrivate *priv = E_CONTACT_MAP_WINDOW (user_data)->priv; + + gtk_spinner_start (GTK_SPINNER (priv->spinner)); + gtk_widget_show (priv->spinner); + + priv->tasks_cnt++; +} + +static void +map_contact_geocoding_failed_cb (EContactMap *map, + const gchar *name, + gpointer user_data) +{ + EContactMapWindowPrivate *priv = E_CONTACT_MAP_WINDOW (user_data)->priv; + + priv->tasks_cnt--; + + if (priv->tasks_cnt == 0) { + gtk_spinner_stop (GTK_SPINNER (priv->spinner)); + gtk_widget_hide (priv->spinner); + } +} + +static void +contact_map_window_find_contact_cb (GtkButton *button, + gpointer user_data) +{ + EContactMapWindowPrivate *priv = E_CONTACT_MAP_WINDOW (user_data)->priv; + ClutterActor *marker; + + marker = g_hash_table_lookup ( + priv->hash_table, + gtk_entry_get_text (GTK_ENTRY (priv->search_entry))); + + if (marker) + e_contact_map_zoom_on_marker (priv->map, marker); +} + +static gboolean +contact_map_window_entry_key_pressed_cb (GtkWidget *entry, + GdkEventKey *event, + gpointer user_data) +{ + if (event->keyval == GDK_KEY_Return) + contact_map_window_find_contact_cb (NULL, user_data); + + return FALSE; +} + +static gboolean +entry_completion_match_selected_cb (GtkEntryCompletion *widget, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer user_data) +{ + GValue name_val = {0}; + EContactMapWindowPrivate *priv = E_CONTACT_MAP_WINDOW (user_data)->priv; + const gchar *name; + + gtk_tree_model_get_value (model, iter, 0, &name_val); + g_return_val_if_fail (G_VALUE_HOLDS_STRING (&name_val), FALSE); + + name = g_value_get_string (&name_val); + gtk_entry_set_text (GTK_ENTRY (priv->search_entry), name); + + contact_map_window_find_contact_cb (NULL, user_data); + + return TRUE; +} + +static void +contact_map_window_finalize (GObject *object) +{ + EContactMapWindowPrivate *priv; + + priv = E_CONTACT_MAP_WINDOW (object)->priv; + + if (priv->hash_table) { + g_hash_table_destroy (priv->hash_table); + priv->hash_table = NULL; + } + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_contact_map_window_parent_class)->finalize (object); +} + +static void +contact_map_window_dispose (GObject *object) +{ + EContactMapWindowPrivate *priv; + + priv = E_CONTACT_MAP_WINDOW (object)->priv; + + if (priv->map) { + gtk_widget_destroy (GTK_WIDGET (priv->map)); + priv->map = NULL; + } + + if (priv->completion_model) { + g_object_unref (priv->completion_model); + priv->completion_model = NULL; + } + + G_OBJECT_CLASS (e_contact_map_window_parent_class)->dispose (object); +} + +static void +e_contact_map_window_class_init (EContactMapWindowClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (EContactMapWindowPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->finalize = contact_map_window_finalize; + object_class->dispose = contact_map_window_dispose; + + signals[SHOW_CONTACT_EDITOR] = g_signal_new ( + "show-contact-editor", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EContactMapWindowClass, show_contact_editor), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); +} + +static void +e_contact_map_window_init (EContactMapWindow *window) +{ + EContactMapWindowPrivate *priv; + GtkWidget *map; + GtkWidget *button, *entry; + GtkWidget *hbox, *vbox, *viewport; + GtkEntryCompletion *entry_completion; + GtkListStore *completion_model; + ChamplainView *view; + GHashTable *hash_table; + + priv = E_CONTACT_MAP_WINDOW_GET_PRIVATE (window); + window->priv = priv; + + priv->tasks_cnt = 0; + + hash_table = g_hash_table_new_full ( + (GHashFunc) g_str_hash, + (GEqualFunc) g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) NULL); + priv->hash_table = hash_table; + + gtk_window_set_title (GTK_WINDOW (window), _("Contacts Map")); + gtk_container_set_border_width (GTK_CONTAINER (window), 12); + gtk_widget_set_size_request (GTK_WIDGET (window), 800, 600); + + /* The map view itself */ + map = e_contact_map_new (); + view = e_contact_map_get_view (E_CONTACT_MAP (map)); + champlain_view_set_zoom_level (view, 2); + priv->map = E_CONTACT_MAP (map); + g_signal_connect ( + view, "notify::zoom-level", + G_CALLBACK (zoom_level_changed_cb), window); + g_signal_connect ( + map, "contact-added", + G_CALLBACK (map_contact_added_cb), window); + g_signal_connect ( + map, "contact-removed", + G_CALLBACK (map_contact_removed_cb), window); + g_signal_connect ( + map, "geocoding-started", + G_CALLBACK (map_contact_geocoding_started_cb), window); + g_signal_connect ( + map, "geocoding-failed", + G_CALLBACK (map_contact_geocoding_failed_cb), window); + + /* HBox container */ + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 7); + + /* Spinner */ + button = gtk_spinner_new (); + gtk_container_add (GTK_CONTAINER (hbox), button); + gtk_widget_hide (button); + priv->spinner = button; + + /* Zoom-in button */ + button = gtk_button_new_from_stock (GTK_STOCK_ZOOM_IN); + g_signal_connect ( + button, "clicked", + G_CALLBACK (contact_map_window_zoom_in_cb), window); + priv->zoom_in_btn = button; + gtk_container_add (GTK_CONTAINER (hbox), button); + + /* Zoom-out button */ + button = gtk_button_new_from_stock (GTK_STOCK_ZOOM_OUT); + g_signal_connect ( + button, "clicked", + G_CALLBACK (contact_map_window_zoom_out_cb), window); + priv->zoom_out_btn = button; + gtk_container_add (GTK_CONTAINER (hbox), button); + + /* Completion model */ + completion_model = gtk_list_store_new (1, G_TYPE_STRING); + priv->completion_model = completion_model; + + /* Entry completion */ + entry_completion = gtk_entry_completion_new (); + gtk_entry_completion_set_model ( + entry_completion, GTK_TREE_MODEL (completion_model)); + gtk_entry_completion_set_text_column (entry_completion, 0); + g_signal_connect ( + entry_completion, "match-selected", + G_CALLBACK (entry_completion_match_selected_cb), window); + + /* Search entry */ + entry = gtk_entry_new (); + gtk_entry_set_completion (GTK_ENTRY (entry), entry_completion); + g_signal_connect ( + entry, "key-press-event", + G_CALLBACK (contact_map_window_entry_key_pressed_cb), window); + window->priv->search_entry = entry; + gtk_container_add (GTK_CONTAINER (hbox), entry); + + /* Search button */ + button = gtk_button_new_from_stock (GTK_STOCK_FIND); + g_signal_connect ( + button, "clicked", + G_CALLBACK (contact_map_window_find_contact_cb), window); + gtk_container_add (GTK_CONTAINER (hbox), button); + + viewport = gtk_frame_new (NULL); + gtk_container_add (GTK_CONTAINER (viewport), map); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + gtk_container_add (GTK_CONTAINER (vbox), viewport); + gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + + gtk_container_add (GTK_CONTAINER (window), vbox); + + gtk_widget_show_all (vbox); + gtk_widget_hide (priv->spinner); +} + +EContactMapWindow * +e_contact_map_window_new (void) +{ + return g_object_new ( + E_TYPE_CONTACT_MAP_WINDOW, NULL); +} + +/** + * Gets all contacts from @book and puts them + * on the map view + */ +void +e_contact_map_window_load_addressbook (EContactMapWindow *map, + EBookClient *book_client) +{ + EBookQuery *book_query; + gchar *query_string; + + g_return_if_fail (E_IS_CONTACT_MAP_WINDOW (map)); + g_return_if_fail (E_IS_BOOK_CLIENT (book_client)); + + /* Reference book, so that it does not get deleted before the callback is + * involved. The book is unrefed in the callback */ + g_object_ref (book_client); + + book_query = e_book_query_field_exists (E_CONTACT_ADDRESS); + query_string = e_book_query_to_string (book_query); + e_book_query_unref (book_query); + + e_book_client_get_contacts ( + book_client, query_string, NULL, + book_contacts_received_cb, map); + + g_free (query_string); +} + +EContactMap * +e_contact_map_window_get_map (EContactMapWindow *window) +{ + g_return_val_if_fail (E_IS_CONTACT_MAP_WINDOW (window), NULL); + + return window->priv->map; +} + +#endif /* WITH_CONTACT_MAPS */ diff --git a/addressbook/gui/widgets/e-contact-map-window.h b/addressbook/gui/widgets/e-contact-map-window.h new file mode 100644 index 0000000000..aa7bff4208 --- /dev/null +++ b/addressbook/gui/widgets/e-contact-map-window.h @@ -0,0 +1,81 @@ +/* + * e-contact-map-window.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * Copyright (C) 2011 Dan Vratil <dvratil@redhat.com> + * + */ + +#ifndef E_CONTACT_MAP_WINDOW_H +#define E_CONTACT_MAP_WINDOW_H + +#ifdef WITH_CONTACT_MAPS + +#include <gtk/gtk.h> + +#include <libebook/libebook.h> + +#include "e-contact-map.h" + +/* Standard GObject macros */ +#define E_TYPE_CONTACT_MAP_WINDOW \ + (e_contact_map_window_get_type ()) +#define E_CONTACT_MAP_WINDOW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_CONTACT_MAP_WINDOW, EContactMapWindow)) +#define E_CONTACT_MAP_WINDOW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_CONTACT_MAP_WINDOW, EContactMapWindowClass)) +#define E_IS_CONTACT_MAP_WINDOW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_CONTACT_MAP_WINDOW)) +#define E_IS_CONTACT_MAP_WINDOW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_CONTACT_MAP_WINDOW)) +#define E_CONTACT_MAP_WINDOW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_CONTACT_MAP_WINDOW, EContactMapWindowClass)) + +G_BEGIN_DECLS + +typedef struct _EContactMapWindow EContactMapWindow; +typedef struct _EContactMapWindowClass EContactMapWindowClass; +typedef struct _EContactMapWindowPrivate EContactMapWindowPrivate; + +struct _EContactMapWindow { + GtkWindow parent; + EContactMapWindowPrivate *priv; +}; + +struct _EContactMapWindowClass { + GtkWindowClass parent_class; + + void (*show_contact_editor) (EContactMapWindow *window, + const gchar *contact_uid); +}; + +GType e_contact_map_window_get_type (void) G_GNUC_CONST; +EContactMapWindow * e_contact_map_window_new (void); + +void e_contact_map_window_load_addressbook (EContactMapWindow *window, + EBookClient *book); + +EContactMap * e_contact_map_window_get_map (EContactMapWindow *window); + +G_END_DECLS + +#endif /* WITH_CONTACT_MAPS */ + +#endif /* E_CONTACT_MAP_WINDOW_H */ diff --git a/addressbook/gui/widgets/e-contact-map.c b/addressbook/gui/widgets/e-contact-map.c new file mode 100644 index 0000000000..57e7e55b97 --- /dev/null +++ b/addressbook/gui/widgets/e-contact-map.c @@ -0,0 +1,408 @@ +/* + * e-contact-map.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * Copyright (C) 2011 Dan Vratil <dvratil@redhat.com> + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef WITH_CONTACT_MAPS + +#include "e-contact-map.h" + +#include <champlain/champlain.h> +#include <champlain-gtk/champlain-gtk.h> +#include <geoclue/geoclue-address.h> +#include <geoclue/geoclue-position.h> +#include <geocode-glib.h> + +#include <clutter/clutter.h> + +#include <string.h> +#include <glib/gi18n.h> +#include <math.h> + +#include "e-util/e-util.h" + +#include "e-contact-marker.h" + +#define E_CONTACT_MAP_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_CONTACT_MAP, EContactMapPrivate)) + +typedef struct _AsyncContext AsyncContext; + +struct _EContactMapPrivate { + GHashTable *markers; /* Hash table contact-name -> marker */ + + ChamplainMarkerLayer *marker_layer; +}; + +struct _AsyncContext { + EContactMap *map; + EContactMarker *marker; +}; + +enum { + CONTACT_ADDED, + CONTACT_REMOVED, + GEOCODING_STARTED, + GEOCODING_FAILED, + LAST_SIGNAL +}; + +static gint signals[LAST_SIGNAL] = {0}; + +G_DEFINE_TYPE (EContactMap, e_contact_map, GTK_CHAMPLAIN_TYPE_EMBED) + +static void +async_context_free (AsyncContext *async_context) +{ + if (async_context->map != NULL) + g_object_unref (async_context->map); + + g_slice_free (AsyncContext, async_context); +} + +static void +contact_map_address_resolved_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GHashTable *resolved = NULL; + gpointer marker_ptr; + const gchar *name; + gdouble latitude, longitude; + AsyncContext *async_context = user_data; + ChamplainMarkerLayer *marker_layer; + ChamplainMarker *marker; + GError *error = NULL; + + g_return_if_fail (async_context != NULL); + g_return_if_fail (E_IS_CONTACT_MAP (async_context->map)); + g_return_if_fail (E_IS_CONTACT_MARKER (async_context->marker)); + + marker = CHAMPLAIN_MARKER (async_context->marker); + marker_layer = async_context->map->priv->marker_layer; + + /* If the marker_layer does not exist anymore, the map has + * probably been destroyed before this callback was launched. + * It's not a failure, just silently clean up what was left + * behind and pretend nothing happened. */ + + if (!CHAMPLAIN_IS_MARKER_LAYER (marker_layer)) + goto exit; + + resolved = geocode_object_resolve_finish ( + GEOCODE_OBJECT (source), result, &error); + + if (resolved == NULL || + !geocode_object_get_coords (resolved, &longitude, &latitude)) { + const gchar *name; + if (error) + g_error_free (error); + name = champlain_label_get_text (CHAMPLAIN_LABEL (marker)); + g_signal_emit ( + async_context->map, + signals[GEOCODING_FAILED], 0, name); + goto exit; + } + + /* Move the marker to resolved position */ + champlain_location_set_location ( + CHAMPLAIN_LOCATION (marker), latitude, longitude); + champlain_marker_layer_add_marker (marker_layer, marker); + champlain_marker_set_selected (marker, FALSE); + + /* Store the marker in the hash table. Use it's label as key */ + name = champlain_label_get_text (CHAMPLAIN_LABEL (marker)); + marker_ptr = g_hash_table_lookup ( + async_context->map->priv->markers, name); + if (marker_ptr != NULL) { + g_hash_table_remove (async_context->map->priv->markers, name); + champlain_marker_layer_remove_marker (marker_layer, marker_ptr); + } + g_hash_table_insert ( + async_context->map->priv->markers, + g_strdup (name), marker); + + g_signal_emit ( + async_context->map, + signals[CONTACT_ADDED], 0, marker); + +exit: + async_context_free (async_context); + + if (resolved != NULL) + g_hash_table_unref (resolved); +} + +static void +resolve_marker_position (EContactMap *map, + EContactMarker *marker, + EContactAddress *address) +{ + GeocodeObject *geocoder; + AsyncContext *async_context; + const gchar *key; + + g_return_if_fail (E_IS_CONTACT_MAP (map)); + g_return_if_fail (address != NULL); + + geocoder = geocode_object_new (); + + key = GEOCODE_OBJECT_FIELD_POSTAL; + geocode_object_add (geocoder, key, address->code); + + key = GEOCODE_OBJECT_FIELD_COUNTRY; + geocode_object_add (geocoder, key, address->country); + + key = GEOCODE_OBJECT_FIELD_STATE; + geocode_object_add (geocoder, key, address->region); + + key = GEOCODE_OBJECT_FIELD_CITY; + geocode_object_add (geocoder, key, address->locality); + + key = GEOCODE_OBJECT_FIELD_STREET; + geocode_object_add (geocoder, key, address->street); + + async_context = g_slice_new0 (AsyncContext); + async_context->map = g_object_ref (map); + async_context->marker = marker; + + geocode_object_resolve_async ( + geocoder, NULL, + contact_map_address_resolved_cb, + async_context); + + g_object_unref (geocoder); + + g_signal_emit (map, signals[GEOCODING_STARTED], 0, marker); +} + +static void +contact_map_finalize (GObject *object) +{ + EContactMapPrivate *priv; + + priv = E_CONTACT_MAP (object)->priv; + + if (priv->markers) { + g_hash_table_destroy (priv->markers); + priv->markers = NULL; + } + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_contact_map_parent_class)->finalize (object); +} + +static void +e_contact_map_class_init (EContactMapClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (EContactMapPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->finalize = contact_map_finalize; + + signals[CONTACT_ADDED] = g_signal_new ( + "contact-added", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EContactMapClass, contact_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, G_TYPE_OBJECT); + + signals[CONTACT_REMOVED] = g_signal_new ( + "contact-removed", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EContactMapClass, contact_removed), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); + + signals[GEOCODING_STARTED] = g_signal_new ( + "geocoding-started", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EContactMapClass, geocoding_started), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, G_TYPE_OBJECT); + + signals[GEOCODING_FAILED] = g_signal_new ( + "geocoding-failed", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EContactMapClass, geocoding_failed), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); +} + +static void +e_contact_map_init (EContactMap *map) +{ + GHashTable *hash_table; + ChamplainMarkerLayer *layer; + ChamplainView *view; + + map->priv = E_CONTACT_MAP_GET_PRIVATE (map); + + hash_table = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) g_free, NULL); + + map->priv->markers = hash_table; + + view = gtk_champlain_embed_get_view (GTK_CHAMPLAIN_EMBED (map)); + /* This feature is somehow broken sometimes, so disable it for now */ + champlain_view_set_zoom_on_double_click (view, FALSE); + layer = champlain_marker_layer_new_full (CHAMPLAIN_SELECTION_SINGLE); + champlain_view_add_layer (view, CHAMPLAIN_LAYER (layer)); + map->priv->marker_layer = layer; +} + +GtkWidget * +e_contact_map_new (void) +{ + return g_object_new ( + E_TYPE_CONTACT_MAP,NULL); +} + +void +e_contact_map_add_contact (EContactMap *map, + EContact *contact) +{ + EContactAddress *address; + EContactPhoto *photo; + const gchar *contact_uid; + gchar *name; + + g_return_if_fail (map && E_IS_CONTACT_MAP (map)); + g_return_if_fail (contact && E_IS_CONTACT (contact)); + + photo = e_contact_get (contact, E_CONTACT_PHOTO); + contact_uid = e_contact_get_const (contact, E_CONTACT_UID); + + address = e_contact_get (contact, E_CONTACT_ADDRESS_HOME); + if (address) { + name = g_strconcat (e_contact_get_const (contact, E_CONTACT_FILE_AS), " (", _("Home"), ")", NULL); + e_contact_map_add_marker (map, name, contact_uid, address, photo); + g_free (name); + e_contact_address_free (address); + } + + address = e_contact_get (contact, E_CONTACT_ADDRESS_WORK); + if (address) { + name = g_strconcat (e_contact_get_const (contact, E_CONTACT_FILE_AS), " (", _("Work"), ")", NULL); + e_contact_map_add_marker (map, name, contact_uid, address, photo); + g_free (name); + e_contact_address_free (address); + } + + if (photo) + e_contact_photo_free (photo); +} + +void +e_contact_map_add_marker (EContactMap *map, + const gchar *name, + const gchar *contact_uid, + EContactAddress *address, + EContactPhoto *photo) +{ + EContactMarker *marker; + + g_return_if_fail (map && E_IS_CONTACT_MAP (map)); + g_return_if_fail (name && *name); + g_return_if_fail (contact_uid && *contact_uid); + g_return_if_fail (address); + + marker = E_CONTACT_MARKER (e_contact_marker_new (name, contact_uid, photo)); + + resolve_marker_position (map, marker, address); +} + +/** + * The \name parameter must match the label of the + * marker (for example "John Smith (work)") + */ +void +e_contact_map_remove_contact (EContactMap *map, + const gchar *name) +{ + ChamplainMarker *marker; + + g_return_if_fail (map && E_IS_CONTACT_MAP (map)); + g_return_if_fail (name && *name); + + marker = g_hash_table_lookup (map->priv->markers, name); + + champlain_marker_layer_remove_marker (map->priv->marker_layer, marker); + + g_hash_table_remove (map->priv->markers, name); + + g_signal_emit (map, signals[CONTACT_REMOVED], 0, name); +} + +void +e_contact_map_remove_marker (EContactMap *map, + ClutterActor *marker) +{ + const gchar *name; + + g_return_if_fail (map && E_IS_CONTACT_MAP (map)); + g_return_if_fail (marker && CLUTTER_IS_ACTOR (marker)); + + name = champlain_label_get_text (CHAMPLAIN_LABEL (marker)); + + e_contact_map_remove_contact (map, name); +} + +void +e_contact_map_zoom_on_marker (EContactMap *map, + ClutterActor *marker) +{ + ChamplainView *view; + gdouble lat, lng; + + g_return_if_fail (map && E_IS_CONTACT_MAP (map)); + g_return_if_fail (marker && CLUTTER_IS_ACTOR (marker)); + + lat = champlain_location_get_latitude (CHAMPLAIN_LOCATION (marker)); + lng = champlain_location_get_longitude (CHAMPLAIN_LOCATION (marker)); + + view = gtk_champlain_embed_get_view (GTK_CHAMPLAIN_EMBED (map)); + + champlain_view_center_on (view, lat, lng); + champlain_view_set_zoom_level (view, 15); +} + +ChamplainView * +e_contact_map_get_view (EContactMap *map) +{ + g_return_val_if_fail (E_IS_CONTACT_MAP (map), NULL); + + return gtk_champlain_embed_get_view (GTK_CHAMPLAIN_EMBED (map)); +} + +#endif /* WITH_CONTACT_MAPS */ diff --git a/addressbook/gui/widgets/e-contact-map.h b/addressbook/gui/widgets/e-contact-map.h new file mode 100644 index 0000000000..d9503e2c9b --- /dev/null +++ b/addressbook/gui/widgets/e-contact-map.h @@ -0,0 +1,106 @@ +/* + * e-contact-map.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * Copyright (C) 2011 Dan Vratil <dvratil@redhat.com> + * + */ + +#ifndef E_CONTACT_MAP_H +#define E_CONTACT_MAP_H + +#ifdef WITH_CONTACT_MAPS + +#include <gtk/gtk.h> + +#include <champlain/champlain.h> +#include <champlain-gtk/champlain-gtk.h> + +#include <libebook/libebook.h> + +/* Standard GObject macros */ +#define E_TYPE_CONTACT_MAP \ + (e_contact_map_get_type ()) +#define E_CONTACT_MAP(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_CONTACT_MAP, EContactMap)) +#define E_CONTACT_MAP_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_CONTACT_MAP, EContactMapClass)) +#define E_IS_CONTACT_MAP(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_CONTACT_MAP)) +#define E_IS_CONTACT_MAP_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_CONTACT_MAP)) +#define E_CONTACT_MAP_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_CONTACT_MAP, EContactMapClass)) + +G_BEGIN_DECLS + +typedef struct _EContactMap EContactMap; +typedef struct _EContactMapClass EContactMapClass; +typedef struct _EContactMapPrivate EContactMapPrivate; + +struct _EContactMap { + GtkChamplainEmbed parent; + EContactMapPrivate *priv; +}; + +struct _EContactMapClass { + GtkWindowClass parent_class; + + void (*contact_added) (EContactMap *map, + ClutterActor *marker); + + void (*contact_removed) (EContactMap *map, + const gchar *name); + + void (*geocoding_started) (EContactMap *map, + ClutterActor *marker); + + void (*geocoding_failed) (EContactMap *map, + const gchar *name); +}; + +GType e_contact_map_get_type (void) G_GNUC_CONST; +GtkWidget * e_contact_map_new (void); + +void e_contact_map_add_contact (EContactMap *map, + EContact *contact); + +void e_contact_map_add_marker (EContactMap *map, + const gchar *name, + const gchar *contact_uid, + EContactAddress *address, + EContactPhoto *photo); + +void e_contact_map_remove_contact (EContactMap *map, + const gchar *name); + +void e_contact_map_remove_marker (EContactMap *map, + ClutterActor *marker); + +void e_contact_map_zoom_on_marker (EContactMap *map, + ClutterActor *marker); + +ChamplainView * e_contact_map_get_view (EContactMap *map); + +G_END_DECLS + +#endif /* WITH_CONTACT_MAPS */ + +#endif diff --git a/addressbook/gui/widgets/e-contact-marker.c b/addressbook/gui/widgets/e-contact-marker.c new file mode 100644 index 0000000000..9ac9417c9f --- /dev/null +++ b/addressbook/gui/widgets/e-contact-marker.c @@ -0,0 +1,624 @@ +/* + * e-contact-marker.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * Copyright (C) 2008 Pierre-Luc Beaudoin <pierre-luc@pierlux.com> + * Copyright (C) 2011 Jiri Techet <techet@gmail.com> + * Copyright (C) 2011 Dan Vratil <dvratil@redhat.com> + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef WITH_CONTACT_MAPS + +#include "e-contact-marker.h" + +#include <champlain/champlain.h> +#include <gtk/gtk.h> +#include <clutter/clutter.h> +#include <glib.h> +#include <glib/gi18n.h> +#include <glib-object.h> +#include <cairo.h> +#include <math.h> +#include <string.h> + +#define E_CONTACT_MARKER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_CONTACT_MARKER, EContactMarkerPrivate)) + +G_DEFINE_TYPE (EContactMarker, e_contact_marker, CHAMPLAIN_TYPE_LABEL); + +struct _EContactMarkerPrivate +{ + gchar *contact_uid; + + ClutterActor *image; + ClutterActor *text_actor; + + ClutterActor *shadow; + ClutterActor *background; + + guint total_width; + guint total_height; + + ClutterGroup *content_group; + + guint redraw_id; +}; + +enum { + DOUBLE_CLICKED, + LAST_SIGNAL +}; + +static gint signals[LAST_SIGNAL] = {0}; + +#define DEFAULT_FONT_NAME "Serif 9" + +static ClutterColor DEFAULT_COLOR = { 0x33, 0x33, 0x33, 0xff }; + +#define RADIUS 10 +#define PADDING (RADIUS / 2) + +static gboolean +contact_marker_clicked_cb (ClutterActor *actor, + ClutterEvent *event, + gpointer user_data) +{ + gint click_count = clutter_event_get_click_count (event); + + if (click_count == 2) + g_signal_emit (E_CONTACT_MARKER (actor), signals[DOUBLE_CLICKED], 0); + + return TRUE; +} + +static ClutterActor * +texture_new_from_pixbuf (GdkPixbuf *pixbuf, + GError **error) +{ + ClutterActor *texture = NULL; + const guchar *data; + gboolean has_alpha, success; + gint width, height, rowstride; + ClutterTextureFlags flags = 0; + + data = gdk_pixbuf_get_pixels (pixbuf); + width = gdk_pixbuf_get_width (pixbuf); + height = gdk_pixbuf_get_height (pixbuf); + has_alpha = gdk_pixbuf_get_has_alpha (pixbuf); + rowstride = gdk_pixbuf_get_rowstride (pixbuf); + + texture = clutter_texture_new (); + success = clutter_texture_set_from_rgb_data ( + CLUTTER_TEXTURE (texture), + data, has_alpha, width, height, rowstride, + (has_alpha ? 4: 3), flags, NULL); + + if (!success) { + clutter_actor_destroy (CLUTTER_ACTOR (texture)); + texture = NULL; + } + + return texture; +} + +static ClutterActor * +contact_photo_to_texture (EContactPhoto *photo) +{ + GdkPixbuf *pixbuf; + + if (photo->type == E_CONTACT_PHOTO_TYPE_INLINED) { + GError *error = NULL; + + GdkPixbufLoader *loader = gdk_pixbuf_loader_new (); + gdk_pixbuf_loader_write ( + loader, photo->data.inlined.data, + photo->data.inlined.length, NULL); + gdk_pixbuf_loader_close (loader, NULL); + pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); + if (pixbuf) + g_object_ref (pixbuf); + g_object_unref (loader); + + if (error) { + g_error_free (error); + return NULL; + } + } else if (photo->type == E_CONTACT_PHOTO_TYPE_URI) { + GError *error = NULL; + + pixbuf = gdk_pixbuf_new_from_file (photo->data.uri, &error); + + if (error) { + g_error_free (error); + return NULL; + } + } else + return NULL; + + if (pixbuf) { + ClutterActor *texture; + GError *error = NULL; + + texture = texture_new_from_pixbuf (pixbuf, &error); + if (error) { + g_error_free (error); + g_object_unref (pixbuf); + return NULL; + } + + g_object_unref (pixbuf); + return texture; + } + + return NULL; +} + +static void +draw_box (cairo_t *cr, + gint width, + gint height, + gint point) +{ + cairo_move_to (cr, RADIUS, 0); + cairo_line_to (cr, width - RADIUS, 0); + cairo_arc (cr, width - RADIUS, RADIUS, RADIUS - 1, 3 * M_PI / 2.0, 0); + cairo_line_to (cr, width, height - RADIUS); + cairo_arc (cr, width - RADIUS, height - RADIUS, RADIUS - 1, 0, M_PI / 2.0); + cairo_line_to (cr, point, height); + cairo_line_to (cr, 0, height + point); + cairo_arc (cr, RADIUS, RADIUS, RADIUS - 1, M_PI, 3 * M_PI / 2.0); + cairo_close_path (cr); +} + +static void +draw_shadow (EContactMarker *marker, + gint width, + gint height, + gint point) +{ + EContactMarkerPrivate *priv = marker->priv; + ClutterActor *shadow = NULL; + cairo_t *cr; + gdouble slope; + gdouble scaling; + gint x; + cairo_matrix_t matrix; + + slope = -0.3; + scaling = 0.65; + x = -40 * slope; + + shadow = clutter_cairo_texture_new (width + x, (height + point)); + cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (shadow)); + + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); + cairo_paint (cr); + cairo_set_operator (cr, CAIRO_OPERATOR_OVER); + + cairo_matrix_init (&matrix, 1, 0, slope, scaling, x, 0); + cairo_set_matrix (cr, &matrix); + + draw_box (cr, width, height, point); + + cairo_set_source_rgba (cr, 0, 0, 0, 0.15); + cairo_fill (cr); + + cairo_destroy (cr); + + clutter_actor_set_position (shadow, 0, height / 2.0); + + clutter_container_add_actor (CLUTTER_CONTAINER (priv->content_group), shadow); + + if (priv->shadow != NULL) { + clutter_container_remove_actor ( + CLUTTER_CONTAINER (priv->content_group), + priv->shadow); + } + + priv->shadow = shadow; +} + +static void +draw_background (EContactMarker *marker, + gint width, + gint height, + gint point) +{ + EContactMarkerPrivate *priv = marker->priv; + ClutterActor *bg = NULL; + const ClutterColor *color; + ClutterColor darker_color; + cairo_t *cr; + + bg = clutter_cairo_texture_new (width, height + point); + cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (bg)); + + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); + cairo_paint (cr); + cairo_set_operator (cr, CAIRO_OPERATOR_OVER); + + /* If selected, add the selection color to the marker's color */ + if (champlain_marker_get_selected (CHAMPLAIN_MARKER (marker))) + color = champlain_marker_get_selection_color (); + else + color = &DEFAULT_COLOR; + + draw_box (cr, width, height, point); + + clutter_color_darken (color, &darker_color); + + cairo_set_source_rgba ( + cr, + color->red / 255.0, + color->green / 255.0, + color->blue / 255.0, + color->alpha / 255.0); + cairo_fill_preserve (cr); + + cairo_set_line_width (cr, 1.0); + cairo_set_source_rgba ( + cr, + darker_color.red / 255.0, + darker_color.green / 255.0, + darker_color.blue / 255.0, + darker_color.alpha / 255.0); + cairo_stroke (cr); + cairo_destroy (cr); + + clutter_container_add_actor (CLUTTER_CONTAINER (priv->content_group), bg); + + if (priv->background != NULL) { + clutter_container_remove_actor ( + CLUTTER_CONTAINER (priv->content_group), + priv->background); + } + + priv->background = bg; +} + +static void +draw_marker (EContactMarker *marker) +{ + EContactMarkerPrivate *priv = marker->priv; + ChamplainLabel *label = CHAMPLAIN_LABEL (marker); + guint height = 0, point = 0; + guint total_width = 0, total_height = 0; + ClutterText *text; + + if (priv->image) { + clutter_actor_set_position (priv->image, 2 *PADDING, 2 *PADDING); + if (clutter_actor_get_parent (priv->image) == NULL) + clutter_container_add_actor ( + CLUTTER_CONTAINER (priv->content_group), + priv->image); + } + + if (priv->text_actor == NULL) { + priv->text_actor = clutter_text_new_with_text ( + "Serif 8", + champlain_label_get_text (label)); + champlain_label_set_font_name (label, "Serif 8"); + } + + text = CLUTTER_TEXT (priv->text_actor); + clutter_text_set_text ( + text, + champlain_label_get_text (label)); + clutter_text_set_font_name ( + text, + champlain_label_get_font_name (label)); + clutter_text_set_line_alignment (text, PANGO_ALIGN_CENTER); + clutter_text_set_line_wrap (text, TRUE); + clutter_text_set_line_wrap_mode (text, PANGO_WRAP_WORD); + clutter_text_set_ellipsize ( + text, + champlain_label_get_ellipsize (label)); + clutter_text_set_attributes ( + text, + champlain_label_get_attributes (label)); + clutter_text_set_use_markup ( + text, + champlain_label_get_use_markup (label)); + + if (priv->image) { + clutter_actor_set_width ( + priv->text_actor, + clutter_actor_get_width (priv->image)); + total_height = clutter_actor_get_height (priv->image) + 2 *PADDING + + clutter_actor_get_height (priv->text_actor) + 2 *PADDING; + total_width = clutter_actor_get_width (priv->image) + 4 *PADDING; + clutter_actor_set_position ( + priv->text_actor, PADDING, + clutter_actor_get_height (priv->image) + 2 *PADDING + 3); + } else { + total_height = clutter_actor_get_height (priv->text_actor) + 2 *PADDING; + total_width = clutter_actor_get_width (priv->text_actor) + 4 *PADDING; + clutter_actor_set_position (priv->text_actor, 2 * PADDING, PADDING); + } + + height += 2 * PADDING; + if (height > total_height) + total_height = height; + + clutter_text_set_color ( + CLUTTER_TEXT (priv->text_actor), + (champlain_marker_get_selected (CHAMPLAIN_MARKER (marker)) ? + champlain_marker_get_selection_text_color () : + champlain_label_get_text_color (CHAMPLAIN_LABEL (marker)))); + if (clutter_actor_get_parent (priv->text_actor) == NULL) + clutter_container_add_actor ( + CLUTTER_CONTAINER (priv->content_group), + priv->text_actor); + + if (priv->text_actor == NULL && priv->image == NULL) { + total_width = 6 * PADDING; + total_height = 6 * PADDING; + } + + point = (total_height + 2 * PADDING) / 4.0; + priv->total_width = total_width; + priv->total_height = total_height; + + draw_shadow (marker, total_width, total_height, point); + draw_background (marker, total_width, total_height, point); + + if (priv->text_actor != NULL && priv->background != NULL) + clutter_actor_raise (priv->text_actor, priv->background); + if (priv->image != NULL && priv->background != NULL) + clutter_actor_raise (priv->image, priv->background); + + clutter_actor_set_anchor_point (CLUTTER_ACTOR (marker), 0, total_height + point); +} + +static gboolean +redraw_on_idle (gpointer gobject) +{ + EContactMarker *marker = E_CONTACT_MARKER (gobject); + + draw_marker (marker); + marker->priv->redraw_id = 0; + return FALSE; +} + +static void +queue_redraw (EContactMarker *marker) +{ + EContactMarkerPrivate *priv = marker->priv; + + if (!priv->redraw_id) { + priv->redraw_id = g_idle_add_full ( + G_PRIORITY_DEFAULT, + (GSourceFunc) redraw_on_idle, + g_object_ref (marker), + (GDestroyNotify) g_object_unref); + } +} + +static void +allocate (ClutterActor *self, + const ClutterActorBox *box, + ClutterAllocationFlags flags) +{ + ClutterActorBox child_box; + EContactMarkerPrivate *priv = E_CONTACT_MARKER (self)->priv; + + CLUTTER_ACTOR_CLASS (e_contact_marker_parent_class)->allocate (self, box, flags); + + child_box.x1 = 0; + child_box.x2 = box->x2 - box->x1; + child_box.y1 = 0; + child_box.y2 = box->y2 - box->y1; + clutter_actor_allocate (CLUTTER_ACTOR (priv->content_group), &child_box, flags); +} + +static void +paint (ClutterActor *self) +{ + EContactMarkerPrivate *priv = E_CONTACT_MARKER (self)->priv; + + clutter_actor_paint (CLUTTER_ACTOR (priv->content_group)); +} + +static void +map (ClutterActor *self) +{ + EContactMarkerPrivate *priv = E_CONTACT_MARKER (self)->priv; + + CLUTTER_ACTOR_CLASS (e_contact_marker_parent_class)->map (self); + + clutter_actor_map (CLUTTER_ACTOR (priv->content_group)); +} + +static void +unmap (ClutterActor *self) +{ + EContactMarkerPrivate *priv = E_CONTACT_MARKER (self)->priv; + + CLUTTER_ACTOR_CLASS (e_contact_marker_parent_class)->unmap (self); + + clutter_actor_unmap (CLUTTER_ACTOR (priv->content_group)); +} + +static void +pick (ClutterActor *self, + const ClutterColor *color) +{ + EContactMarkerPrivate *priv = E_CONTACT_MARKER (self)->priv; + gfloat width, height; + + if (!clutter_actor_should_pick_paint (self)) + return; + + width = priv->total_width; + height = priv->total_height; + + cogl_path_new (); + + cogl_set_source_color4ub ( + color->red, + color->green, + color->blue, + color->alpha); + + cogl_path_move_to (RADIUS, 0); + cogl_path_line_to (width - RADIUS, 0); + cogl_path_arc (width - RADIUS, RADIUS, RADIUS, RADIUS, -90, 0); + cogl_path_line_to (width, height - RADIUS); + cogl_path_arc (width - RADIUS, height - RADIUS, RADIUS, RADIUS, 0, 90); + cogl_path_line_to (RADIUS, height); + cogl_path_arc (RADIUS, height - RADIUS, RADIUS, RADIUS, 90, 180); + cogl_path_line_to (0, RADIUS); + cogl_path_arc (RADIUS, RADIUS, RADIUS, RADIUS, 180, 270); + cogl_path_close (); + cogl_path_fill (); +} + +static void +notify_selected (GObject *gobject, + G_GNUC_UNUSED GParamSpec *pspec, + G_GNUC_UNUSED gpointer user_data) +{ + queue_redraw (E_CONTACT_MARKER (gobject)); +} + +static void +e_contact_marker_finalize (GObject *object) +{ + EContactMarkerPrivate *priv = E_CONTACT_MARKER (object)->priv; + + if (priv->contact_uid) { + g_free (priv->contact_uid); + priv->contact_uid = NULL; + } + + if (priv->redraw_id) { + g_source_remove (priv->redraw_id); + priv->redraw_id = 0; + } + + G_OBJECT_CLASS (e_contact_marker_parent_class)->finalize (object); +} + +static void +e_contact_marker_dispose (GObject *object) +{ + EContactMarkerPrivate *priv = E_CONTACT_MARKER (object)->priv; + + priv->background = NULL; + priv->shadow = NULL; + priv->text_actor = NULL; + + if (priv->content_group) { + clutter_actor_unparent (CLUTTER_ACTOR (priv->content_group)); + priv->content_group = NULL; + } + + G_OBJECT_CLASS (e_contact_marker_parent_class)->dispose (object); +} + +static void +e_contact_marker_class_init (EContactMarkerClass *class) +{ + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (class); + GObjectClass *object_class = G_OBJECT_CLASS (class); + + g_type_class_add_private (class, sizeof (EContactMarkerPrivate)); + + object_class->dispose = e_contact_marker_dispose; + object_class->finalize = e_contact_marker_finalize; + + actor_class->paint = paint; + actor_class->allocate = allocate; + actor_class->map = map; + actor_class->unmap = unmap; + actor_class->pick = pick; + + signals[DOUBLE_CLICKED] = g_signal_new ( + "double-clicked", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EContactMarkerClass, double_clicked), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +e_contact_marker_init (EContactMarker *marker) +{ + EContactMarkerPrivate *priv; + + priv = E_CONTACT_MARKER_GET_PRIVATE (marker); + + marker->priv = priv; + priv->contact_uid = NULL; + priv->image = NULL; + priv->background = NULL; + priv->shadow = NULL; + priv->text_actor = NULL; + priv->content_group = CLUTTER_GROUP (clutter_group_new ()); + priv->redraw_id = 0; + + clutter_actor_set_parent ( + CLUTTER_ACTOR (priv->content_group), CLUTTER_ACTOR (marker)); + clutter_actor_queue_relayout (CLUTTER_ACTOR (marker)); + + priv->total_width = 0; + priv->total_height = 0; + + g_signal_connect ( + marker, "notify::selected", + G_CALLBACK (notify_selected), NULL); + g_signal_connect ( + marker, "button-release-event", + G_CALLBACK (contact_marker_clicked_cb), NULL); +} + +ClutterActor * +e_contact_marker_new (const gchar *name, + const gchar *contact_uid, + EContactPhoto *photo) +{ + ClutterActor *marker = CLUTTER_ACTOR (g_object_new (E_TYPE_CONTACT_MARKER, NULL)); + EContactMarkerPrivate *priv = E_CONTACT_MARKER (marker)->priv; + + g_return_val_if_fail (name && *name, NULL); + g_return_val_if_fail (contact_uid && *contact_uid, NULL); + + champlain_label_set_text (CHAMPLAIN_LABEL (marker), name); + priv->contact_uid = g_strdup (contact_uid); + if (photo) + priv->image = contact_photo_to_texture (photo); + + queue_redraw (E_CONTACT_MARKER (marker)); + + return marker; +} + +const gchar * +e_contact_marker_get_contact_uid (EContactMarker *marker) +{ + g_return_val_if_fail (marker && E_IS_CONTACT_MARKER (marker), NULL); + + return marker->priv->contact_uid; +} + +#endif /* WITH_CONTACT_MAPS */ diff --git a/addressbook/gui/widgets/e-contact-marker.h b/addressbook/gui/widgets/e-contact-marker.h new file mode 100644 index 0000000000..791a9c46b5 --- /dev/null +++ b/addressbook/gui/widgets/e-contact-marker.h @@ -0,0 +1,84 @@ +/* + * e-contact-marker.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * Copyright (C) 2008 Pierre-Luc Beaudoin <pierre-luc@pierlux.com> + * Copyright (C) 2011 Jiri Techet <techet@gmail.com> + * Copyright (C) 2011 Dan Vratil <dvratil@redhat.com> + * + */ + +#ifndef E_CONTACT_MARKER_H +#define E_CONTACT_MARKER_H + +#ifdef WITH_CONTACT_MAPS + +#include <libebook/libebook.h> + +#include <champlain/champlain.h> + +#include <glib-object.h> +#include <clutter/clutter.h> + +G_BEGIN_DECLS + +#define E_TYPE_CONTACT_MARKER e_contact_marker_get_type () + +#define E_CONTACT_MARKER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_CONTACT_MARKER, EContactMarker)) + +#define E_CONTACT_MARKER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_CONTACT_MARKER, EContactMarkerClass)) + +#define E_IS_CONTACT_MARKER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_CONTACT_MARKER)) + +#define E_IS_CONTACT_MARKER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_CONTACT_MARKER)) + +#define E_CONTACT_MARKER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_CONTACT_MARKER, EContactMarkerClass)) + +typedef struct _EContactMarkerPrivate EContactMarkerPrivate; + +typedef struct _EContactMarker EContactMarker; +typedef struct _EContactMarkerClass EContactMarkerClass; + +struct _EContactMarker +{ + ChamplainLabel parent; + EContactMarkerPrivate *priv; +}; + +struct _EContactMarkerClass +{ + ChamplainLabelClass parent_class; + + void (*double_clicked) (ClutterActor *actor); +}; + +GType e_contact_marker_get_type (void); + +ClutterActor * e_contact_marker_new (const gchar *name, + const gchar *contact_uid, + EContactPhoto *photo); + +const gchar * e_contact_marker_get_contact_uid (EContactMarker *marker); + +G_END_DECLS + +#endif /* WITH_CONTACT_MAPS */ + +#endif diff --git a/addressbook/gui/widgets/e-minicard-control.c b/addressbook/gui/widgets/e-minicard-control.c deleted file mode 100644 index 73417af78c..0000000000 --- a/addressbook/gui/widgets/e-minicard-control.c +++ /dev/null @@ -1,373 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-minicard-control.c - * - * Authors: - * Chris Lahey <clahey@ximian.com> - * - * Copyright 1999, 2000, Ximian, Inc. - */ - -#include <config.h> - -#include <bonobo/bonobo-generic-factory.h> -#include <bonobo/bonobo-persist.h> -#include <bonobo/bonobo-persist-stream.h> -#include <bonobo/bonobo-stream-client.h> -#include <addressbook/backend/ebook/e-book.h> -#include <addressbook/backend/ebook/e-book-util.h> -#include <addressbook/backend/ebook/e-card.h> -#include <gal/util/e-util.h> - -#include <addressbook/gui/component/addressbook.h> - -#include "e-minicard-control.h" -#include "e-minicard-widget.h" -#include "e-card-merging.h" - -typedef struct { - EMinicardWidget *minicard; - GList *card_list; - GtkWidget *label; -} EMinicardControl; - -#if 0 -enum { - PROP_RUNNING -} MyArgs; - -#define RUNNING_KEY "Clock::Running" - -static void -get_prop (BonoboPropertyBag *bag, - BonoboArg *arg, - guint arg_id, - CORBA_Environment *ev, - gpointer user_data) -{ - GtkObject *clock = user_data; - - switch (arg_id) { - - case PROP_RUNNING: - { - gboolean b = GPOINTER_TO_UINT (gtk_object_get_data (clock, RUNNING_KEY)); - BONOBO_ARG_SET_BOOLEAN (arg, b); - break; - } - - default: - g_warning ("Unhandled arg %d", arg_id); - break; - } -} - -static void -set_prop (BonoboPropertyBag *bag, - const BonoboArg *arg, - guint arg_id, - CORBA_Environment *ev, - gpointer user_data) -{ - GtkClock *clock = user_data; - - switch (arg_id) { - - case PROP_RUNNING: - { - guint i; - - i = BONOBO_ARG_GET_BOOLEAN (arg); - - if (i) - gtk_clock_start (clock); - else - gtk_clock_stop (clock); - - gtk_object_set_data (GTK_OBJECT (clock), RUNNING_KEY, - GUINT_TO_POINTER (i)); - break; - } - - default: - g_warning ("Unhandled arg %d", arg_id); - break; - } -} -#endif - -/* - * Bonobo::PersistStream - * - * These two functions implement the Bonobo::PersistStream load and - * save methods which allow data to be loaded into and out of the - * BonoboObject. - */ -static char * -stream_read (Bonobo_Stream stream) -{ - Bonobo_Stream_iobuf *buffer; - CORBA_Environment ev; - char *data = NULL; - gint length = 0; - - CORBA_exception_init (&ev); - do { -#define READ_CHUNK_SIZE 65536 - Bonobo_Stream_read (stream, READ_CHUNK_SIZE, - &buffer, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) { - CORBA_exception_free (&ev); - return NULL; - } - - if (buffer->_length <= 0) - break; - - data = g_realloc (data, length + buffer->_length + 1); - - memcpy (data + length, buffer->_buffer, buffer->_length); - - length += buffer->_length; - - CORBA_free (buffer); - } while (1); - - CORBA_free (buffer); - CORBA_exception_free (&ev); - - if (data) - data[length] = '\0'; - else - data = g_strdup(""); - - return data; -} /* stream_read */ - -/* - * This function implements the Bonobo::PersistStream:load method. - */ -static void -pstream_load (BonoboPersistStream *ps, const Bonobo_Stream stream, - Bonobo_Persist_ContentType type, void *data, - CORBA_Environment *ev) -{ - GList *list; - char *vcard; - EMinicardControl *minicard_control = data; - - if (type && g_strcasecmp (type, "text/vCard") != 0 && - g_strcasecmp (type, "text/x-vCard") != 0) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_Bonobo_Persist_WrongDataType, NULL); - return; - } - - if ((vcard = stream_read (stream)) == NULL) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_Bonobo_Persist_FileNotFound, NULL); - return; - } - - e_free_object_list (minicard_control->card_list); - list = e_card_load_cards_from_string_with_default_charset(vcard, "ISO-8859-1"); - g_free(vcard); - minicard_control->card_list = list; - if (list) - gtk_object_set(GTK_OBJECT(minicard_control->minicard), - "card", list->data, - NULL); - if (list && list->next) { - char *message; - int length = g_list_length (list) - 1; - if (length > 1) { - message = g_strdup_printf (_("and %d other cards."), length); - } else { - message = g_strdup_printf (_("and one other card.")); - } - gtk_label_set_text (GTK_LABEL (minicard_control->label), message); - g_free (message); - gtk_widget_show (minicard_control->label); - } else { - gtk_widget_hide (minicard_control->label); - } -} /* pstream_load */ - -/* - * This function implements the Bonobo::PersistStream:save method. - */ -static void -pstream_save (BonoboPersistStream *ps, const Bonobo_Stream stream, - Bonobo_Persist_ContentType type, void *data, - CORBA_Environment *ev) -{ - EMinicardControl *minicard_control = data; - char *vcard; - int length; - - if (type && g_strcasecmp (type, "text/vCard") != 0 && - g_strcasecmp (type, "text/x-vCard") != 0) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_Bonobo_Persist_WrongDataType, NULL); - return; - } - - vcard = e_card_list_get_vcard(minicard_control->card_list); - length = strlen (vcard); - bonobo_stream_client_write (stream, vcard, length, ev); - g_free (vcard); -} /* pstream_save */ - -static CORBA_long -pstream_get_max_size (BonoboPersistStream *ps, void *data, - CORBA_Environment *ev) -{ - EMinicardControl *minicard_control = data; - char *vcard; - gint length; - - vcard = e_card_list_get_vcard(minicard_control->card_list); - length = strlen (vcard); - g_free (vcard); - - return length; -} - -static Bonobo_Persist_ContentTypeList * -pstream_get_content_types (BonoboPersistStream *ps, void *closure, - CORBA_Environment *ev) -{ - return bonobo_persist_generate_content_types (2, "text/vCard", "text/x-vCard"); -} - -static void -book_open_cb (EBook *book, EBookStatus status, gpointer closure) -{ - GList *list = closure; - if (book) { - GList *p; - for (p = list; p; p = p->next) { - e_card_merging_book_add_card(book, p->data, NULL, NULL); - } - gtk_object_unref (GTK_OBJECT (book)); - } - e_free_object_list (list); -} - -static void -save_in_addressbook(GtkWidget *button, gpointer data) -{ - EMinicardControl *minicard_control = data; - GList *list, *p; - EBook *book; - - book = e_book_new (); - - list = g_list_copy (minicard_control->card_list); - - for (p = list; p; p = p->next) - gtk_object_ref (GTK_OBJECT (p->data)); - - if (!addressbook_load_default_book (book, book_open_cb, list)) { - gtk_object_unref (GTK_OBJECT (book)); - book_open_cb (NULL, E_BOOK_STATUS_OTHER_ERROR, list); - } -} - -static void -free_struct (GtkWidget *control, gpointer data) -{ - EMinicardControl *minicard_control = data; - e_free_object_list (minicard_control->card_list); - g_free (minicard_control); -} - -static BonoboObject * -e_minicard_control_factory (BonoboGenericFactory *Factory, void *closure) -{ -#if 0 - BonoboPropertyBag *pb; -#endif - BonoboControl *control; - BonoboPersistStream *stream; - GtkWidget *minicard; - GtkWidget *button; - GtkWidget *label; - GtkWidget *vbox; - - EMinicardControl *minicard_control = g_new (EMinicardControl, 1); - - - minicard_control->card_list = NULL; - minicard_control->minicard = NULL; - minicard_control->label = NULL; - - /* Create the control. */ - - minicard = e_minicard_widget_new (); - gtk_widget_show (minicard); - minicard_control->minicard = E_MINICARD_WIDGET (minicard); - - /* This is intentionally not shown. */ - label = gtk_label_new (""); - minicard_control->label = label; - - button = gtk_button_new_with_label(_("Save in addressbook")); - gtk_signal_connect(GTK_OBJECT(button), "clicked", - save_in_addressbook, minicard_control); - gtk_widget_show (button); - - vbox = gtk_vbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox), minicard, TRUE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0); - gtk_widget_show (vbox); - - control = bonobo_control_new (vbox); - - gtk_signal_connect (GTK_OBJECT (control), "destroy", - free_struct, minicard_control); - - stream = bonobo_persist_stream_new (pstream_load, pstream_save, - pstream_get_max_size, - pstream_get_content_types, - minicard_control); - -#if 0 - /* Create the properties. */ - pb = bonobo_property_bag_new (get_prop, set_prop, clock); - bonobo_control_set_properties (control, pb); - - bonobo_property_bag_add (pb, "running", PROP_RUNNING, - BONOBO_ARG_BOOLEAN, NULL, - "Whether or not the clock is running", 0); -#endif - - if (stream == NULL) { - bonobo_object_unref (BONOBO_OBJECT (control)); - return NULL; - } - - bonobo_object_add_interface (BONOBO_OBJECT (control), - BONOBO_OBJECT (stream)); - - return BONOBO_OBJECT (control); -} - -void -e_minicard_control_factory_init (void) -{ - static BonoboGenericFactory *factory = NULL; - - if (factory != NULL) - return; - - factory = - bonobo_generic_factory_new ( - "OAFIID:GNOME_Evolution_Addressbook_MiniCard_ControlFactory", - e_minicard_control_factory, NULL); - - if (factory == NULL) - g_error ("I could not register a EMinicard control factory."); -} diff --git a/addressbook/gui/widgets/e-minicard-control.h b/addressbook/gui/widgets/e-minicard-control.h deleted file mode 100644 index 4a0da88435..0000000000 --- a/addressbook/gui/widgets/e-minicard-control.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __E_MINICARD_CONTROL_H__ -#define __E_MINICARD_CONTROL_H__ - -#include <bonobo/bonobo-control.h> - -void e_minicard_control_factory_init (void); - -#endif /* __E_MINICARD_CONTROL_H__ */ diff --git a/addressbook/gui/widgets/e-minicard-label.c b/addressbook/gui/widgets/e-minicard-label.c index b59ff46ae3..0e75917b80 100644 --- a/addressbook/gui/widgets/e-minicard-label.c +++ b/addressbook/gui/widgets/e-minicard-label.c @@ -1,216 +1,286 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-minicard-label.c - * Copyright (C) 2000 Ximian, Inc. - * Author: Chris Lahey <clahey@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. * * 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. + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. */ +#ifdef HAVE_CONFIG_H #include <config.h> +#endif #include "e-minicard-label.h" -#include <gtk/gtksignal.h> -#include <libgnomeui/gnome-canvas-rect-ellipse.h> -#include <gal/util/e-util.h> -#include <gal/e-text/e-text.h> -#include <gal/widgets/e-canvas.h> -#include <gal/widgets/e-canvas-utils.h> +#include <gtk/gtk.h> +#include <glib/gi18n.h> #include <gdk/gdkkeysyms.h> -static void e_minicard_label_init (EMinicardLabel *card); -static void e_minicard_label_class_init (EMinicardLabelClass *klass); -static void e_minicard_label_set_arg (GtkObject *o, GtkArg *arg, guint arg_id); -static void e_minicard_label_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); +#include <libgnomecanvas/libgnomecanvas.h> + +#include "e-util/e-util.h" + +static void e_minicard_label_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); +static void e_minicard_label_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); static gboolean e_minicard_label_event (GnomeCanvasItem *item, GdkEvent *event); static void e_minicard_label_realize (GnomeCanvasItem *item); -static void e_minicard_label_unrealize (GnomeCanvasItem *item); -static void e_minicard_label_reflow(GnomeCanvasItem *item, int flags); +static void e_minicard_label_reflow (GnomeCanvasItem *item, gint flags); +static void e_minicard_label_style_set (EMinicardLabel *label, GtkStyle *previous_style); -static void e_minicard_label_resize_children( EMinicardLabel *e_minicard_label ); +static void e_minicard_label_resize_children (EMinicardLabel *e_minicard_label); -static GnomeCanvasGroupClass *parent_class = NULL; +static void set_colors (EMinicardLabel *label); -/* The arguments we take */ enum { - ARG_0, - ARG_WIDTH, - ARG_HEIGHT, - ARG_HAS_FOCUS, - ARG_FIELD, - ARG_FIELDNAME, - ARG_TEXT_MODEL, - ARG_MAX_FIELD_NAME_WIDTH, - ARG_EDITABLE + PROP_0, + PROP_WIDTH, + PROP_HEIGHT, + PROP_HAS_FOCUS, + PROP_FIELD, + PROP_FIELDNAME, + PROP_TEXT_MODEL, + PROP_MAX_FIELD_NAME_WIDTH, + PROP_EDITABLE }; -GtkType -e_minicard_label_get_type (void) -{ - static GtkType minicard_label_type = 0; - - if (!minicard_label_type) - { - static const GtkTypeInfo minicard_label_info = - { - "EMinicardLabel", - sizeof (EMinicardLabel), - sizeof (EMinicardLabelClass), - (GtkClassInitFunc) e_minicard_label_class_init, - (GtkObjectInitFunc) e_minicard_label_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - minicard_label_type = gtk_type_unique (gnome_canvas_group_get_type (), &minicard_label_info); - } - - return minicard_label_type; -} +enum { + STYLE_SET, + LAST_SIGNAL +}; + +static guint e_minicard_label_signals[LAST_SIGNAL] = {0, }; + +G_DEFINE_TYPE ( + EMinicardLabel, + e_minicard_label, + GNOME_TYPE_CANVAS_GROUP) static void -e_minicard_label_class_init (EMinicardLabelClass *klass) +e_minicard_label_class_init (EMinicardLabelClass *class) { - GtkObjectClass *object_class; - GnomeCanvasItemClass *item_class; - - object_class = (GtkObjectClass*) klass; - item_class = (GnomeCanvasItemClass *) klass; - - parent_class = gtk_type_class (gnome_canvas_group_get_type ()); - - gtk_object_add_arg_type ("EMinicardLabel::width", GTK_TYPE_DOUBLE, - GTK_ARG_READWRITE, ARG_WIDTH); - gtk_object_add_arg_type ("EMinicardLabel::height", GTK_TYPE_DOUBLE, - GTK_ARG_READABLE, ARG_HEIGHT); - gtk_object_add_arg_type ("EMinicardLabel::has_focus", GTK_TYPE_BOOL, - GTK_ARG_READWRITE, ARG_HAS_FOCUS); - gtk_object_add_arg_type ("EMinicardLabel::field", GTK_TYPE_STRING, - GTK_ARG_READWRITE, ARG_FIELD); - gtk_object_add_arg_type ("EMinicardLabel::fieldname", GTK_TYPE_STRING, - GTK_ARG_READWRITE, ARG_FIELDNAME); - gtk_object_add_arg_type ("EMinicardLabel::text_model", GTK_TYPE_OBJECT, - GTK_ARG_READWRITE, ARG_TEXT_MODEL); - gtk_object_add_arg_type ("EMinicardLabel::max_field_name_length", GTK_TYPE_DOUBLE, - GTK_ARG_READWRITE, ARG_MAX_FIELD_NAME_WIDTH); - gtk_object_add_arg_type ("EMinicardLabel::editable", GTK_TYPE_BOOL, - GTK_ARG_READWRITE, ARG_EDITABLE); - - object_class->set_arg = e_minicard_label_set_arg; - object_class->get_arg = e_minicard_label_get_arg; - /* object_class->destroy = e_minicard_label_destroy; */ - - /* GnomeCanvasItem method overrides */ - item_class->realize = e_minicard_label_realize; - item_class->unrealize = e_minicard_label_unrealize; - item_class->event = e_minicard_label_event; + GObjectClass *object_class; + GnomeCanvasItemClass *item_class; + + object_class = G_OBJECT_CLASS (class); + item_class = (GnomeCanvasItemClass *) class; + + class->style_set = e_minicard_label_style_set; + + object_class->set_property = e_minicard_label_set_property; + object_class->get_property = e_minicard_label_get_property; + + g_object_class_install_property ( + object_class, + PROP_WIDTH, + g_param_spec_double ( + "width", + "Width", + NULL, + 0.0, G_MAXDOUBLE, 10.0, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_HEIGHT, + g_param_spec_double ( + "height", + "Height", + NULL, + 0.0, G_MAXDOUBLE, 10.0, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_HAS_FOCUS, + g_param_spec_boolean ( + "has_focus", + "Has Focus", + NULL, + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_FIELD, + g_param_spec_string ( + "field", + "Field", + NULL, + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_FIELDNAME, + g_param_spec_string ( + "fieldname", + "Field Name", + NULL, + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_TEXT_MODEL, + g_param_spec_object ( + "text_model", + "Text Model", + NULL, + E_TYPE_TEXT_MODEL, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_MAX_FIELD_NAME_WIDTH, + g_param_spec_double ( + "max_field_name_length", + "Max field name length", + NULL, + -1.0, G_MAXDOUBLE, -1.0, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_EDITABLE, + g_param_spec_boolean ( + "editable", + "Editable", + NULL, + FALSE, + G_PARAM_READWRITE)); + + e_minicard_label_signals[STYLE_SET] = g_signal_new ( + "style_set", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMinicardLabelClass, style_set), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + GTK_TYPE_STYLE); + + /* GnomeCanvasItem method overrides */ + item_class->realize = e_minicard_label_realize; + item_class->event = e_minicard_label_event; } static void e_minicard_label_init (EMinicardLabel *minicard_label) { - minicard_label->width = 10; - minicard_label->height = 10; - minicard_label->rect = NULL; - minicard_label->fieldname = NULL; - minicard_label->field = NULL; + minicard_label->width = 10; + minicard_label->height = 10; + minicard_label->rect = NULL; + minicard_label->fieldname = NULL; + minicard_label->field = NULL; - minicard_label->max_field_name_length = -1; + minicard_label->max_field_name_length = -1; - e_canvas_item_set_reflow_callback(GNOME_CANVAS_ITEM(minicard_label), e_minicard_label_reflow); + e_canvas_item_set_reflow_callback ( + GNOME_CANVAS_ITEM (minicard_label), + e_minicard_label_reflow); } static void -e_minicard_label_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) +e_minicard_label_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - GnomeCanvasItem *item; EMinicardLabel *e_minicard_label; + GnomeCanvasItem *item; + + e_minicard_label = E_MINICARD_LABEL (object); + item = GNOME_CANVAS_ITEM (object); - item = GNOME_CANVAS_ITEM (o); - e_minicard_label = E_MINICARD_LABEL (o); - - switch (arg_id){ - case ARG_WIDTH: - e_minicard_label->width = GTK_VALUE_DOUBLE (*arg); - e_minicard_label_resize_children(e_minicard_label); + switch (property_id) { + case PROP_WIDTH: + e_minicard_label->width = g_value_get_double (value); + e_minicard_label_resize_children (e_minicard_label); e_canvas_item_request_reflow (item); break; - case ARG_HAS_FOCUS: - if (e_minicard_label->field && (GTK_VALUE_ENUM(*arg) != E_FOCUS_NONE)) - e_canvas_item_grab_focus(e_minicard_label->field, FALSE); + case PROP_HAS_FOCUS: + if (e_minicard_label->field && (g_value_get_boolean (value) != E_FOCUS_NONE)) + e_canvas_item_grab_focus (e_minicard_label->field, FALSE); break; - case ARG_FIELD: - gnome_canvas_item_set( e_minicard_label->field, "text", GTK_VALUE_STRING (*arg), NULL ); + case PROP_FIELD: + gnome_canvas_item_set (e_minicard_label->field, "text", g_value_get_string (value), NULL); break; - case ARG_FIELDNAME: - gnome_canvas_item_set( e_minicard_label->fieldname, "text", GTK_VALUE_STRING (*arg), NULL ); + case PROP_FIELDNAME: + gnome_canvas_item_set (e_minicard_label->fieldname, "text", g_value_get_string (value), NULL); break; - case ARG_TEXT_MODEL: - gnome_canvas_item_set( e_minicard_label->field, "model", GTK_VALUE_OBJECT (*arg), NULL); + case PROP_TEXT_MODEL: + gnome_canvas_item_set (e_minicard_label->field, "model", g_value_get_object (value), NULL); break; - case ARG_MAX_FIELD_NAME_WIDTH: - e_minicard_label->max_field_name_length = GTK_VALUE_DOUBLE (*arg); + case PROP_MAX_FIELD_NAME_WIDTH: + e_minicard_label->max_field_name_length = g_value_get_double (value); break; - case ARG_EDITABLE: - e_minicard_label->editable = GTK_VALUE_BOOL (*arg); - gtk_object_set (GTK_OBJECT (e_minicard_label->field), "editable", e_minicard_label->editable, NULL); + case PROP_EDITABLE: + e_minicard_label->editable = g_value_get_boolean (value); + g_object_set (e_minicard_label->field, "editable", FALSE /* e_minicard_label->editable */, NULL); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void -e_minicard_label_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +e_minicard_label_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { EMinicardLabel *e_minicard_label; - char *temp; - ETextModel *tempmodel; e_minicard_label = E_MINICARD_LABEL (object); - switch (arg_id) { - case ARG_WIDTH: - GTK_VALUE_DOUBLE (*arg) = e_minicard_label->width; + switch (property_id) { + case PROP_WIDTH: + g_value_set_double (value, e_minicard_label->width); break; - case ARG_HEIGHT: - GTK_VALUE_DOUBLE (*arg) = e_minicard_label->height; + case PROP_HEIGHT: + g_value_set_double (value, e_minicard_label->height); break; - case ARG_HAS_FOCUS: - GTK_VALUE_ENUM (*arg) = e_minicard_label->has_focus ? E_FOCUS_CURRENT : E_FOCUS_NONE; + case PROP_HAS_FOCUS: + g_value_set_boolean (value, e_minicard_label->has_focus ? E_FOCUS_CURRENT : E_FOCUS_NONE); break; - case ARG_FIELD: - gtk_object_get( GTK_OBJECT( e_minicard_label->field ), "text", &temp, NULL ); - GTK_VALUE_STRING (*arg) = temp; + case PROP_FIELD: + g_object_get_property ( + G_OBJECT (e_minicard_label->field), + "text", value); break; - case ARG_FIELDNAME: - gtk_object_get( GTK_OBJECT( e_minicard_label->fieldname ), "text", &temp, NULL ); - GTK_VALUE_STRING (*arg) = temp; + case PROP_FIELDNAME: + g_object_get_property ( + G_OBJECT (e_minicard_label->fieldname), + "text", value); break; - case ARG_TEXT_MODEL: - gtk_object_get( GTK_OBJECT( e_minicard_label->field ), "model", &tempmodel, NULL ); - GTK_VALUE_OBJECT (*arg) = GTK_OBJECT(tempmodel); + case PROP_TEXT_MODEL: + g_object_get_property ( + G_OBJECT (e_minicard_label->field), + "model", value); break; - case ARG_MAX_FIELD_NAME_WIDTH: - GTK_VALUE_DOUBLE (*arg) = e_minicard_label->max_field_name_length; + case PROP_MAX_FIELD_NAME_WIDTH: + g_value_set_double (value, e_minicard_label->max_field_name_length); break; - case ARG_EDITABLE: - GTK_VALUE_BOOL (*arg) = e_minicard_label->editable; + case PROP_EDITABLE: + g_value_set_boolean (value, e_minicard_label->editable); break; default: - arg->type = GTK_TYPE_INVALID; + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } @@ -218,253 +288,241 @@ e_minicard_label_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) static void e_minicard_label_realize (GnomeCanvasItem *item) { - if (GNOME_CANVAS_ITEM_CLASS( parent_class )->realize) - (* GNOME_CANVAS_ITEM_CLASS( parent_class )->realize) (item); - - e_canvas_item_request_reflow(item); - - if (!item->canvas->aa) - { - } -} - -void -e_minicard_label_construct (GnomeCanvasItem *item) -{ EMinicardLabel *e_minicard_label; GnomeCanvasGroup *group; - GdkFont *font; - - font = ((GtkWidget *) item->canvas)->style->font; e_minicard_label = E_MINICARD_LABEL (item); - group = GNOME_CANVAS_GROUP( item ); - - e_minicard_label->rect = - gnome_canvas_item_new( group, - gnome_canvas_rect_get_type(), - "x1", (double) 0, - "y1", (double) 0, - "x2", (double) e_minicard_label->width - 1, - "y2", (double) e_minicard_label->height - 1, - "outline_color", NULL, - NULL ); - e_minicard_label->fieldname = - gnome_canvas_item_new( group, - e_text_get_type(), - "anchor", GTK_ANCHOR_NW, - "clip_width", (double) ( e_minicard_label->width / 2 - 4 ), - "clip", TRUE, - "use_ellipsis", TRUE, - "font_gdk", font, - "fill_color", "black", - "draw_background", FALSE, - NULL ); - e_canvas_item_move_absolute(e_minicard_label->fieldname, 2, 1); - - e_minicard_label->field = - gnome_canvas_item_new( group, - e_text_get_type(), - "anchor", GTK_ANCHOR_NW, - "clip_width", (double) ( ( e_minicard_label->width + 1 ) / 2 - 4 ), - "clip", TRUE, - "use_ellipsis", TRUE, - "font_gdk", font, - "fill_color", "black", - "editable", e_minicard_label->editable, - "draw_background", FALSE, - NULL ); - e_canvas_item_move_absolute(e_minicard_label->field, ( e_minicard_label->width / 2 + 2), 1); - - e_canvas_item_request_reflow(item); + group = GNOME_CANVAS_GROUP (item); + + GNOME_CANVAS_ITEM_CLASS (e_minicard_label_parent_class)->realize (item); + + e_canvas_item_request_reflow (item); + + e_minicard_label->rect = gnome_canvas_item_new ( + group, + gnome_canvas_rect_get_type (), + "x1", (gdouble) 0, + "y1", (gdouble) 0, + "x2", (gdouble) e_minicard_label->width - 1, + "y2", (gdouble) e_minicard_label->height - 1, + "outline_color", NULL, + NULL); + + e_minicard_label->fieldname = gnome_canvas_item_new ( + group, + e_text_get_type (), + "clip_width", (gdouble) (e_minicard_label->width / 2 - 4), + "clip", TRUE, + "use_ellipsis", TRUE, + "fill_color", "black", + "im_context", E_CANVAS (item->canvas)->im_context, + NULL); + + e_canvas_item_move_absolute (e_minicard_label->fieldname, 2, 1); + + e_minicard_label->field = gnome_canvas_item_new ( + group, + e_text_get_type (), + "clip_width", (gdouble) ((e_minicard_label->width + 1) / 2 - 4), + "clip", TRUE, + "use_ellipsis", TRUE, + "fill_color", "black", + "editable", FALSE, /* e_minicard_label->editable, */ + "im_context", E_CANVAS (item->canvas)->im_context, + NULL); + + e_canvas_item_move_absolute ( + e_minicard_label->field, + (e_minicard_label->width / 2 + 2), 1); + + set_colors (e_minicard_label); + + e_canvas_item_request_reflow (item); } -static void -e_minicard_label_unrealize (GnomeCanvasItem *item) +static gboolean +e_minicard_label_event (GnomeCanvasItem *item, + GdkEvent *event) { - EMinicardLabel *e_minicard_label; + EMinicardLabel *e_minicard_label; + + e_minicard_label = E_MINICARD_LABEL (item); - e_minicard_label = E_MINICARD_LABEL (item); + switch (event->type) { + case GDK_KEY_PRESS: + if (event->key.keyval == GDK_KEY_Escape) { + GnomeCanvasItem *parent; - if (!item->canvas->aa) - { - } + e_text_cancel_editing (E_TEXT (e_minicard_label->field)); - if (GNOME_CANVAS_ITEM_CLASS( parent_class )->unrealize) - (* GNOME_CANVAS_ITEM_CLASS( parent_class )->unrealize) (item); -} + parent = GNOME_CANVAS_ITEM (e_minicard_label)->parent; + if (parent) + e_canvas_item_grab_focus (parent, FALSE); + } + break; + case GDK_FOCUS_CHANGE: { + GdkEventFocus *focus_event = (GdkEventFocus *) event; -static gboolean -e_minicard_label_event (GnomeCanvasItem *item, GdkEvent *event) -{ - EMinicardLabel *e_minicard_label; - - e_minicard_label = E_MINICARD_LABEL (item); - - switch( event->type ) - { - case GDK_KEY_PRESS: - if (event->key.keyval == GDK_Escape) { - GnomeCanvasItem *parent; - - e_text_cancel_editing (E_TEXT (e_minicard_label->field)); - - parent = GNOME_CANVAS_ITEM (e_minicard_label)->parent; - if (parent) - e_canvas_item_grab_focus(parent, FALSE); - } - break; - case GDK_FOCUS_CHANGE: - { - GdkEventFocus *focus_event = (GdkEventFocus *) event; - if ( focus_event->in ) - { - gnome_canvas_item_set( e_minicard_label->rect, - "outline_color", "grey50", - "fill_color", "grey90", - NULL ); - e_minicard_label->has_focus = TRUE; - } - else - { - gnome_canvas_item_set( e_minicard_label->rect, - "outline_color", NULL, - "fill_color", NULL, - NULL ); - e_minicard_label->has_focus = FALSE; - } - } - break; - case GDK_BUTTON_PRESS: - case GDK_BUTTON_RELEASE: - case GDK_MOTION_NOTIFY: - case GDK_ENTER_NOTIFY: - case GDK_LEAVE_NOTIFY: { - gboolean return_val; -#if 0 - GnomeCanvasItem *field; - ArtPoint p; - double inv[6], affine[6]; - - field = e_minicard_label->field; - art_affine_identity (affine); - - if (field->xform != NULL) { - if (field->object.flags & GNOME_CANVAS_ITEM_AFFINE_FULL) { - art_affine_multiply (affine, affine, field->xform); - } else { - affine[4] += field->xform[0]; - affine[5] += field->xform[1]; - } - } - - art_affine_invert (inv, affine); - switch(event->type) { - case GDK_MOTION_NOTIFY: - p.x = event->motion.x; - p.y = event->motion.y; - art_affine_point (&p, &p, inv); - event->motion.x = p.x; - event->motion.y = p.y; - break; - case GDK_BUTTON_PRESS: - case GDK_BUTTON_RELEASE: - p.x = event->button.x; - p.y = event->button.y; - art_affine_point (&p, &p, inv); - event->button.x = p.x; - event->button.y = p.y; - break; - case GDK_ENTER_NOTIFY: - case GDK_LEAVE_NOTIFY: - p.x = event->crossing.x; - p.y = event->crossing.y; - art_affine_point (&p, &p, inv); - event->crossing.x = p.x; - event->crossing.y = p.y; - break; - default: - break; - } -#endif - gtk_signal_emit_by_name(GTK_OBJECT(e_minicard_label->field), "event", event, &return_val); - return return_val; - break; - } - default: - break; - } - - if (GNOME_CANVAS_ITEM_CLASS( parent_class )->event) - return (* GNOME_CANVAS_ITEM_CLASS( parent_class )->event) (item, event); - else - return 0; + e_minicard_label->has_focus = focus_event->in; + set_colors (e_minicard_label); + + g_object_set ( + e_minicard_label->field, + "handle_popup", e_minicard_label->has_focus, + NULL); + break; + } + case GDK_BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + case GDK_MOTION_NOTIFY: + case GDK_ENTER_NOTIFY: + case GDK_LEAVE_NOTIFY: { + gboolean return_val; + g_signal_emit_by_name (e_minicard_label->field, "event", event, &return_val); + return return_val; + } + default: + break; + } + + return GNOME_CANVAS_ITEM_CLASS (e_minicard_label_parent_class)-> + event (item, event); } static void -e_minicard_label_resize_children(EMinicardLabel *e_minicard_label) +e_minicard_label_resize_children (EMinicardLabel *e_minicard_label) { - double left_width; + gdouble left_width; + gdouble fieldnamewidth; + gdouble fieldwidth; + gboolean is_rtl = (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL); if (e_minicard_label->max_field_name_length != -1 && ((e_minicard_label->width / 2) - 4 > e_minicard_label->max_field_name_length)) left_width = e_minicard_label->max_field_name_length; else left_width = e_minicard_label->width / 2 - 4; - gnome_canvas_item_set( e_minicard_label->fieldname, - "clip_width", (double) ( left_width ), - NULL ); - gnome_canvas_item_set( e_minicard_label->field, - "clip_width", (double) ( e_minicard_label->width - 8 - left_width ), - NULL ); + fieldnamewidth = (gdouble) MAX (left_width, 0); + fieldwidth = (gdouble) MAX (e_minicard_label->width - 8 - left_width, 0); + gnome_canvas_item_set ( + e_minicard_label->fieldname, + "clip_width", is_rtl ? fieldwidth : fieldnamewidth, + NULL); + gnome_canvas_item_set ( + e_minicard_label->field, + "clip_width", is_rtl ? fieldnamewidth : fieldwidth, + NULL); } static void -e_minicard_label_reflow(GnomeCanvasItem *item, int flags) +set_colors (EMinicardLabel *label) { - EMinicardLabel *e_minicard_label = E_MINICARD_LABEL(item); - + GnomeCanvasItem *item = GNOME_CANVAS_ITEM (label); + + if ((item->flags & GNOME_CANVAS_ITEM_REALIZED)) { + GnomeCanvas *canvas; + GtkStyle *style; + + canvas = GNOME_CANVAS_ITEM (label)->canvas; + style = gtk_widget_get_style (GTK_WIDGET (canvas)); + + if (label->has_focus) { + gnome_canvas_item_set ( + label->rect, + "outline_color_gdk", &style->mid[GTK_STATE_SELECTED], + "fill_color_gdk", &style->bg[GTK_STATE_NORMAL], + NULL); + + gnome_canvas_item_set ( + label->field, + "fill_color_gdk", &style->text[GTK_STATE_NORMAL], + NULL); + + gnome_canvas_item_set ( + label->fieldname, + "fill_color_gdk", &style->text[GTK_STATE_NORMAL], + NULL); + } + else { + gnome_canvas_item_set ( + label->rect, + "outline_color_gdk", NULL, + "fill_color_gdk", NULL, + NULL); + + gnome_canvas_item_set ( + label->field, + "fill_color_gdk", &style->text[GTK_STATE_NORMAL], + NULL); + + gnome_canvas_item_set ( + label->fieldname, + "fill_color_gdk", &style->text[GTK_STATE_NORMAL], + NULL); + } + } +} + +static void +e_minicard_label_style_set (EMinicardLabel *label, + GtkStyle *previous_style) +{ + set_colors (label); +} + +static void +e_minicard_label_reflow (GnomeCanvasItem *item, + gint flags) +{ + EMinicardLabel *e_minicard_label = E_MINICARD_LABEL (item); + gint old_height; gdouble text_height; gdouble left_width; old_height = e_minicard_label->height; - gtk_object_get(GTK_OBJECT(e_minicard_label->fieldname), - "text_height", &text_height, - NULL); + g_object_get ( + e_minicard_label->fieldname, + "text_height", &text_height, + NULL); e_minicard_label->height = text_height; - - gtk_object_get(GTK_OBJECT(e_minicard_label->field), - "text_height", &text_height, - NULL); + g_object_get ( + e_minicard_label->field, + "text_height", &text_height, + NULL); if (e_minicard_label->height < text_height) e_minicard_label->height = text_height; e_minicard_label->height += 3; - gnome_canvas_item_set( e_minicard_label->rect, - "x2", (double) e_minicard_label->width - 1, - "y2", (double) e_minicard_label->height - 1, - NULL ); + gnome_canvas_item_set ( + e_minicard_label->rect, + "x2", (gdouble) e_minicard_label->width - 1, + "y2", (gdouble) e_minicard_label->height - 1, + NULL); + + gnome_canvas_item_set ( + e_minicard_label->fieldname, + "clip_height", (gdouble) e_minicard_label->height - 3, + NULL); if (e_minicard_label->max_field_name_length != -1 && ((e_minicard_label->width / 2) - 4 > e_minicard_label->max_field_name_length)) left_width = e_minicard_label->max_field_name_length; else left_width = e_minicard_label->width / 2 - 4; - e_canvas_item_move_absolute(e_minicard_label->field, left_width + 6, 1); + e_canvas_item_move_absolute (e_minicard_label->field, left_width + 6, 1); if (old_height != e_minicard_label->height) - e_canvas_item_request_parent_reflow(item); + e_canvas_item_request_parent_reflow (item); } GnomeCanvasItem * -e_minicard_label_new(GnomeCanvasGroup *parent) +e_minicard_label_new (GnomeCanvasGroup *parent) { - GnomeCanvasItem *item = gnome_canvas_item_new(parent, e_minicard_label_get_type(), NULL); - e_minicard_label_construct(item); - return item; + return gnome_canvas_item_new ( + parent, e_minicard_label_get_type (), NULL); } diff --git a/addressbook/gui/widgets/e-minicard-label.h b/addressbook/gui/widgets/e-minicard-label.h index 32792991a7..0cd9183e5f 100644 --- a/addressbook/gui/widgets/e-minicard-label.h +++ b/addressbook/gui/widgets/e-minicard-label.h @@ -1,32 +1,31 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* e-minicard-label.h - * Copyright (C) 2000 Ximian, Inc. - * Author: Chris Lahey <clahey@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. * * 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. + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. */ + #ifndef __E_MINICARD_LABEL_H__ #define __E_MINICARD_LABEL_H__ -#include <glib.h> -#include <libgnomeui/gnome-canvas.h> +#include <libgnomecanvas/libgnomecanvas.h> -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ +G_BEGIN_DECLS /* EMinicardLabel - A label doing focus with non-marching ants. * @@ -40,12 +39,11 @@ extern "C" { * fieldname string RW text in the fieldname label */ -#define E_MINICARD_LABEL_TYPE (e_minicard_label_get_type ()) -#define E_MINICARD_LABEL(obj) (GTK_CHECK_CAST ((obj), E_MINICARD_LABEL_TYPE, EMinicardLabel)) -#define E_MINICARD_LABEL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_MINICARD_LABEL_TYPE, EMiniCardLabelClass)) -#define E_IS_MINICARD_LABEL(obj) (GTK_CHECK_TYPE ((obj), E_MINICARD_LABEL_TYPE)) -#define E_IS_MINICARD_LABEL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_MINICARD_LABEL_TYPE)) - +#define E_TYPE_MINICARD_LABEL (e_minicard_label_get_type ()) +#define E_MINICARD_LABEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_MINICARD_LABEL, EMinicardLabel)) +#define E_MINICARD_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_MINICARD_LABEL, EMiniCardLabelClass)) +#define E_IS_MINICARD_LABEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_MINICARD_LABEL)) +#define E_IS_MINICARD_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_MINICARD_LABEL)) typedef struct _EMinicardLabel EMinicardLabel; typedef struct _EMinicardLabelClass EMinicardLabelClass; @@ -53,11 +51,11 @@ typedef struct _EMinicardLabelClass EMinicardLabelClass; struct _EMinicardLabel { GnomeCanvasGroup parent; - + /* item specific fields */ - double width; - double height; - double max_field_name_length; + gdouble width; + gdouble height; + gdouble max_field_name_length; guint editable : 1; GnomeCanvasItem *fieldname; GnomeCanvasItem *field; @@ -69,16 +67,14 @@ struct _EMinicardLabel struct _EMinicardLabelClass { GnomeCanvasGroupClass parent_class; -}; + void (* style_set) (EMinicardLabel *label, GtkStyle *previous_style); +}; -GtkType e_minicard_label_get_type (void); -GnomeCanvasItem *e_minicard_label_new(GnomeCanvasGroup *parent); +GType e_minicard_label_get_type (void); +GnomeCanvasItem *e_minicard_label_new (GnomeCanvasGroup *parent); void e_minicard_label_construct (GnomeCanvasItem *item); -#ifdef __cplusplus -} -#endif /* __cplusplus */ - +G_END_DECLS #endif /* __E_MINICARD_LABEL_H__ */ diff --git a/addressbook/gui/widgets/e-minicard-view-widget.c b/addressbook/gui/widgets/e-minicard-view-widget.c index 1f6e1bd26b..7ff63a1bd9 100644 --- a/addressbook/gui/widgets/e-minicard-view-widget.c +++ b/addressbook/gui/widgets/e-minicard-view-widget.c @@ -1,146 +1,194 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-minicard-view-widget.c - * Copyright (C) 2000 Ximian, Inc. - * Author: Chris Lahey <clahey@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. * * 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. + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. */ +#ifdef HAVE_CONFIG_H #include <config.h> +#endif -#include <gtk/gtksignal.h> -#include <gal/widgets/e-canvas-background.h> -#include <gal/widgets/e-canvas.h> +#include <gtk/gtk.h> +#include <glib/gi18n.h> -#include "e-minicard-view-widget.h" +#include <e-util/e-util.h> -static void e_minicard_view_widget_init (EMinicardViewWidget *widget); -static void e_minicard_view_widget_class_init (EMinicardViewWidgetClass *klass); -static void e_minicard_view_widget_set_arg (GtkObject *o, GtkArg *arg, guint arg_id); -static void e_minicard_view_widget_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); -static void e_minicard_view_widget_destroy (GtkObject *object); -static void e_minicard_view_widget_reflow (ECanvas *canvas); -static void e_minicard_view_widget_size_allocate (GtkWidget *widget, GtkAllocation *allocation); -static void e_minicard_view_widget_realize (GtkWidget *widget); +#include "e-minicard-view-widget.h" -static ECanvasClass *parent_class = NULL; +static void e_minicard_view_widget_set_property + (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void e_minicard_view_widget_get_property + (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); +static void e_minicard_view_widget_dispose (GObject *object); +static void e_minicard_view_widget_reflow (ECanvas *canvas); +static void e_minicard_view_widget_size_allocate + (GtkWidget *widget, + GtkAllocation *allocation); +static void e_minicard_view_widget_style_set + (GtkWidget *widget, + GtkStyle *previous_style); +static void e_minicard_view_widget_realize (GtkWidget *widget); +static gboolean e_minicard_view_widget_real_focus_in_event + (GtkWidget *widget, + GdkEventFocus *event); -/* The arguments we take */ enum { - ARG_0, - ARG_BOOK, - ARG_QUERY, - ARG_EDITABLE, - ARG_COLUMN_WIDTH + PROP_0, + PROP_CLIENT, + PROP_QUERY, + PROP_EDITABLE, + PROP_COLUMN_WIDTH }; enum { + CREATE_CONTACT, + CREATE_CONTACT_LIST, SELECTION_CHANGE, COLUMN_WIDTH_CHANGED, RIGHT_CLICK, LAST_SIGNAL }; -static guint signals [LAST_SIGNAL] = {0, }; +static guint signals[LAST_SIGNAL] = {0, }; -GtkType -e_minicard_view_widget_get_type (void) -{ - static GtkType type = 0; - - if (!type) - { - static const GtkTypeInfo info = - { - "EMinicardViewWidget", - sizeof (EMinicardViewWidget), - sizeof (EMinicardViewWidgetClass), - (GtkClassInitFunc) e_minicard_view_widget_class_init, - (GtkObjectInitFunc) e_minicard_view_widget_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - type = gtk_type_unique (e_canvas_get_type (), &info); - } - - return type; -} +G_DEFINE_TYPE ( + EMinicardViewWidget, + e_minicard_view_widget, + E_TYPE_CANVAS) static void -e_minicard_view_widget_class_init (EMinicardViewWidgetClass *klass) +e_minicard_view_widget_class_init (EMinicardViewWidgetClass *class) { - GtkObjectClass *object_class; + GObjectClass *object_class; GtkWidgetClass *widget_class; ECanvasClass *canvas_class; - object_class = (GtkObjectClass*) klass; - widget_class = GTK_WIDGET_CLASS (klass); - canvas_class = E_CANVAS_CLASS (klass); - - parent_class = gtk_type_class (e_canvas_get_type ()); - - gtk_object_add_arg_type ("EMinicardViewWidget::book", GTK_TYPE_OBJECT, - GTK_ARG_READWRITE, ARG_BOOK); - gtk_object_add_arg_type ("EMinicardViewWidget::query", GTK_TYPE_STRING, - GTK_ARG_READWRITE, ARG_QUERY); - gtk_object_add_arg_type ("EMinicardViewWidget::editable", GTK_TYPE_BOOL, - GTK_ARG_READWRITE, ARG_EDITABLE); - gtk_object_add_arg_type ("EMinicardViewWidget::column_width", GTK_TYPE_INT, - GTK_ARG_READWRITE, ARG_COLUMN_WIDTH); - - signals [SELECTION_CHANGE] = - gtk_signal_new ("selection_change", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EMinicardViewWidgetClass, selection_change), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - signals [COLUMN_WIDTH_CHANGED] = - gtk_signal_new ("column_width_changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EMinicardViewWidgetClass, column_width_changed), - e_marshal_NONE__DOUBLE, - GTK_TYPE_NONE, 1, GTK_TYPE_DOUBLE); - - signals [RIGHT_CLICK] = - gtk_signal_new ("right_click", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EMinicardViewWidgetClass, right_click), - gtk_marshal_INT__POINTER, - GTK_TYPE_INT, 1, GTK_TYPE_GDK_EVENT); - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); - - object_class->set_arg = e_minicard_view_widget_set_arg; - object_class->get_arg = e_minicard_view_widget_get_arg; - object_class->destroy = e_minicard_view_widget_destroy; - - widget_class->realize = e_minicard_view_widget_realize; - widget_class->size_allocate = e_minicard_view_widget_size_allocate; - - canvas_class->reflow = e_minicard_view_widget_reflow; + object_class = G_OBJECT_CLASS (class); + object_class->set_property = e_minicard_view_widget_set_property; + object_class->get_property = e_minicard_view_widget_get_property; + object_class->dispose = e_minicard_view_widget_dispose; - klass->selection_change = NULL; - klass->column_width_changed = NULL; - klass->right_click = NULL; + widget_class = GTK_WIDGET_CLASS (class); + widget_class->style_set = e_minicard_view_widget_style_set; + widget_class->realize = e_minicard_view_widget_realize; + widget_class->size_allocate = e_minicard_view_widget_size_allocate; + widget_class->focus_in_event = e_minicard_view_widget_real_focus_in_event; + + canvas_class = E_CANVAS_CLASS (class); + canvas_class->reflow = e_minicard_view_widget_reflow; + + class->selection_change = NULL; + class->column_width_changed = NULL; + class->right_click = NULL; + + g_object_class_install_property ( + object_class, + PROP_CLIENT, + g_param_spec_object ( + "client", + "EBookClient", + NULL, + E_TYPE_BOOK_CLIENT, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_QUERY, + g_param_spec_string ( + "query", + "Query", + NULL, + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_EDITABLE, + g_param_spec_boolean ( + "editable", + "Editable", + NULL, + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_COLUMN_WIDTH, + g_param_spec_double ( + "column_width", + "Column Width", + NULL, + 0.0, G_MAXDOUBLE, 225.0, + G_PARAM_READWRITE)); + + signals[CREATE_CONTACT] = g_signal_new ( + "create-contact", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardViewWidgetClass, create_contact), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[CREATE_CONTACT_LIST] = g_signal_new ( + "create-contact-list", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardViewWidgetClass, create_contact_list), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[SELECTION_CHANGE] = g_signal_new ( + "selection_change", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardViewWidgetClass, selection_change), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[COLUMN_WIDTH_CHANGED] = g_signal_new ( + "column_width_changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardViewWidgetClass, column_width_changed), + NULL, NULL, + g_cclosure_marshal_VOID__DOUBLE, + G_TYPE_NONE, 1, + G_TYPE_DOUBLE); + + signals[RIGHT_CLICK] = g_signal_new ( + "right_click", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardViewWidgetClass, right_click), + NULL, NULL, + e_marshal_INT__POINTER, + G_TYPE_INT, 1, + G_TYPE_POINTER); } static void @@ -148,205 +196,287 @@ e_minicard_view_widget_init (EMinicardViewWidget *view) { view->emv = NULL; - view->book = NULL; + view->book_client = NULL; view->query = NULL; view->editable = FALSE; - view->column_width = 150; + view->column_width = 225; } GtkWidget * e_minicard_view_widget_new (EAddressbookReflowAdapter *adapter) { - EMinicardViewWidget *widget = E_MINICARD_VIEW_WIDGET (gtk_type_new (e_minicard_view_widget_get_type ())); + EMinicardViewWidget *widget; + + widget = g_object_new (E_TYPE_MINICARD_VIEW_WIDGET, NULL); - widget->adapter = adapter; - gtk_object_ref (GTK_OBJECT (widget->adapter)); + widget->adapter = g_object_ref (adapter); return GTK_WIDGET (widget); } static void -e_minicard_view_widget_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) +e_minicard_view_widget_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { EMinicardViewWidget *emvw; - emvw = E_MINICARD_VIEW_WIDGET (o); + emvw = E_MINICARD_VIEW_WIDGET (object); - switch (arg_id){ - case ARG_BOOK: - if (emvw->book) - gtk_object_unref(GTK_OBJECT(emvw->book)); - if (GTK_VALUE_OBJECT (*arg)) { - emvw->book = E_BOOK(GTK_VALUE_OBJECT (*arg)); - if (emvw->book) - gtk_object_ref(GTK_OBJECT(emvw->book)); + switch (property_id) { + case PROP_CLIENT: + if (emvw->book_client) + g_object_unref (emvw->book_client); + if (g_value_get_object (value)) { + emvw->book_client = E_BOOK_CLIENT (g_value_get_object (value)); + if (emvw->book_client) + g_object_ref (emvw->book_client); } else - emvw->book = NULL; + emvw->book_client = NULL; if (emvw->emv) - gtk_object_set(GTK_OBJECT(emvw->emv), - "book", emvw->book, - NULL); + g_object_set ( + emvw->emv, + "client", emvw->book_client, + NULL); break; - case ARG_QUERY: - emvw->query = g_strdup(GTK_VALUE_STRING (*arg)); + case PROP_QUERY: + emvw->query = g_strdup (g_value_get_string (value)); if (emvw->emv) - gtk_object_set(GTK_OBJECT(emvw->emv), - "query", emvw->query, - NULL); + g_object_set ( + emvw->emv, + "query", emvw->query, + NULL); break; - case ARG_EDITABLE: - emvw->editable = GTK_VALUE_BOOL(*arg); + case PROP_EDITABLE: + emvw->editable = g_value_get_boolean (value); if (emvw->emv) - gtk_object_set (GTK_OBJECT(emvw->emv), - "editable", emvw->editable, - NULL); + g_object_set ( + emvw->emv, + "editable", emvw->editable, + NULL); break; - case ARG_COLUMN_WIDTH: - emvw->column_width = GTK_VALUE_INT (*arg); + case PROP_COLUMN_WIDTH: + emvw->column_width = g_value_get_double (value); if (emvw->emv) { - gtk_object_set (GTK_OBJECT(emvw->emv), - "column_width", (int) emvw->column_width, - NULL); + g_object_set ( + emvw->emv, + "column_width", emvw->column_width, + NULL); } break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; } } static void -e_minicard_view_widget_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +e_minicard_view_widget_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { EMinicardViewWidget *emvw; emvw = E_MINICARD_VIEW_WIDGET (object); - switch (arg_id) { - case ARG_BOOK: - GTK_VALUE_OBJECT (*arg) = GTK_OBJECT(emvw->book); + switch (property_id) { + case PROP_CLIENT: + g_value_set_object (value, emvw->book_client); break; - case ARG_QUERY: - GTK_VALUE_STRING (*arg) = g_strdup(emvw->query); + case PROP_QUERY: + g_value_set_string (value, emvw->query); break; - case ARG_EDITABLE: - GTK_VALUE_BOOL (*arg) = emvw->editable; + case PROP_EDITABLE: + g_value_set_boolean (value, emvw->editable); break; - case ARG_COLUMN_WIDTH: - GTK_VALUE_INT (*arg) = emvw->column_width; + case PROP_COLUMN_WIDTH: + g_value_set_double (value, emvw->column_width); break; default: - arg->type = GTK_TYPE_INVALID; + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void -e_minicard_view_widget_destroy (GtkObject *object) +e_minicard_view_widget_dispose (GObject *object) { - EMinicardViewWidget *view = E_MINICARD_VIEW_WIDGET(object); + EMinicardViewWidget *view = E_MINICARD_VIEW_WIDGET (object); - if (view->book) - gtk_object_unref(GTK_OBJECT(view->book)); - g_free(view->query); + if (view->book_client) { + g_object_unref (view->book_client); + view->book_client = NULL; + } + if (view->query) { + g_free (view->query); + view->query = NULL; + } - gtk_object_unref (GTK_OBJECT (view->adapter)); + if (view->adapter) { + g_object_unref (view->adapter); + view->adapter = NULL; + } - GTK_OBJECT_CLASS(parent_class)->destroy (object); + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_minicard_view_widget_parent_class)->dispose (object); } static void -selection_change (ESelectionModel *esm, EMinicardViewWidget *widget) +selection_change (ESelectionModel *esm, + EMinicardViewWidget *widget) { - gtk_signal_emit (GTK_OBJECT(widget), - signals [SELECTION_CHANGE]); + g_signal_emit (widget, signals[SELECTION_CHANGE], 0); } static void -column_width_changed (ESelectionModel *esm, double width, EMinicardViewWidget *widget) +selection_row_change (ESelectionModel *esm, + gint row, + EMinicardViewWidget *widget) { - gtk_signal_emit (GTK_OBJECT(widget), - signals [COLUMN_WIDTH_CHANGED], width); + selection_change (esm, widget); +} + +static void +column_width_changed (ESelectionModel *esm, + gdouble width, + EMinicardViewWidget *widget) +{ + g_signal_emit (widget, signals[COLUMN_WIDTH_CHANGED], 0, width); +} + +static void +create_contact (EMinicardView *view, + EMinicardViewWidget *widget) +{ + g_signal_emit (widget, signals[CREATE_CONTACT], 0); +} + +static void +create_contact_list (EMinicardView *view, + EMinicardViewWidget *widget) +{ + g_signal_emit (widget, signals[CREATE_CONTACT_LIST], 0); } static guint -right_click (EMinicardView *view, GdkEvent *event, EMinicardViewWidget *widget) +right_click (EMinicardView *view, + GdkEvent *event, + EMinicardViewWidget *widget) { guint ret_val; - gtk_signal_emit (GTK_OBJECT(widget), - signals [RIGHT_CLICK], - event, &ret_val); + + g_signal_emit (widget, signals[RIGHT_CLICK], 0, event, &ret_val); + return ret_val; } static void +e_minicard_view_widget_style_set (GtkWidget *widget, + GtkStyle *previous_style) +{ + EMinicardViewWidget *view = E_MINICARD_VIEW_WIDGET (widget); + GtkStyle *style; + + style = gtk_widget_get_style (widget); + + if (view->background) + gnome_canvas_item_set ( + view->background, "fill_color_gdk", + &style->base[GTK_STATE_NORMAL], NULL); + + GTK_WIDGET_CLASS (e_minicard_view_widget_parent_class)-> + style_set (widget, previous_style); +} + +static void e_minicard_view_widget_realize (GtkWidget *widget) { - EMinicardViewWidget *view = E_MINICARD_VIEW_WIDGET(widget); - - gnome_canvas_item_new(gnome_canvas_root( GNOME_CANVAS(view) ), - e_canvas_background_get_type(), - "fill_color", "white", - NULL ); - - view->emv = gnome_canvas_item_new( - gnome_canvas_root( GNOME_CANVAS(view) ), - e_minicard_view_get_type(), - "height", (double) 100, - "minimum_width", (double) 100, + EMinicardViewWidget *view = E_MINICARD_VIEW_WIDGET (widget); + GtkStyle *style = gtk_widget_get_style (widget); + + view->background = gnome_canvas_item_new ( + gnome_canvas_root (GNOME_CANVAS (view)), + e_canvas_background_get_type (), + "fill_color_gdk", &style->base[GTK_STATE_NORMAL], + NULL); + + view->emv = gnome_canvas_item_new ( + gnome_canvas_root (GNOME_CANVAS (view)), + e_minicard_view_get_type (), + "height", (gdouble) 100, + "minimum_width", (gdouble) 100, "adapter", view->adapter, - "column_width", (int) view->column_width, - NULL ); - - gtk_signal_connect (GTK_OBJECT (E_REFLOW(view->emv)->selection), - "selection_changed", - selection_change, view); - gtk_signal_connect (GTK_OBJECT (view->emv), - "column_width_changed", - column_width_changed, view); - gtk_signal_connect (GTK_OBJECT (view->emv), - "right_click", - GTK_SIGNAL_FUNC (right_click), view); - - if (GTK_WIDGET_CLASS(parent_class)->realize) - GTK_WIDGET_CLASS(parent_class)->realize (widget); + "column_width", view->column_width, + NULL); + + g_signal_connect ( + E_REFLOW (view->emv)->selection, + "selection_changed", + G_CALLBACK (selection_change), view); + g_signal_connect ( + E_REFLOW (view->emv)->selection, + "selection_row_changed", + G_CALLBACK (selection_row_change), view); + g_signal_connect ( + view->emv, "column_width_changed", + G_CALLBACK (column_width_changed), view); + g_signal_connect ( + view->emv, "create-contact", + G_CALLBACK (create_contact), view); + g_signal_connect ( + view->emv, "create-contact-list", + G_CALLBACK (create_contact_list), view); + g_signal_connect ( + view->emv, "right_click", + G_CALLBACK (right_click), view); + + GTK_WIDGET_CLASS (e_minicard_view_widget_parent_class)-> + realize (widget); } static void -e_minicard_view_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation) +e_minicard_view_widget_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) { - if (GTK_WIDGET_CLASS(parent_class)->size_allocate) - GTK_WIDGET_CLASS(parent_class)->size_allocate (widget, allocation); - - if (GTK_WIDGET_REALIZED(widget)) { - double width; - EMinicardViewWidget *view = E_MINICARD_VIEW_WIDGET(widget); - - gnome_canvas_item_set( view->emv, - "height", (double) allocation->height, - NULL ); - gnome_canvas_item_set( view->emv, - "minimum_width", (double) allocation->width, - NULL ); - gtk_object_get(GTK_OBJECT(view->emv), - "width", &width, - NULL); - width = MAX(width, allocation->width); - gnome_canvas_set_scroll_region (GNOME_CANVAS (view), 0, 0, width - 1, allocation->height - 1); + GTK_WIDGET_CLASS (e_minicard_view_widget_parent_class)-> + size_allocate (widget, allocation); + + if (gtk_widget_get_realized (widget)) { + gdouble width; + EMinicardViewWidget *view = E_MINICARD_VIEW_WIDGET (widget); + + gnome_canvas_item_set ( + view->emv, "height", + (gdouble) allocation->height, NULL); + gnome_canvas_item_set ( + view->emv, "minimum_width", + (gdouble) allocation->width, NULL); + g_object_get (view->emv, "width", &width, NULL); + width = MAX (width, allocation->width); + gnome_canvas_set_scroll_region ( + GNOME_CANVAS (view), 0, 0, + width - 1, allocation->height - 1); } } static void -e_minicard_view_widget_reflow(ECanvas *canvas) +e_minicard_view_widget_reflow (ECanvas *canvas) { - double width; - EMinicardViewWidget *view = E_MINICARD_VIEW_WIDGET(canvas); + gdouble width; + EMinicardViewWidget *view = E_MINICARD_VIEW_WIDGET (canvas); + GtkAllocation allocation; + + E_CANVAS_CLASS (e_minicard_view_widget_parent_class)->reflow (canvas); - if (E_CANVAS_CLASS(parent_class)->reflow) - E_CANVAS_CLASS(parent_class)->reflow (canvas); + g_object_get (view->emv, "width", &width, NULL); + gtk_widget_get_allocation (GTK_WIDGET (canvas), &allocation); - gtk_object_get(GTK_OBJECT(view->emv), - "width", &width, - NULL); - width = MAX(width, GTK_WIDGET(canvas)->allocation.width); - gnome_canvas_set_scroll_region(GNOME_CANVAS(canvas), 0, 0, width - 1, GTK_WIDGET(canvas)->allocation.height - 1); + gnome_canvas_set_scroll_region ( + GNOME_CANVAS (canvas), 0, 0, + MAX (width, allocation.width) - 1, + allocation.height - 1); } ESelectionModel * @@ -359,10 +489,35 @@ e_minicard_view_widget_get_selection_model (EMinicardViewWidget *view) } EMinicardView * -e_minicard_view_widget_get_view (EMinicardViewWidget *view) +e_minicard_view_widget_get_view (EMinicardViewWidget *view) { if (view->emv) return E_MINICARD_VIEW (view->emv); else return NULL; } + +static gboolean +e_minicard_view_widget_real_focus_in_event (GtkWidget *widget, + GdkEventFocus *event) +{ + GnomeCanvas *canvas; + EMinicardViewWidget *view; + + canvas = GNOME_CANVAS (widget); + view = E_MINICARD_VIEW_WIDGET (widget); + + if (!canvas->focused_item) { + EReflow *reflow = E_REFLOW (view->emv); + if (reflow->count) { + gint unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), 0); + + if (unsorted != -1) + canvas->focused_item = reflow->items[unsorted]; + } + } + + return GTK_WIDGET_CLASS (e_minicard_view_widget_parent_class)-> + focus_in_event (widget, event); +} + diff --git a/addressbook/gui/widgets/e-minicard-view-widget.h b/addressbook/gui/widgets/e-minicard-view-widget.h index c55bb6e636..71fe00a497 100644 --- a/addressbook/gui/widgets/e-minicard-view-widget.h +++ b/addressbook/gui/widgets/e-minicard-view-widget.h @@ -1,41 +1,41 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* e-minicard-view-widget.h - * Copyright (C) 2000 Ximian, Inc. - * Author: Chris Lahey <clahey@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. * * 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. + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. */ + #ifndef __E_MINICARD_VIEW_WIDGET_H__ #define __E_MINICARD_VIEW_WIDGET_H__ -#include <gal/widgets/e-canvas.h> -#include <gal/unicode/gunicode.h> -#include "addressbook/backend/ebook/e-book.h" -#include "e-minicard-view.h" +#include <libebook/libebook.h> -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ +#include <e-util/e-util.h> -#define E_MINICARD_VIEW_WIDGET_TYPE (e_minicard_view_widget_get_type ()) -#define E_MINICARD_VIEW_WIDGET(obj) (GTK_CHECK_CAST ((obj), E_MINICARD_VIEW_WIDGET_TYPE, EMinicardViewWidget)) -#define E_MINICARD_VIEW_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_MINICARD_VIEW_WIDGET_TYPE, EMinicardViewWidgetClass)) -#define E_IS_MINICARD_VIEW_WIDGET(obj) (GTK_CHECK_TYPE ((obj), E_MINICARD_VIEW_WIDGET_TYPE)) -#define E_IS_MINICARD_VIEW_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_MINICARD_VIEW_WIDGET_TYPE)) +#include "e-minicard-view.h" +G_BEGIN_DECLS + +#define E_TYPE_MINICARD_VIEW_WIDGET (e_minicard_view_widget_get_type ()) +#define E_MINICARD_VIEW_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_MINICARD_VIEW_WIDGET, EMinicardViewWidget)) +#define E_MINICARD_VIEW_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_MINICARD_VIEW_WIDGET, EMinicardViewWidgetClass)) +#define E_IS_MINICARD_VIEW_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_MINICARD_VIEW_WIDGET)) +#define E_IS_MINICARD_VIEW_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_MINICARD_VIEW_WIDGET)) typedef struct _EMinicardViewWidget EMinicardViewWidget; typedef struct _EMinicardViewWidgetClass EMinicardViewWidgetClass; @@ -44,35 +44,35 @@ struct _EMinicardViewWidget { ECanvas parent; + GnomeCanvasItem *background; GnomeCanvasItem *emv; EAddressbookReflowAdapter *adapter; - EBook *book; - char *query; + EBookClient *book_client; + gchar *query; guint editable : 1; - double column_width; + gdouble column_width; }; struct _EMinicardViewWidgetClass { ECanvasClass parent_class; + void (*create_contact) (EMinicardViewWidget *emvw); + void (*create_contact_list) (EMinicardViewWidget *emvw); void (*selection_change) (EMinicardViewWidget *emvw); void (*column_width_changed) (EMinicardViewWidget *emvw, double width); guint (*right_click) (EMinicardViewWidget *emvw); }; - -GtkType e_minicard_view_widget_get_type (void); +GType e_minicard_view_widget_get_type (void); GtkWidget *e_minicard_view_widget_new (EAddressbookReflowAdapter *adapter); /* Get parts of the view widget. */ ESelectionModel *e_minicard_view_widget_get_selection_model (EMinicardViewWidget *view); EMinicardView *e_minicard_view_widget_get_view (EMinicardViewWidget *view); -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS #endif /* __E_MINICARD_VIEW_WIDGET_H__ */ diff --git a/addressbook/gui/widgets/e-minicard-view.c b/addressbook/gui/widgets/e-minicard-view.c index 6b596bb754..1a35f3aa09 100644 --- a/addressbook/gui/widgets/e-minicard-view.c +++ b/addressbook/gui/widgets/e-minicard-view.c @@ -1,123 +1,158 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-minicard-view.c - * Copyright (C) 2000 Ximian, Inc. - * Author: Chris Lahey <clahey@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. * * 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. + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. */ +#ifdef HAVE_CONFIG_H #include <config.h> +#endif #include "e-minicard-view.h" -#include "e-addressbook-util.h" +#include <string.h> + +#include <gtk/gtk.h> +#include <glib/gi18n.h> +#include <gdk/gdkkeysyms.h> -#include <gtk/gtkselection.h> -#include <gtk/gtkdnd.h> -#include <gal/widgets/e-canvas.h> -#include <gal/widgets/e-unicode.h> -#include <libgnome/gnome-i18n.h> +#include "e-util/e-util.h" -static void e_minicard_view_drag_data_get(GtkWidget *widget, +#include "eab-gui-util.h" +#include "util/eab-book-util.h" + +#include "ea-addressbook.h" + +static void e_minicard_view_drag_data_get (GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data, guint info, guint time, EMinicardView *view); -static EReflowClass *parent_class = NULL; -#define PARENT_TYPE (E_REFLOW_TYPE) - -/* The arguments we take */ enum { - ARG_0, - ARG_ADAPTER, - ARG_BOOK, - ARG_QUERY, - ARG_EDITABLE + PROP_0, + PROP_ADAPTER, + PROP_CLIENT, + PROP_QUERY, + PROP_EDITABLE }; - enum { + CREATE_CONTACT, + CREATE_CONTACT_LIST, RIGHT_CLICK, LAST_SIGNAL }; -static guint signals [LAST_SIGNAL] = {0, }; +static guint signals[LAST_SIGNAL] = {0, }; enum DndTargetType { DND_TARGET_TYPE_VCARD_LIST, + DND_TARGET_TYPE_SOURCE_VCARD_LIST }; #define VCARD_LIST_TYPE "text/x-vcard" +#define SOURCE_VCARD_LIST_TYPE "text/x-source-vcard" static GtkTargetEntry drag_types[] = { - { VCARD_LIST_TYPE, 0, DND_TARGET_TYPE_VCARD_LIST } + { (gchar *) SOURCE_VCARD_LIST_TYPE, 0, DND_TARGET_TYPE_SOURCE_VCARD_LIST }, + { (gchar *) VCARD_LIST_TYPE, 0, DND_TARGET_TYPE_VCARD_LIST } }; -static gint num_drag_types = sizeof(drag_types) / sizeof(drag_types[0]); + +G_DEFINE_TYPE (EMinicardView, e_minicard_view, E_TYPE_REFLOW) static void -e_minicard_view_drag_data_get(GtkWidget *widget, - GdkDragContext *context, - GtkSelectionData *selection_data, - guint info, - guint time, - EMinicardView *view) +e_minicard_view_drag_data_get (GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time, + EMinicardView *view) { - if (!E_IS_MINICARD_VIEW(view)) + GdkAtom target; + + if (!E_IS_MINICARD_VIEW (view)) return; + target = gtk_selection_data_get_target (selection_data); + switch (info) { case DND_TARGET_TYPE_VCARD_LIST: { - char *value; - - value = e_card_list_get_vcard(view->drag_list); - - gtk_selection_data_set (selection_data, - selection_data->target, - 8, - value, strlen (value)); + gchar *value; + + value = eab_contact_list_to_string (view->drag_list); + + gtk_selection_data_set ( + selection_data, target, 8, + (guchar *) value, strlen (value)); + g_free (value); + break; + } + case DND_TARGET_TYPE_SOURCE_VCARD_LIST: { + EBookClient *book_client = NULL; + gchar *value; + + g_object_get (view->adapter, "book_client", &book_client, NULL); + value = eab_book_and_contact_list_to_string (book_client, view->drag_list); + + gtk_selection_data_set ( + selection_data, target, 8, + (guchar *) value, strlen (value)); + + g_object_unref (book_client); + g_free (value); break; } } +} - g_list_foreach (view->drag_list, (GFunc)gtk_object_unref, NULL); - g_list_free (view->drag_list); +static void +clear_drag_data (EMinicardView *view) +{ + g_slist_free_full (view->drag_list, (GDestroyNotify) g_object_unref); view->drag_list = NULL; } -static int -e_minicard_view_drag_begin (EAddressbookReflowAdapter *adapter, GdkEvent *event, EMinicardView *view) +static gint +e_minicard_view_drag_begin (EAddressbookReflowAdapter *adapter, + GdkEvent *event, + EMinicardView *view) { GdkDragContext *context; GtkTargetList *target_list; GdkDragAction actions = GDK_ACTION_MOVE | GDK_ACTION_COPY; - + + clear_drag_data (view); + view->drag_list = e_minicard_view_get_card_list (view); - g_print ("dragging %d card(s)\n", g_list_length (view->drag_list)); + g_print ("dragging %d card(s)\n", g_slist_length (view->drag_list)); - target_list = gtk_target_list_new (drag_types, num_drag_types); + target_list = gtk_target_list_new (drag_types, G_N_ELEMENTS (drag_types)); - context = gtk_drag_begin (GTK_WIDGET (GNOME_CANVAS_ITEM (view)->canvas), - target_list, actions, 1/*XXX*/, event); + context = gtk_drag_begin ( + GTK_WIDGET (GNOME_CANVAS_ITEM (view)->canvas), + target_list, actions, 1/*XXX */, event); if (!view->canvas_drag_data_get_id) - view->canvas_drag_data_get_id = gtk_signal_connect (GTK_OBJECT (GNOME_CANVAS_ITEM (view)->canvas), - "drag_data_get", - GTK_SIGNAL_FUNC (e_minicard_view_drag_data_get), - view); + view->canvas_drag_data_get_id = g_signal_connect ( + GNOME_CANVAS_ITEM (view)->canvas, "drag_data_get", + G_CALLBACK (e_minicard_view_drag_data_get), view); gtk_drag_set_icon_default (context); @@ -127,30 +162,64 @@ e_minicard_view_drag_begin (EAddressbookReflowAdapter *adapter, GdkEvent *event, static void set_empty_message (EMinicardView *view) { - char *empty_message; - gboolean editable = FALSE; + gchar *empty_message; + gboolean editable = FALSE, perform_initial_query = FALSE, searching = FALSE; if (view->adapter) { - gtk_object_get (GTK_OBJECT (view->adapter), - "editable", &editable, - NULL); + EAddressbookModel *model = NULL; + EBookClient *book_client = NULL; + + g_object_get ( + view->adapter, + "editable", &editable, + "model", &model, + "client", &book_client, + NULL); + + if (book_client && !e_client_check_capability (E_CLIENT (book_client), "do-initial-query")) + perform_initial_query = TRUE; + + searching = model && e_addressbook_model_can_stop (model); + + if (book_client) + g_object_unref (book_client); + if (model) + g_object_unref (model); } - if (editable) - empty_message = e_utf8_from_locale_string(_("\n\nThere are no items to show in this view.\n\n" - "Double-click here to create a new Contact.")); - else - empty_message = e_utf8_from_locale_string(_("\n\nThere are no items to show in this view.")); + if (searching) { + empty_message = _("\n\nSearching for the Contacts..."); + } else if (editable) { + if (perform_initial_query) + empty_message = _("\n\nSearch for the Contact\n\n" + "or double-click here to create a new Contact."); + else + empty_message = _("\n\nThere are no items to show in this view.\n\n" + "Double-click here to create a new Contact."); + } else { + if (perform_initial_query) + empty_message = _("\n\nSearch for the Contact."); + else + empty_message = _("\n\nThere are no items to show in this view."); + } - gtk_object_set (GTK_OBJECT(view), - "empty_message", empty_message, - NULL); + g_object_set ( + view, + "empty_message", empty_message, + NULL); +} - g_free (empty_message); +static void +writable_status_change (EAddressbookModel *model, + gboolean writable, + EMinicardView *view) +{ + set_empty_message (view); } static void -writable_status_change (EAddressbookModel *model, gboolean writable, EMinicardView *view) +stop_state_changed (EAddressbookModel *model, + EMinicardView *view) { set_empty_message (view); } @@ -160,169 +229,206 @@ adapter_changed (EMinicardView *view) { set_empty_message (view); - gtk_signal_connect (GTK_OBJECT (view->adapter), "drag_begin", - GTK_SIGNAL_FUNC (e_minicard_view_drag_begin), view); + g_signal_connect ( + view->adapter, "drag_begin", + G_CALLBACK (e_minicard_view_drag_begin), view); } static void -e_minicard_view_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) +e_minicard_view_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - GnomeCanvasItem *item; EMinicardView *view; - item = GNOME_CANVAS_ITEM (o); - view = E_MINICARD_VIEW (o); - - switch (arg_id){ - case ARG_ADAPTER: + view = E_MINICARD_VIEW (object); + + switch (property_id) { + case PROP_ADAPTER: if (view->adapter) { - if (view->writable_status_id) { + if (view->writable_status_id || view->stop_state_id) { EAddressbookModel *model; - gtk_object_get (GTK_OBJECT (view->adapter), - "model", &model, - NULL); + g_object_get ( + view->adapter, + "model", &model, + NULL); if (model) { - gtk_signal_disconnect (GTK_OBJECT (model), view->writable_status_id); + if (view->writable_status_id) + g_signal_handler_disconnect (model, view->writable_status_id); + if (view->stop_state_id) + g_signal_handler_disconnect (model, view->stop_state_id); } } - gtk_object_unref (GTK_OBJECT(view->adapter)); + g_object_unref (view->adapter); } view->writable_status_id = 0; - view->adapter = GTK_VALUE_POINTER (*arg); - gtk_object_ref (GTK_OBJECT (view->adapter)); + view->stop_state_id = 0; + view->adapter = g_value_get_object (value); + g_object_ref (view->adapter); adapter_changed (view); - gtk_object_set (GTK_OBJECT (view), - "model", view->adapter, - NULL); + g_object_set ( + view, + "model", view->adapter, + NULL); if (view->adapter) { EAddressbookModel *model; - gtk_object_get (GTK_OBJECT (view->adapter), - "model", &model, - NULL); + g_object_get ( + view->adapter, + "model", &model, + NULL); if (model) { - view->writable_status_id = - gtk_signal_connect (GTK_OBJECT (model), "writable_status", - GTK_SIGNAL_FUNC (writable_status_change), view); + view->writable_status_id = g_signal_connect ( + model, "writable_status", + G_CALLBACK (writable_status_change), view); + view->stop_state_id = g_signal_connect ( + model, "stop_state_changed", + G_CALLBACK (stop_state_changed), view); } - + } break; - case ARG_BOOK: - gtk_object_set (GTK_OBJECT (view->adapter), - "book", GTK_VALUE_OBJECT (*arg), - NULL); + case PROP_CLIENT: + g_object_set ( + view->adapter, + "client", g_value_get_object (value), + NULL); set_empty_message (view); break; - case ARG_QUERY: - gtk_object_set (GTK_OBJECT (view->adapter), - "query", GTK_VALUE_STRING (*arg), - NULL); + case PROP_QUERY: + g_object_set ( + view->adapter, + "query", g_value_get_string (value), + NULL); break; - case ARG_EDITABLE: - gtk_object_set (GTK_OBJECT (view->adapter), - "editable", GTK_VALUE_BOOL (*arg), - NULL); + case PROP_EDITABLE: + g_object_set ( + view->adapter, + "editable", g_value_get_boolean (value), + NULL); set_empty_message (view); break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; } } static void -e_minicard_view_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +e_minicard_view_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { EMinicardView *view; view = E_MINICARD_VIEW (object); - switch (arg_id) { - case ARG_ADAPTER: - GTK_VALUE_POINTER (*arg) = view->adapter; + switch (property_id) { + case PROP_ADAPTER: + g_value_set_object (value, view->adapter); break; - case ARG_BOOK: - gtk_object_get (GTK_OBJECT (view->adapter), - "book", >K_VALUE_OBJECT (*arg), - NULL); + case PROP_CLIENT: + g_object_get_property ( + G_OBJECT (view->adapter), + "client", value); break; - case ARG_QUERY: - gtk_object_get (GTK_OBJECT (view->adapter), - "query", >K_VALUE_STRING (*arg), - NULL); + case PROP_QUERY: + g_object_get_property ( + G_OBJECT (view->adapter), + "query", value); break; - case ARG_EDITABLE: - gtk_object_get (GTK_OBJECT (view->adapter), - "editable", >K_VALUE_BOOL (*arg), - NULL); + case PROP_EDITABLE: + g_object_get_property ( + G_OBJECT (view->adapter), + "editable", value); break; default: - arg->type = GTK_TYPE_INVALID; + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void -e_minicard_view_destroy (GtkObject *object) +e_minicard_view_dispose (GObject *object) { - EMinicardView *view = E_MINICARD_VIEW(object); + EMinicardView *view = E_MINICARD_VIEW (object); + + clear_drag_data (view); if (view->canvas_drag_data_get_id) { - gtk_signal_disconnect (GTK_OBJECT (GNOME_CANVAS_ITEM (view)->canvas), - view->canvas_drag_data_get_id); + g_signal_handler_disconnect ( + GNOME_CANVAS_ITEM (view)->canvas, + view->canvas_drag_data_get_id); + view->canvas_drag_data_get_id = 0; } if (view->adapter) { - if (view->writable_status_id) { + if (view->writable_status_id || view->stop_state_id) { EAddressbookModel *model; - gtk_object_get (GTK_OBJECT (view->adapter), - "model", &model, - NULL); + g_object_get ( + view->adapter, + "model", &model, + NULL); if (model) { - gtk_signal_disconnect (GTK_OBJECT (model), view->writable_status_id); + if (view->writable_status_id) + g_signal_handler_disconnect (model, view->writable_status_id); + if (view->stop_state_id) + g_signal_handler_disconnect (model, view->stop_state_id); } } - gtk_object_unref (GTK_OBJECT(view->adapter)); + g_object_unref (view->adapter); } view->writable_status_id = 0; + view->stop_state_id = 0; view->adapter = NULL; - GTK_OBJECT_CLASS(parent_class)->destroy (object); + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_minicard_view_parent_class)->dispose (object); } static guint -e_minicard_view_right_click (EMinicardView *view, GdkEvent *event) +e_minicard_view_right_click (EMinicardView *view, + GdkEvent *event) { guint ret_val = 0; - gtk_signal_emit (GTK_OBJECT (view), signals[RIGHT_CLICK], - event, &ret_val); + g_signal_emit ( + view, signals[RIGHT_CLICK], 0, + event, &ret_val); return ret_val; } static gboolean -e_minicard_view_event (GnomeCanvasItem *item, GdkEvent *event) +e_minicard_view_event (GnomeCanvasItem *item, + GdkEvent *event) { EMinicardView *view; - + guint event_button = 0; + view = E_MINICARD_VIEW (item); - switch( event->type ) { + switch (event->type) { case GDK_2BUTTON_PRESS: - if (((GdkEventButton *)event)->button == 1) { + gdk_event_get_button (event, &event_button); + if (event_button == 1) { gboolean editable; - gtk_object_get(GTK_OBJECT(view->adapter), "editable", &editable, NULL); - - if (editable) { - EBook *book; - gtk_object_get(GTK_OBJECT(view), "book", &book, NULL); - - if (book && E_IS_BOOK (book)) - e_addressbook_show_contact_editor (book, e_card_new(""), TRUE, editable); - } + g_object_get (view->adapter, "editable", &editable, NULL); + + if (editable) + e_minicard_view_create_contact (view); return TRUE; } case GDK_BUTTON_PRESS: - if (event->button.button == 3) { + gdk_event_get_button (event, &event_button); + if (event_button == 3) + e_minicard_view_right_click (view, event); + break; + case GDK_KEY_PRESS: + if (event->key.keyval & GDK_SHIFT_MASK && + event->key.keyval == GDK_KEY_F10) { e_minicard_view_right_click (view, event); } break; @@ -330,30 +436,29 @@ e_minicard_view_event (GnomeCanvasItem *item, GdkEvent *event) break; } - if (GNOME_CANVAS_ITEM_CLASS(parent_class)->event) - return GNOME_CANVAS_ITEM_CLASS(parent_class)->event(item, event); - else - return FALSE; + return GNOME_CANVAS_ITEM_CLASS (e_minicard_view_parent_class)-> + event (item, event); } static gint -e_minicard_view_selection_event (EReflow *reflow, GnomeCanvasItem *item, GdkEvent *event) +e_minicard_view_selection_event (EReflow *reflow, + GnomeCanvasItem *item, + GdkEvent *event) { EMinicardView *view; - int return_val = FALSE; + gint return_val = FALSE; view = E_MINICARD_VIEW (reflow); - if (parent_class->selection_event) { - return_val = parent_class->selection_event (reflow, item, event); - } + return_val = E_REFLOW_CLASS (e_minicard_view_parent_class)-> + selection_event (reflow, item, event); switch (event->type) { case GDK_FOCUS_CHANGE: if (event->focus_change.in) { - int i; + gint i; for (i = 0; i < reflow->count; i++) { if (reflow->items[i] == item) { - e_selection_model_maybe_do_something(reflow->selection, i, 0, 0); + e_selection_model_maybe_do_something (reflow->selection, i, 0, 0); break; } } @@ -363,7 +468,7 @@ e_minicard_view_selection_event (EReflow *reflow, GnomeCanvasItem *item, GdkEven if (event->button.button == 3) { return_val = e_minicard_view_right_click (view, event); if (!return_val) - e_selection_model_right_click_up(reflow->selection); + e_selection_model_right_click_up (reflow->selection); } break; default: @@ -372,176 +477,139 @@ e_minicard_view_selection_event (EReflow *reflow, GnomeCanvasItem *item, GdkEven return return_val; } -typedef struct { - EMinicardView *view; - EBookCallback cb; - gpointer closure; -} ViewCbClosure; - -static void -do_remove (int i, gpointer user_data) -{ - EBook *book; - ECard *card; - ViewCbClosure *viewcbclosure = user_data; - EMinicardView *view = viewcbclosure->view; - EBookCallback cb = viewcbclosure->cb; - gpointer closure = viewcbclosure->closure; - - gtk_object_get (GTK_OBJECT(view->adapter), - "book", &book, - NULL); - - card = e_addressbook_reflow_adapter_get_card (view->adapter, i); - - e_book_remove_card(book, card, cb, closure); - - gtk_object_unref (GTK_OBJECT (card)); -} - -#if 0 -static int -compare_to_utf_str (EMinicard *card, const char *utf_str) -{ - g_return_val_if_fail(card != NULL, 0); - g_return_val_if_fail(E_IS_MINICARD(card), 0); - - if (g_unichar_isdigit (g_utf8_get_char (utf_str))) { - return 1; - } - - if (card->card) { - char *file_as; - gtk_object_get(GTK_OBJECT(card->card), - "file_as", &file_as, - NULL); - if (file_as) - return g_utf8_strcasecmp (file_as, utf_str); - else - return 0; - } else { - return 0; - } -} -#endif - static void -e_minicard_view_class_init (EMinicardViewClass *klass) +e_minicard_view_class_init (EMinicardViewClass *class) { - GtkObjectClass *object_class; + GObjectClass *object_class; GnomeCanvasItemClass *item_class; EReflowClass *reflow_class; - - object_class = (GtkObjectClass*) klass; - item_class = (GnomeCanvasItemClass *) klass; - reflow_class = (EReflowClass *) klass; - - parent_class = gtk_type_class (PARENT_TYPE); - - gtk_object_add_arg_type ("EMinicardView::adapter", GTK_TYPE_OBJECT, - GTK_ARG_READWRITE, ARG_ADAPTER); - gtk_object_add_arg_type ("EMinicardView::book", GTK_TYPE_OBJECT, - GTK_ARG_READWRITE, ARG_BOOK); - gtk_object_add_arg_type ("EMinicardView::query", GTK_TYPE_STRING, - GTK_ARG_READWRITE, ARG_QUERY); - gtk_object_add_arg_type ("EMinicardView::editable", GTK_TYPE_BOOL, - GTK_ARG_READWRITE, ARG_EDITABLE); - - signals [RIGHT_CLICK] = - gtk_signal_new ("right_click", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EMinicardViewClass, right_click), - gtk_marshal_INT__POINTER, - GTK_TYPE_INT, 1, GTK_TYPE_GDK_EVENT); - - gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); - - object_class->set_arg = e_minicard_view_set_arg; - object_class->get_arg = e_minicard_view_get_arg; - object_class->destroy = e_minicard_view_destroy; + + object_class = G_OBJECT_CLASS (class); + item_class = (GnomeCanvasItemClass *) class; + reflow_class = (EReflowClass *) class; + + object_class->set_property = e_minicard_view_set_property; + object_class->get_property = e_minicard_view_get_property; + object_class->dispose = e_minicard_view_dispose; + + g_object_class_install_property ( + object_class, + PROP_ADAPTER, + g_param_spec_object ( + "adapter", + "Adapter", + NULL, + E_TYPE_ADDRESSBOOK_REFLOW_ADAPTER, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_CLIENT, + g_param_spec_object ( + "client", + "EBookClient", + NULL, + E_TYPE_BOOK_CLIENT, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_QUERY, + g_param_spec_string ( + "query", + "Query", + NULL, + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_EDITABLE, + g_param_spec_boolean ( + "editable", + "Editable", + NULL, + FALSE, + G_PARAM_READWRITE)); + + signals[CREATE_CONTACT] = g_signal_new ( + "create-contact", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[CREATE_CONTACT_LIST] = g_signal_new ( + "create-contact-list", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[RIGHT_CLICK] = g_signal_new ( + "right_click", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardViewClass, right_click), + NULL, NULL, + e_marshal_INT__POINTER, + G_TYPE_INT, 1, + G_TYPE_POINTER); item_class->event = e_minicard_view_event; reflow_class->selection_event = e_minicard_view_selection_event; /* GnomeCanvasItem method overrides */ + + /* init the accessibility support for e_minicard_view */ + e_minicard_view_a11y_init (); } static void e_minicard_view_init (EMinicardView *view) { + view->drag_list = NULL; view->adapter = NULL; view->canvas_drag_data_get_id = 0; view->writable_status_id = 0; + view->stop_state_id = 0; set_empty_message (view); } -GtkType -e_minicard_view_get_type (void) -{ - static GtkType reflow_type = 0; - - if (!reflow_type) { - static const GtkTypeInfo reflow_info = { - "EMinicardView", - sizeof (EMinicardView), - sizeof (EMinicardViewClass), - (GtkClassInitFunc) e_minicard_view_class_init, - (GtkObjectInitFunc) e_minicard_view_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - reflow_type = gtk_type_unique (PARENT_TYPE, &reflow_info); - } - - return reflow_type; -} - -void -e_minicard_view_remove_selection(EMinicardView *view, - EBookCallback cb, - gpointer closure) -{ - ViewCbClosure viewcbclosure; - viewcbclosure.view = view; - viewcbclosure.cb = cb; - viewcbclosure.closure = closure; - - e_selection_model_foreach (E_REFLOW (view)->selection, - do_remove, - &viewcbclosure); -} - void e_minicard_view_jump_to_letter (EMinicardView *view, gunichar letter) { #if 0 - char uft_str[6 + 1]; + gchar uft_str[6 + 1]; - utf_str [g_unichar_to_utf8 (letter, utf_str)] = '\0'; - e_reflow_sorted_jump (E_REFLOW_SORTED (view), - (GCompareFunc) compare_to_utf_str, - utf_str); + utf_str[g_unichar_to_utf8 (letter, utf_str)] = '\0'; + e_reflow_sorted_jump ( + E_REFLOW_SORTED (view), + (GCompareFunc) compare_to_utf_str, + utf_str); #endif } typedef struct { - GList *list; + GSList *list; EAddressbookReflowAdapter *adapter; } ModelAndList; static void -add_to_list (int index, gpointer closure) +add_to_list (gint index, + gpointer closure) { ModelAndList *mal = closure; - mal->list = g_list_prepend (mal->list, e_addressbook_reflow_adapter_get_card (mal->adapter, index)); + mal->list = g_slist_prepend ( + mal->list, e_addressbook_reflow_adapter_get_contact ( + mal->adapter, index)); } -GList * +GSList * e_minicard_view_get_card_list (EMinicardView *view) { ModelAndList mal; @@ -551,6 +619,21 @@ e_minicard_view_get_card_list (EMinicardView *view) e_selection_model_foreach (E_REFLOW (view)->selection, add_to_list, &mal); - mal.list = g_list_reverse (mal.list); - return mal.list; + return g_slist_reverse (mal.list); +} + +void +e_minicard_view_create_contact (EMinicardView *view) +{ + g_return_if_fail (E_IS_MINICARD_VIEW (view)); + + g_signal_emit (view, signals[CREATE_CONTACT], 0); +} + +void +e_minicard_view_create_contact_list (EMinicardView *view) +{ + g_return_if_fail (E_IS_MINICARD_VIEW (view)); + + g_signal_emit (view, signals[CREATE_CONTACT_LIST], 0); } diff --git a/addressbook/gui/widgets/e-minicard-view.h b/addressbook/gui/widgets/e-minicard-view.h index 1f23c62754..bf116e4513 100644 --- a/addressbook/gui/widgets/e-minicard-view.h +++ b/addressbook/gui/widgets/e-minicard-view.h @@ -1,37 +1,36 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* e-minicard-view.h - * Copyright (C) 2000 Ximian, Inc. - * Author: Chris Lahey <clahey@ximian.com> +/* * - * This library is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. * * 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. + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. */ + #ifndef __E_MINICARD_VIEW_H__ #define __E_MINICARD_VIEW_H__ #include "e-minicard.h" -#include <gal/widgets/e-reflow.h> -#include <gal/widgets/e-selection-model-simple.h> -#include <gal/unicode/gunicode.h> -#include "addressbook/backend/ebook/e-book.h" +#include <e-util/e-util.h> + #include "e-addressbook-reflow-adapter.h" -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ +G_BEGIN_DECLS /* EMinicardView - A canvas item container. * @@ -52,12 +51,11 @@ extern "C" { * height double RW height of the reflow */ -#define E_MINICARD_VIEW_TYPE (e_minicard_view_get_type ()) -#define E_MINICARD_VIEW(obj) (GTK_CHECK_CAST ((obj), E_MINICARD_VIEW_TYPE, EMinicardView)) -#define E_MINICARD_VIEW_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_MINICARD_VIEW_TYPE, EMinicardViewClass)) -#define E_IS_MINICARD_VIEW(obj) (GTK_CHECK_TYPE ((obj), E_MINICARD_VIEW_TYPE)) -#define E_IS_MINICARD_VIEW_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_MINICARD_VIEW_TYPE)) - +#define E_TYPE_MINICARD_VIEW (e_minicard_view_get_type ()) +#define E_MINICARD_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_MINICARD_VIEW, EMinicardView)) +#define E_MINICARD_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_MINICARD_VIEW, EMinicardViewClass)) +#define E_IS_MINICARD_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_MINICARD_VIEW)) +#define E_IS_MINICARD_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_MINICARD_VIEW)) typedef struct _EMinicardView EMinicardView; typedef struct _EMinicardViewClass EMinicardViewClass; @@ -67,14 +65,14 @@ struct _EMinicardView EReflow parent; EAddressbookReflowAdapter *adapter; - + /* item specific fields */ - GList *drag_list; + GSList *drag_list; guint canvas_drag_data_get_id; - guint writable_status_id; + guint stop_state_id; }; struct _EMinicardViewClass @@ -84,17 +82,13 @@ struct _EMinicardViewClass void (*right_click) (EMinicardView *view, GdkEvent *event); }; -GtkType e_minicard_view_get_type (void); -void e_minicard_view_remove_selection (EMinicardView *view, - EBookCallback cb, - gpointer closure); +GType e_minicard_view_get_type (void); void e_minicard_view_jump_to_letter (EMinicardView *view, gunichar letter); -GList *e_minicard_view_get_card_list (EMinicardView *view); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ +GSList *e_minicard_view_get_card_list (EMinicardView *view); +void e_minicard_view_create_contact (EMinicardView *view); +void e_minicard_view_create_contact_list (EMinicardView *view); +G_END_DECLS #endif /* __E_MINICARD_VIEW_H__ */ diff --git a/addressbook/gui/widgets/e-minicard-widget-test.c b/addressbook/gui/widgets/e-minicard-widget-test.c deleted file mode 100644 index 04ef2f0823..0000000000 --- a/addressbook/gui/widgets/e-minicard-widget-test.c +++ /dev/null @@ -1,119 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* test-minicard.c - * - * Copyright (C) 2000 Ximian, Inc. - * Author: Chris Lahey <clahey@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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. - * - */ - -#define TEST_VCARD \ -"BEGIN:VCARD -" \ -"FN:Nat -" \ -"N:Friedman;Nat;D;Mr. -" \ -"ORG:Ximian, Inc. -" \ -"TITLE:Head Geek -" \ -"ROLE:Programmer/Executive -" \ -"BDAY:1977-08-06 -" \ -"TEL;WORK:617 679 1984 -" \ -"TEL;CELL:123 456 7890 -" \ -"EMAIL;INTERNET:nat@nat.org -" \ -"EMAIL;INTERNET:nat@ximian.com -" \ -"ADR;WORK;POSTAL:P.O. Box 101;;;Any Town;CA;91921-1234; -" \ -"ADR;HOME;POSTAL;INTL:P.O. Box 202;;;Any Town 2;MI;12344-4321;USA -" \ -"END:VCARD -" \ -" -" - -#include "config.h" -#include <gtk/gtkmain.h> -#include <libgnomeui/gnome-app.h> -#include <libgnomeui/gnome-init.h> -#include "e-minicard-widget.h" - -/* This is a horrible thing to do, but it is just a test. */ - -static void destroy_callback(GtkWidget *app, gpointer data) -{ - exit(0); -} - -#if 0 -static void about_callback( GtkWidget *widget, gpointer data ) -{ - - const gchar *authors[] = - { - "Christopher James Lahey <clahey@umich.edu>", - NULL - }; - - GtkWidget *about = - gnome_about_new ( _( "Minicard Widget Test" ), VERSION, - _( "Copyright (C) 2000, Ximian, Inc." ), - authors, - _( "This should test the minicard widget" ), - NULL); - gtk_widget_show (about); -} -#endif - -int main( int argc, char *argv[] ) -{ - GtkWidget *app; - GtkWidget *minicard; - ECard *card; - - /* bindtextdomain (PACKAGE, GNOMELOCALEDIR); - textdomain (PACKAGE);*/ - - gnome_init( "Minicard Widget Test", VERSION, argc, argv); - app = gnome_app_new("Minicard Widget Test", NULL); - - minicard = e_minicard_widget_new(); - card = e_card_new(TEST_VCARD); - gtk_object_set(GTK_OBJECT(minicard), - "card", card, - NULL); - - gnome_app_set_contents( GNOME_APP( app ), minicard ); - - /* Connect the signals */ - gtk_signal_connect( GTK_OBJECT( app ), "destroy", - GTK_SIGNAL_FUNC( destroy_callback ), - ( gpointer ) app ); - - gtk_widget_show_all( app ); - - gtk_main(); - - /* Not reached. */ - return 0; -} diff --git a/addressbook/gui/widgets/e-minicard-widget.c b/addressbook/gui/widgets/e-minicard-widget.c deleted file mode 100644 index 566a43b087..0000000000 --- a/addressbook/gui/widgets/e-minicard-widget.c +++ /dev/null @@ -1,249 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-table-field-chooser.c - * Copyright (C) 2000 Ximian, Inc. - * Author: Chris Lahey <clahey@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <config.h> -#include <libgnomeui/gnome-canvas-rect-ellipse.h> -#include "e-minicard-widget.h" -#include "e-minicard.h" - -static void e_minicard_widget_init (EMinicardWidget *card); -static void e_minicard_widget_class_init (EMinicardWidgetClass *klass); -static void e_minicard_widget_set_arg (GtkObject *o, GtkArg *arg, guint arg_id); -static void e_minicard_widget_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); -static void e_minicard_widget_destroy (GtkObject *object); -static void e_minicard_widget_size_request (GtkWidget *widget, GtkRequisition *requisition); -static void e_minicard_widget_size_allocate (GtkWidget *widget, GtkAllocation *allocation); -static void e_minicard_widget_reflow (ECanvas *canvas); - -static ECanvasClass *parent_class = NULL; - -/* The arguments we take */ -enum { - ARG_0, - ARG_CARD, -}; - -GtkType -e_minicard_widget_get_type (void) -{ - static GtkType type = 0; - - if (!type) - { - static const GtkTypeInfo info = - { - "EMinicardWidget", - sizeof (EMinicardWidget), - sizeof (EMinicardWidgetClass), - (GtkClassInitFunc) e_minicard_widget_class_init, - (GtkObjectInitFunc) e_minicard_widget_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - type = gtk_type_unique (e_canvas_get_type (), &info); - } - - return type; -} - -static void -e_minicard_widget_class_init (EMinicardWidgetClass *klass) -{ - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - ECanvasClass *ecanvas_class; - - object_class = GTK_OBJECT_CLASS(klass); - widget_class = GTK_WIDGET_CLASS(klass); - ecanvas_class = E_CANVAS_CLASS(klass); - - parent_class = gtk_type_class (e_canvas_get_type ()); - - object_class->set_arg = e_minicard_widget_set_arg; - object_class->get_arg = e_minicard_widget_get_arg; - object_class->destroy = e_minicard_widget_destroy; - - widget_class->size_request = e_minicard_widget_size_request; - widget_class->size_allocate = e_minicard_widget_size_allocate; - - ecanvas_class->reflow = e_minicard_widget_reflow; - - gtk_object_add_arg_type ("EMinicardWidget::card", GTK_TYPE_OBJECT, - GTK_ARG_READWRITE, ARG_CARD); -} - -static void -e_minicard_widget_size_request(GtkWidget *widget, GtkRequisition *requisition) -{ - double height; - EMinicardWidget *emw = E_MINICARD_WIDGET(widget); - gtk_object_get(GTK_OBJECT(emw->item), - "height", &height, - NULL); - if (height <= 0) - height = 1; - widget->requisition.height = height; - widget->requisition.width = 200; - requisition->height = height; - requisition->width = 200; -} - -static void -e_minicard_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation) -{ - double height; - EMinicardWidget *emw = E_MINICARD_WIDGET(widget); - gnome_canvas_item_set( emw->item, - "width", (double) allocation->width, - NULL ); - gtk_object_get(GTK_OBJECT(emw->item), - "height", &height, - NULL); - height = MAX(height, allocation->height); - gnome_canvas_set_scroll_region(GNOME_CANVAS( emw ), 0, 0, allocation->width - 1, height - 1); - gnome_canvas_item_set( emw->rect, - "x2", (double) allocation->width, - "y2", (double) height, - NULL ); - if (GTK_WIDGET_CLASS(parent_class)->size_allocate) - GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, allocation); -} - -static void e_minicard_widget_reflow(ECanvas *canvas) -{ - double height; - EMinicardWidget *emw = E_MINICARD_WIDGET(canvas); - gtk_object_get(GTK_OBJECT(emw->item), - "height", &height, - NULL); - - height = MAX(height, GTK_WIDGET(emw)->allocation.height); - - gnome_canvas_set_scroll_region (GNOME_CANVAS(emw), 0, 0, GTK_WIDGET(emw)->allocation.width - 1, height - 1); - gnome_canvas_item_set( emw->rect, - "x2", (double) GTK_WIDGET(emw)->allocation.width, - "y2", (double) height, - NULL ); - - gtk_widget_queue_resize(GTK_WIDGET(canvas)); -} - -static void -e_minicard_widget_init (EMinicardWidget *emw) -{ - emw->rect = gnome_canvas_item_new(gnome_canvas_root(GNOME_CANVAS(emw)), - gnome_canvas_rect_get_type(), - "x1", (double) 0, - "y1", (double) 0, - "x2", (double) 100, - "y2", (double) 100, - "fill_color", "white", - NULL ); - - emw->item = gnome_canvas_item_new(gnome_canvas_root(GNOME_CANVAS(emw)), - e_minicard_get_type(), - "width", (double) 100, - NULL ); - - gnome_canvas_set_scroll_region ( GNOME_CANVAS( emw ), - 0, 0, - 100, 100 ); - - emw->card = NULL; -} - -static void -e_minicard_widget_destroy (GtkObject *object) -{ - EMinicardWidget *emw = E_MINICARD_WIDGET(object); - - if (emw->card) - gtk_object_unref(GTK_OBJECT(emw->card)); - - if (GTK_OBJECT_CLASS(parent_class)->destroy) - GTK_OBJECT_CLASS(parent_class)->destroy(object); -} - -GtkWidget* -e_minicard_widget_new (void) -{ - GtkWidget *widget = GTK_WIDGET (gtk_type_new (e_minicard_widget_get_type ())); - return widget; -} - -static void -e_minicard_widget_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) -{ - EMinicardWidget *emw = E_MINICARD_WIDGET(object); - gpointer ptr; - - switch (arg_id){ - case ARG_CARD: - ptr = GTK_VALUE_POINTER (*arg); - e_minicard_widget_set_card (emw, ptr ? E_CARD (ptr) : NULL); - break; - default: - break; - } -} - -static void -e_minicard_widget_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) -{ - EMinicardWidget *emw = E_MINICARD_WIDGET(object); - - switch (arg_id) { - case ARG_CARD: - if (emw->card) - GTK_VALUE_OBJECT (*arg) = GTK_OBJECT(emw->card); - else - GTK_VALUE_OBJECT (*arg) = NULL; - break; - default: - arg->type = GTK_TYPE_INVALID; - break; - } -} - -void -e_minicard_widget_set_card (EMinicardWidget *emw, ECard *card) -{ - g_return_if_fail (emw && E_IS_MINICARD_WIDGET (emw)); - g_return_if_fail (card == NULL || E_IS_CARD (card)); - - if (card != emw->card) { - - if (emw->card) - gtk_object_unref (GTK_OBJECT (emw->card)); - - emw->card = card; - - if (emw->card) - gtk_object_ref (GTK_OBJECT (emw->card)); - - if (emw->item) - gtk_object_set (GTK_OBJECT (emw->item), - "card", emw->card, - NULL); - } -} diff --git a/addressbook/gui/widgets/e-minicard-widget.h b/addressbook/gui/widgets/e-minicard-widget.h deleted file mode 100644 index eaf0f8edb6..0000000000 --- a/addressbook/gui/widgets/e-minicard-widget.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* e-minicard-widget.h - * Copyright (C) 2000 Ximian, Inc. - * Author: Chris Lahey <clahey@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#ifndef __E_MINICARD_WIDGET_H__ -#define __E_MINICARD_WIDGET_H__ - -#include <gal/widgets/e-canvas.h> -#include "addressbook/backend/ebook/e-card.h" - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -/* EMinicardWidget - A card displaying information about a contact. - * - * The following arguments are available: - * - * name type read/write description - * -------------------------------------------------------------------------------- - */ - -#define E_MINICARD_WIDGET_TYPE (e_minicard_widget_get_type ()) -#define E_MINICARD_WIDGET(obj) (GTK_CHECK_CAST ((obj), E_MINICARD_WIDGET_TYPE, EMinicardWidget)) -#define E_MINICARD_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_MINICARD_WIDGET_TYPE, EMinicardWidgetClass)) -#define E_IS_MINICARD_WIDGET(obj) (GTK_CHECK_TYPE ((obj), E_MINICARD_WIDGET_TYPE)) -#define E_IS_MINICARD_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_MINICARD_WIDGET_TYPE)) - - -typedef struct _EMinicardWidget EMinicardWidget; -typedef struct _EMinicardWidgetClass EMinicardWidgetClass; - -struct _EMinicardWidget -{ - ECanvas parent; - - /* item specific fields */ - GnomeCanvasItem *item; - - GnomeCanvasItem *rect; - ECard *card; -}; - -struct _EMinicardWidgetClass -{ - ECanvasClass parent_class; -}; - - -GtkWidget *e_minicard_widget_new(void); -GtkType e_minicard_widget_get_type (void); - -void e_minicard_widget_set_card (EMinicardWidget *, ECard *); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -#endif /* __E_MINICARD_WIDGET_H__ */ diff --git a/addressbook/gui/widgets/e-minicard.c b/addressbook/gui/widgets/e-minicard.c index 99e1d524fa..d5a1a3ce99 100644 --- a/addressbook/gui/widgets/e-minicard.c +++ b/addressbook/gui/widgets/e-minicard.c @@ -1,189 +1,243 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * e-minicard.c - * Copyright (C) 2000 Ximian, Inc. - * Author: Chris Lahey <clahey@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. * * 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. + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. */ +#ifdef HAVE_CONFIG_H #include <config.h> -#include <glib.h> -#include <gtk/gtkdnd.h> -#include <gdk/gdkkeysyms.h> -#include <libgnome/gnome-defs.h> -#include <libgnome/gnome-i18n.h> -#include <libgnomeui/gnome-canvas-rect-ellipse.h> -#include <gdk-pixbuf/gnome-canvas-pixbuf.h> -#include <gal/e-text/e-text.h> -#include <gal/util/e-util.h> -#include <gal/widgets/e-canvas-utils.h> -#include <gal/widgets/e-canvas.h> -#include <gal/unicode/gunicode.h> -#include "addressbook/backend/ebook/e-book.h" -#include "e-addressbook-util.h" +#endif + #include "e-minicard.h" + +#include <string.h> +#include <glib/gi18n.h> +#include <gdk/gdkkeysyms.h> + +#include <libgnomecanvas/libgnomecanvas.h> + +#include "e-util/e-util.h" + +#include "eab-book-util.h" +#include "eab-gui-util.h" #include "e-minicard-label.h" #include "e-minicard-view.h" -#include "e-contact-editor.h" -#include "e-card-merging.h" - -static void e_minicard_init (EMinicard *card); -static void e_minicard_class_init (EMinicardClass *klass); -static void e_minicard_set_arg (GtkObject *o, GtkArg *arg, guint arg_id); -static void e_minicard_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); -static void e_minicard_destroy (GtkObject *object); -static void e_minicard_finalize (GtkObject *object); +#include "ea-addressbook.h" + +static void e_minicard_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); +static void e_minicard_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); +static void e_minicard_dispose (GObject *object); +static void e_minicard_finalize (GObject *object); static gboolean e_minicard_event (GnomeCanvasItem *item, GdkEvent *event); static void e_minicard_realize (GnomeCanvasItem *item); -static void e_minicard_unrealize (GnomeCanvasItem *item); -static void e_minicard_reflow ( GnomeCanvasItem *item, int flags ); +static void e_minicard_reflow (GnomeCanvasItem *item, gint flags); +static void e_minicard_style_set (EMinicard *minicard, GtkStyle *previous_style); -static void e_minicard_resize_children( EMinicard *e_minicard ); -static void remodel( EMinicard *e_minicard ); +static void e_minicard_resize_children (EMinicard *e_minicard); +static void remodel (EMinicard *e_minicard); static gint e_minicard_drag_begin (EMinicard *minicard, GdkEvent *event); -static GnomeCanvasGroupClass *parent_class = NULL; - -typedef struct _EMinicardField EMinicardField; - -struct _EMinicardField { - ECardSimpleField field; - GnomeCanvasItem *label; -}; - #define d(x) -#define LIST_ICON_FILENAME "contact-list-16.png" - -#define E_MINICARD_FIELD(field) ((EMinicardField *)(field)) +#define LIST_ICON_NAME "stock_contact-list" static void -e_minicard_field_destroy(EMinicardField *field) +e_minicard_field_destroy (EMinicardField *field) { - gtk_object_destroy(GTK_OBJECT(field->label)); - g_free(field); + g_object_run_dispose (G_OBJECT (field->label)); + g_free (field); } -/* The arguments we take */ enum { - ARG_0, - ARG_WIDTH, - ARG_HEIGHT, - ARG_HAS_FOCUS, - ARG_SELECTED, - ARG_HAS_CURSOR, - ARG_EDITABLE, - ARG_CARD + PROP_0, + PROP_WIDTH, + PROP_HEIGHT, + PROP_HAS_FOCUS, + PROP_SELECTED, + PROP_HAS_CURSOR, + PROP_EDITABLE, + PROP_CONTACT }; enum { SELECTED, DRAG_BEGIN, + OPEN_CONTACT, + STYLE_SET, LAST_SIGNAL }; -static guint e_minicard_signals [LAST_SIGNAL] = {0, }; - -GtkType -e_minicard_get_type (void) -{ - static GtkType minicard_type = 0; - - if (!minicard_type) - { - static const GtkTypeInfo minicard_info = - { - "EMinicard", - sizeof (EMinicard), - sizeof (EMinicardClass), - (GtkClassInitFunc) e_minicard_class_init, - (GtkObjectInitFunc) e_minicard_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - minicard_type = gtk_type_unique (gnome_canvas_group_get_type (), &minicard_info); - } - - return minicard_type; +static struct { + const gchar *name; + const gchar *pretty_name; } +common_location[] = +{ + { "WORK", N_ ("Work Email") }, + { "HOME", N_ ("Home Email") }, + { "OTHER", N_ ("Other Email") } +}; + +static guint signals[LAST_SIGNAL] = {0, }; + +G_DEFINE_TYPE (EMinicard, e_minicard, GNOME_TYPE_CANVAS_GROUP) static void -e_minicard_class_init (EMinicardClass *klass) +e_minicard_class_init (EMinicardClass *class) { - GtkObjectClass *object_class; + GObjectClass *object_class; GnomeCanvasItemClass *item_class; - object_class = (GtkObjectClass*) klass; - item_class = (GnomeCanvasItemClass *) klass; - - parent_class = gtk_type_class (gnome_canvas_group_get_type ()); - - gtk_object_add_arg_type ("EMinicard::width", GTK_TYPE_DOUBLE, - GTK_ARG_READWRITE, ARG_WIDTH); - gtk_object_add_arg_type ("EMinicard::height", GTK_TYPE_DOUBLE, - GTK_ARG_READABLE, ARG_HEIGHT); - gtk_object_add_arg_type ("EMinicard::has_focus", GTK_TYPE_ENUM, - GTK_ARG_READWRITE, ARG_HAS_FOCUS); - gtk_object_add_arg_type ("EMinicard::selected", GTK_TYPE_BOOL, - GTK_ARG_READWRITE, ARG_SELECTED); - gtk_object_add_arg_type ("EMinicard::has_cursor", GTK_TYPE_BOOL, - GTK_ARG_READWRITE, ARG_HAS_CURSOR); - gtk_object_add_arg_type ("EMinicard::editable", GTK_TYPE_BOOL, - GTK_ARG_READWRITE, ARG_EDITABLE); - gtk_object_add_arg_type ("EMinicard::card", GTK_TYPE_OBJECT, - GTK_ARG_READWRITE, ARG_CARD); - - e_minicard_signals [SELECTED] = - gtk_signal_new ("selected", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EMinicardClass, selected), - gtk_marshal_INT__POINTER, - GTK_TYPE_INT, 1, GTK_TYPE_POINTER); - - e_minicard_signals [DRAG_BEGIN] = - gtk_signal_new ("drag_begin", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (EMinicardClass, drag_begin), - gtk_marshal_INT__POINTER, - GTK_TYPE_INT, 1, GTK_TYPE_POINTER); - - gtk_object_class_add_signals (object_class, e_minicard_signals, LAST_SIGNAL); - - object_class->set_arg = e_minicard_set_arg; - object_class->get_arg = e_minicard_get_arg; - object_class->destroy = e_minicard_destroy; + object_class = G_OBJECT_CLASS (class); + object_class->set_property = e_minicard_set_property; + object_class->get_property = e_minicard_get_property; + object_class->dispose = e_minicard_dispose; object_class->finalize = e_minicard_finalize; - - /* GnomeCanvasItem method overrides */ - item_class->realize = e_minicard_realize; - item_class->unrealize = e_minicard_unrealize; - item_class->event = e_minicard_event; - klass->selected = NULL; + item_class = GNOME_CANVAS_ITEM_CLASS (class); + item_class->realize = e_minicard_realize; + item_class->event = e_minicard_event; + + class->style_set = e_minicard_style_set; + class->selected = NULL; + + g_object_class_install_property ( + object_class, + PROP_WIDTH, + g_param_spec_double ( + "width", + "Width", + NULL, + 0.0, G_MAXDOUBLE, 10.0, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_HEIGHT, + g_param_spec_double ( + "height", + "Height", + NULL, + 0.0, G_MAXDOUBLE, 10.0, + G_PARAM_READABLE)); + + g_object_class_install_property ( + object_class, + PROP_HAS_FOCUS, + /* XXX should be _enum */ + g_param_spec_int ( + "has_focus", + "Has Focus", + NULL, + E_MINICARD_FOCUS_TYPE_START, + E_MINICARD_FOCUS_TYPE_END, + E_MINICARD_FOCUS_TYPE_START, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SELECTED, + g_param_spec_boolean ( + "selected", + "Selected", + NULL, + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_HAS_CURSOR, + g_param_spec_boolean ( + "has_cursor", + "Has Cursor", + NULL, + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_EDITABLE, + g_param_spec_boolean ( + "editable", + "Editable", + NULL, + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_CONTACT, + g_param_spec_object ( + "contact", + "Contact", + NULL, + E_TYPE_CONTACT, + G_PARAM_READWRITE)); + + signals[SELECTED] = g_signal_new ( + "selected", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardClass, selected), + NULL, NULL, + e_marshal_INT__POINTER, + G_TYPE_INT, 1, + G_TYPE_POINTER); + + signals[DRAG_BEGIN] = g_signal_new ( + "drag_begin", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardClass, drag_begin), + NULL, NULL, + e_marshal_INT__POINTER, + G_TYPE_INT, 1, + G_TYPE_POINTER); + + signals[OPEN_CONTACT] = g_signal_new ( + "open-contact", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardClass, open_contact), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CONTACT); + + signals[STYLE_SET] = g_signal_new ( + "style_set", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMinicardClass, style_set), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + GTK_TYPE_STYLE); + + /* init the accessibility support for e_minicard */ + e_minicard_a11y_init (); } static void e_minicard_init (EMinicard *minicard) { - /* minicard->card = NULL;*/ minicard->rect = NULL; minicard->fields = NULL; minicard->width = 10; @@ -193,163 +247,186 @@ e_minicard_init (EMinicard *minicard) minicard->editable = FALSE; minicard->has_cursor = FALSE; - minicard->card = NULL; - minicard->simple = e_card_simple_new(NULL); + minicard->contact = NULL; - minicard->list_icon_pixbuf = gdk_pixbuf_new_from_file (EVOLUTION_IMAGESDIR "/" LIST_ICON_FILENAME); + minicard->list_icon_pixbuf = e_icon_factory_get_icon (LIST_ICON_NAME, GTK_ICON_SIZE_MENU); minicard->list_icon_size = gdk_pixbuf_get_height (minicard->list_icon_pixbuf); - minicard->editor = NULL; - minicard->changed = FALSE; - e_canvas_item_set_reflow_callback(GNOME_CANVAS_ITEM(minicard), e_minicard_reflow); + e_canvas_item_set_reflow_callback (GNOME_CANVAS_ITEM (minicard), e_minicard_reflow); } static void -set_selected (EMinicard *minicard, gboolean selected) +set_selected (EMinicard *minicard, + gboolean selected) { - GtkWidget *canvas = GTK_WIDGET(GNOME_CANVAS_ITEM(minicard)->canvas); + GnomeCanvas *canvas; + GtkStyle *style; + + canvas = GNOME_CANVAS_ITEM (minicard)->canvas; + style = gtk_widget_get_style (GTK_WIDGET (canvas)); + if (selected) { - gnome_canvas_item_set (minicard->rect, - "outline_color_gdk", &canvas->style->bg[GTK_STATE_NORMAL], - NULL); - gnome_canvas_item_set (minicard->header_rect, - "fill_color_gdk", &canvas->style->bg[GTK_STATE_SELECTED], - NULL); - gnome_canvas_item_set (minicard->header_text, - "fill_color_gdk", &canvas->style->text[GTK_STATE_SELECTED], - NULL); + gnome_canvas_item_set ( + minicard->rect, + "outline_color_gdk", &style->bg[GTK_STATE_ACTIVE], + NULL); + gnome_canvas_item_set ( + minicard->header_rect, + "fill_color_gdk", &style->bg[GTK_STATE_SELECTED], + NULL); + gnome_canvas_item_set ( + minicard->header_text, + "fill_color_gdk", &style->text[GTK_STATE_SELECTED], + NULL); } else { - gnome_canvas_item_set (minicard->rect, - "outline_color", NULL, - NULL); - gnome_canvas_item_set (minicard->header_rect, - "fill_color_gdk", &canvas->style->bg[GTK_STATE_NORMAL], - NULL); - gnome_canvas_item_set (minicard->header_text, - "fill_color_gdk", &canvas->style->fg[GTK_STATE_NORMAL], - NULL); + gnome_canvas_item_set ( + minicard->rect, + "outline_color", NULL, + NULL); + gnome_canvas_item_set ( + minicard->header_rect, + "fill_color_gdk", &style->bg[GTK_STATE_NORMAL], + NULL); + gnome_canvas_item_set ( + minicard->header_text, + "fill_color_gdk", &style->text[GTK_STATE_NORMAL], + NULL); } minicard->selected = selected; } static void -set_has_cursor (EMinicard *minicard, gboolean has_cursor) +set_has_cursor (EMinicard *minicard, + gboolean has_cursor) { if (!minicard->has_focus && has_cursor) - e_canvas_item_grab_focus(GNOME_CANVAS_ITEM (minicard), FALSE); + e_canvas_item_grab_focus (GNOME_CANVAS_ITEM (minicard), FALSE); minicard->has_cursor = has_cursor; } - static void -e_minicard_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) +e_minicard_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { GnomeCanvasItem *item; EMinicard *e_minicard; + EContact *contact; GList *l; - item = GNOME_CANVAS_ITEM (o); - e_minicard = E_MINICARD (o); - - switch (arg_id){ - case ARG_WIDTH: - if (e_minicard->width != GTK_VALUE_DOUBLE (*arg)) { - e_minicard->width = GTK_VALUE_DOUBLE (*arg); - e_minicard_resize_children(e_minicard); - if ( GTK_OBJECT_FLAGS( e_minicard ) & GNOME_CANVAS_ITEM_REALIZED ) - e_canvas_item_request_reflow(item); + item = GNOME_CANVAS_ITEM (object); + e_minicard = E_MINICARD (object); + + switch (property_id) { + case PROP_WIDTH: + if (e_minicard->width != g_value_get_double (value)) { + e_minicard->width = g_value_get_double (value); + e_minicard_resize_children (e_minicard); + if (item->flags & GNOME_CANVAS_ITEM_REALIZED) + e_canvas_item_request_reflow (item); } break; - case ARG_HAS_FOCUS: + case PROP_HAS_FOCUS: if (e_minicard->fields) { - if ( GTK_VALUE_ENUM(*arg) == E_FOCUS_START || - GTK_VALUE_ENUM(*arg) == E_FOCUS_CURRENT) { - gnome_canvas_item_set(E_MINICARD_FIELD(e_minicard->fields->data)->label, - "has_focus", GTK_VALUE_ENUM(*arg), - NULL); - } else if ( GTK_VALUE_ENUM(*arg) == E_FOCUS_END ) { - gnome_canvas_item_set(E_MINICARD_FIELD(g_list_last(e_minicard->fields)->data)->label, - "has_focus", GTK_VALUE_ENUM(*arg), - NULL); + if (g_value_get_int (value) == E_FOCUS_START || + g_value_get_int (value) == E_FOCUS_CURRENT) { + gnome_canvas_item_set ( + E_MINICARD_FIELD (e_minicard->fields->data)->label, + "has_focus", g_value_get_int (value), + NULL); + } else if (g_value_get_int (value) == E_FOCUS_END) { + gnome_canvas_item_set ( + E_MINICARD_FIELD (g_list_last (e_minicard->fields)->data)->label, + "has_focus", g_value_get_int (value), + NULL); } } else { if (!e_minicard->has_focus) - e_canvas_item_grab_focus(item, FALSE); + e_canvas_item_grab_focus (item, FALSE); } break; - case ARG_SELECTED: - if (e_minicard->selected != GTK_VALUE_BOOL(*arg)) - set_selected (e_minicard, GTK_VALUE_BOOL(*arg)); + case PROP_SELECTED: + if (e_minicard->selected != g_value_get_boolean (value)) + set_selected (e_minicard, g_value_get_boolean (value)); break; - case ARG_EDITABLE: - e_minicard->editable = GTK_VALUE_BOOL(*arg); - for (l = e_minicard->fields; l; l = l->next) - gtk_object_set (GTK_OBJECT (E_MINICARD_FIELD (l->data)->label), - "editable", e_minicard->editable, - NULL); + case PROP_EDITABLE: + e_minicard->editable = g_value_get_boolean (value); + for (l = e_minicard->fields; l; l = l->next) { + g_object_set ( + E_MINICARD_FIELD (l->data)->label, + "editable", FALSE /* e_minicard->editable */, + NULL); + } break; - case ARG_HAS_CURSOR: - d(g_print("%s: ARG_HAS_CURSOR\n", __FUNCTION__)); - if (e_minicard->has_cursor != GTK_VALUE_BOOL(*arg)) - set_has_cursor (e_minicard, GTK_VALUE_BOOL(*arg)); + case PROP_HAS_CURSOR: + d (g_print ("%s: PROP_HAS_CURSOR\n", G_STRFUNC)); + if (e_minicard->has_cursor != g_value_get_boolean (value)) + set_has_cursor (e_minicard, g_value_get_boolean (value)); break; - case ARG_CARD: - if (e_minicard->card) - gtk_object_unref (GTK_OBJECT(e_minicard->card)); - e_minicard->card = E_CARD(GTK_VALUE_OBJECT (*arg)); - if (e_minicard->card) - gtk_object_ref (GTK_OBJECT(e_minicard->card)); - gtk_object_set(GTK_OBJECT(e_minicard->simple), - "card", e_minicard->card, - NULL); - remodel(e_minicard); - e_canvas_item_request_reflow(item); + case PROP_CONTACT: + contact = E_CONTACT (g_value_get_object (value)); + if (contact) + g_object_ref (contact); + + if (e_minicard->contact) + g_object_unref (e_minicard->contact); + + e_minicard->contact = contact; + + remodel (e_minicard); + e_canvas_item_request_reflow (item); e_minicard->changed = FALSE; break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; } } static void -e_minicard_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +e_minicard_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { EMinicard *e_minicard; e_minicard = E_MINICARD (object); - switch (arg_id) { - case ARG_WIDTH: - GTK_VALUE_DOUBLE (*arg) = e_minicard->width; - break; - case ARG_HEIGHT: - GTK_VALUE_DOUBLE (*arg) = e_minicard->height; - break; - case ARG_HAS_FOCUS: - GTK_VALUE_ENUM (*arg) = e_minicard->has_focus ? E_FOCUS_CURRENT : E_FOCUS_NONE; + switch (property_id) { + case PROP_WIDTH: + g_value_set_double (value, e_minicard->width); + break; + case PROP_HEIGHT: + g_value_set_double (value, e_minicard->height); + break; + case PROP_HAS_FOCUS: + g_value_set_int (value, e_minicard->has_focus ? E_FOCUS_CURRENT : E_FOCUS_NONE); break; - case ARG_SELECTED: - GTK_VALUE_BOOL (*arg) = e_minicard->selected; + case PROP_SELECTED: + g_value_set_boolean (value, e_minicard->selected); break; - case ARG_HAS_CURSOR: - GTK_VALUE_BOOL (*arg) = e_minicard->has_cursor; + case PROP_HAS_CURSOR: + g_value_set_boolean (value, e_minicard->has_cursor); break; - case ARG_EDITABLE: - GTK_VALUE_BOOL (*arg) = e_minicard->editable; + case PROP_EDITABLE: + g_value_set_boolean (value, e_minicard->editable); break; - case ARG_CARD: - e_card_simple_sync_card(e_minicard->simple); - GTK_VALUE_OBJECT (*arg) = GTK_OBJECT(e_minicard->card); + case PROP_CONTACT: + g_value_set_object (value, e_minicard->contact); break; default: - arg->type = GTK_TYPE_INVALID; - break; + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; } } static void -e_minicard_destroy (GtkObject *object) +e_minicard_dispose (GObject *object) { EMinicard *e_minicard; @@ -357,20 +434,24 @@ e_minicard_destroy (GtkObject *object) g_return_if_fail (E_IS_MINICARD (object)); e_minicard = E_MINICARD (object); - - g_list_foreach(e_minicard->fields, (GFunc) e_minicard_field_destroy, NULL); - g_list_free(e_minicard->fields); - - gdk_pixbuf_unref (e_minicard->list_icon_pixbuf); - if (GTK_OBJECT_CLASS (parent_class)->destroy) - (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); -} + if (e_minicard->fields) { + g_list_foreach (e_minicard->fields, (GFunc) e_minicard_field_destroy, NULL); + g_list_free (e_minicard->fields); + e_minicard->fields = NULL; + } + if (e_minicard->list_icon_pixbuf) { + g_object_unref (e_minicard->list_icon_pixbuf); + e_minicard->list_icon_pixbuf = NULL; + } + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (e_minicard_parent_class)->dispose (object); +} static void -e_minicard_finalize (GtkObject *object) +e_minicard_finalize (GObject *object) { EMinicard *e_minicard; @@ -378,178 +459,149 @@ e_minicard_finalize (GtkObject *object) g_return_if_fail (E_IS_MINICARD (object)); e_minicard = E_MINICARD (object); - - if (e_minicard->card) - gtk_object_unref (GTK_OBJECT(e_minicard->card)); - if (e_minicard->simple) - gtk_object_unref (GTK_OBJECT(e_minicard->simple)); - - if (GTK_OBJECT_CLASS (parent_class)->finalize) - (* GTK_OBJECT_CLASS (parent_class)->finalize) (object); -} - -static void -e_minicard_realize (GnomeCanvasItem *item) -{ - EMinicard *e_minicard; - GnomeCanvasGroup *group; - GtkWidget *canvas; - e_minicard = E_MINICARD (item); - group = GNOME_CANVAS_GROUP( item ); - canvas = GTK_WIDGET (GNOME_CANVAS_ITEM (item)->canvas); - - if (GNOME_CANVAS_ITEM_CLASS(parent_class)->realize) - (* GNOME_CANVAS_ITEM_CLASS(parent_class)->realize) (item); - - e_minicard->rect = - gnome_canvas_item_new( group, - gnome_canvas_rect_get_type(), - "x1", (double) 0, - "y1", (double) 0, - "x2", (double) e_minicard->width - 1, - "y2", (double) e_minicard->height - 1, - "outline_color", NULL, - NULL ); - - e_minicard->header_rect = - gnome_canvas_item_new( group, - gnome_canvas_rect_get_type(), - "x1", (double) 2, - "y1", (double) 2, - "x2", (double) e_minicard->width - 3, - "y2", (double) e_minicard->height - 3, - "fill_color_gdk", &canvas->style->bg[GTK_STATE_NORMAL], - NULL ); - - e_minicard->header_text = - gnome_canvas_item_new( group, - e_text_get_type(), - "anchor", GTK_ANCHOR_NW, - "width", (double) ( e_minicard->width - 12 ), - "clip", TRUE, - "use_ellipsis", TRUE, -#if 0 - "font", "fixed-bold-10", -#endif - "fill_color_gdk", &canvas->style->fg[GTK_STATE_NORMAL], - "text", "", - "draw_background", FALSE, - NULL ); - - e_canvas_item_move_absolute(e_minicard->header_text, 6, 6); - - e_minicard->list_icon = - gnome_canvas_item_new ( group, - gnome_canvas_pixbuf_get_type(), - "pixbuf", e_minicard->list_icon_pixbuf, - NULL); - - remodel(e_minicard); - e_canvas_item_request_reflow(item); + if (e_minicard->contact) { + g_object_unref (e_minicard->contact); + e_minicard->contact = NULL; + } - if (!item->canvas->aa) { + if (e_minicard->list_icon_pixbuf) { + g_object_unref (e_minicard->list_icon_pixbuf); + e_minicard->list_icon_pixbuf = NULL; } + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (e_minicard_parent_class)->finalize (object); } static void -e_minicard_unrealize (GnomeCanvasItem *item) +e_minicard_style_set (EMinicard *minicard, + GtkStyle *previous_style) { - EMinicard *e_minicard; - - e_minicard = E_MINICARD (item); - - if (!item->canvas->aa) - { - } + GnomeCanvasItem *item = GNOME_CANVAS_ITEM (minicard); - if (GNOME_CANVAS_ITEM_CLASS(parent_class)->unrealize) - (* GNOME_CANVAS_ITEM_CLASS(parent_class)->unrealize) (item); + if ((item->flags & GNOME_CANVAS_ITEM_REALIZED)) + set_selected (minicard, minicard->selected); } static void -card_modified_cb (EBook* book, EBookStatus status, gpointer user_data) +e_minicard_realize (GnomeCanvasItem *item) { - d(g_print ("%s: %s(): a card was modified\n", __FILE__, __FUNCTION__)); - if (status != E_BOOK_STATUS_SUCCESS) - e_addressbook_error_dialog (_("Error modifying card"), status); + EMinicard *e_minicard; + GnomeCanvasGroup *group; + GnomeCanvas *canvas; + GtkStyle *style; + + e_minicard = E_MINICARD (item); + group = GNOME_CANVAS_GROUP (item); + + canvas = GNOME_CANVAS_ITEM (item)->canvas; + style = gtk_widget_get_style (GTK_WIDGET (canvas)); + + GNOME_CANVAS_ITEM_CLASS (e_minicard_parent_class)->realize (item); + + e_minicard->rect = gnome_canvas_item_new ( + group, + gnome_canvas_rect_get_type (), + "x1", (gdouble) 0, + "y1", (gdouble) 0, + "x2", (gdouble) MAX (e_minicard->width - 1, 0), + "y2", (gdouble) MAX (e_minicard->height - 1, 0), + "outline_color", NULL, + NULL); + + e_minicard->header_rect = gnome_canvas_item_new ( + group, + gnome_canvas_rect_get_type (), + "x1", (gdouble) 2, + "y1", (gdouble) 2, + "x2", (gdouble) MAX (e_minicard->width - 3, 0), + "y2", (gdouble) MAX (e_minicard->height - 3, 0), + "fill_color_gdk", &style->bg[GTK_STATE_NORMAL], + NULL); + + e_minicard->header_text = gnome_canvas_item_new ( + group, + e_text_get_type (), + "width", (gdouble) MAX (e_minicard->width - 12, 0), + "clip", TRUE, + "use_ellipsis", TRUE, + "fill_color_gdk", &style->fg[GTK_STATE_NORMAL], + "text", "", + NULL); + + e_canvas_item_move_absolute (e_minicard->header_text, 6, 6); + + e_minicard->list_icon = gnome_canvas_item_new ( + group, + gnome_canvas_pixbuf_get_type (), + "pixbuf", e_minicard->list_icon_pixbuf, + NULL); + + set_selected (e_minicard, e_minicard->selected); + + remodel (e_minicard); + e_canvas_item_request_reflow (item); } -/* Callback used when the contact editor is closed */ -static void -editor_closed_cb (GtkObject *editor, gpointer data) +void +e_minicard_activate_editor (EMinicard *minicard) { - EMinicard *minicard = data; - gtk_object_unref (GTK_OBJECT (editor)); - minicard->editor = NULL; + g_return_if_fail (E_IS_MINICARD (minicard)); + + g_signal_emit (minicard, signals[OPEN_CONTACT], 0, minicard->contact); } static gboolean -e_minicard_event (GnomeCanvasItem *item, GdkEvent *event) +e_minicard_event (GnomeCanvasItem *item, + GdkEvent *event) { EMinicard *e_minicard; - GtkWidget *canvas; - + e_minicard = E_MINICARD (item); - canvas = GTK_WIDGET (GNOME_CANVAS_ITEM (item)->canvas); - - switch( event->type ) { + + switch (event->type) { case GDK_FOCUS_CHANGE: { GdkEventFocus *focus_event = (GdkEventFocus *) event; - d(g_print("%s: GDK_FOCUS_CHANGE: %s\n", __FUNCTION__, focus_event->in?"in":"out")); + d (g_print ("%s: GDK_FOCUS_CHANGE: %s\n", G_STRFUNC, focus_event->in?"in":"out")); if (focus_event->in) { /* Chris: When EMinicard gets the cursor, if it doesn't have the focus, it should take it. */ e_minicard->has_focus = TRUE; if (!e_minicard->selected) { - e_minicard_selected(e_minicard, event); - } - } else { - EBook *book = NULL; - - if (e_minicard->changed) { - - e_card_simple_sync_card(e_minicard->simple); - - if (E_IS_MINICARD_VIEW(GNOME_CANVAS_ITEM(e_minicard)->parent)) { - - gtk_object_get(GTK_OBJECT(GNOME_CANVAS_ITEM(e_minicard)->parent), - "book", &book, - NULL); - - } - - if (book) { - - /* Add the card in the contact editor to our ebook */ - e_card_merging_book_commit_card (book, - e_minicard->card, - card_modified_cb, - NULL); - } else { - remodel(e_minicard); - e_canvas_item_request_reflow(GNOME_CANVAS_ITEM(e_minicard)); - } - e_minicard->changed = FALSE; + e_minicard_selected (e_minicard, event); } + } + else { e_minicard->has_focus = FALSE; } } break; case GDK_BUTTON_PRESS: { if (1 <= event->button.button && event->button.button <= 2) { - int ret_val = e_minicard_selected(e_minicard, event); - GdkEventMask mask = ((1 << (4 + event->button.button)) | - GDK_POINTER_MOTION_MASK | - GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK); - - e_canvas_item_grab_focus(item, TRUE); - - if (gnome_canvas_item_grab (GNOME_CANVAS_ITEM (e_minicard), - mask, NULL, event->button.time)) { + gint ret_val = e_minicard_selected (e_minicard, event); + GdkGrabStatus grab_status; + GdkDevice *event_device; + guint32 event_time; + + e_canvas_item_grab_focus (item, TRUE); + + event_device = gdk_event_get_device (event); + event_time = gdk_event_get_time (event); + + grab_status = gnome_canvas_item_grab ( + GNOME_CANVAS_ITEM (e_minicard), + (1 << (4 + event->button.button)) | + GDK_POINTER_MOTION_MASK | + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK, + NULL, + event_device, + event_time); + + if (grab_status != GDK_GRAB_SUCCESS) return FALSE; - } + gtk_grab_add (GTK_WIDGET (GNOME_CANVAS_ITEM (e_minicard)->canvas)); e_minicard->button_x = event->button.x; e_minicard->button_y = event->button.y; @@ -557,21 +609,21 @@ e_minicard_event (GnomeCanvasItem *item, GdkEvent *event) e_minicard->drag_button_down = TRUE; return ret_val; } else if (event->button.button == 3) { - int ret_val = e_minicard_selected(e_minicard, event); + gint ret_val = e_minicard_selected (e_minicard, event); if (ret_val != 0) return ret_val; } break; } case GDK_BUTTON_RELEASE: - e_minicard_selected(e_minicard, event); + e_minicard_selected (e_minicard, event); if (e_minicard->drag_button == event->button.button) { e_minicard->drag_button = 0; e_minicard->drag_button_down = FALSE; e_minicard->button_x = -1; e_minicard->button_y = -1; - if (GTK_WIDGET_HAS_GRAB (GNOME_CANVAS_ITEM (e_minicard)->canvas)) { + if (gtk_widget_has_grab (GTK_WIDGET (GNOME_CANVAS_ITEM (e_minicard)->canvas))) { gtk_grab_remove (GTK_WIDGET (GNOME_CANVAS_ITEM (e_minicard)->canvas)); gnome_canvas_item_ungrab (GNOME_CANVAS_ITEM (e_minicard), event->button.time); } @@ -583,7 +635,7 @@ e_minicard_event (GnomeCanvasItem *item, GdkEvent *event) abs (e_minicard->button_y - event->motion.y)) > 3) { gint ret_val; - ret_val = e_minicard_drag_begin(e_minicard, event); + ret_val = e_minicard_drag_begin (e_minicard, event); e_minicard->drag_button_down = FALSE; @@ -592,408 +644,555 @@ e_minicard_event (GnomeCanvasItem *item, GdkEvent *event) } break; case GDK_2BUTTON_PRESS: - if (event->button.button == 1 && E_IS_MINICARD_VIEW(item->parent)) { - if (e_minicard->editor) { - if (e_card_evolution_list (e_minicard->card)) - e_contact_list_editor_raise (E_CONTACT_LIST_EDITOR(e_minicard->editor)); - else - e_contact_editor_raise(E_CONTACT_EDITOR(e_minicard->editor)); - } else { - EBook *book = NULL; - if (E_IS_MINICARD_VIEW(item->parent)) { - gtk_object_get(GTK_OBJECT(item->parent), - "book", &book, - NULL); + if (event->button.button == 1 && E_IS_MINICARD_VIEW (item->parent)) { + e_minicard_activate_editor (e_minicard); + return TRUE; + } + break; + case GDK_KEY_PRESS: + if (event->key.keyval == GDK_KEY_Tab || + event->key.keyval == GDK_KEY_KP_Tab || + event->key.keyval == GDK_KEY_ISO_Left_Tab) { + + EMinicardView *view = E_MINICARD_VIEW (item->parent); + EReflow *reflow = E_REFLOW (view); + + if (reflow == NULL) { + return FALSE; + } + + if (event->key.state & GDK_SHIFT_MASK) { + if (event->key.state & GDK_CONTROL_MASK) { + return FALSE; } + else { + gint row_count = e_selection_model_row_count (reflow->selection); + gint model_index = e_selection_model_cursor_row (reflow->selection); + gint view_index = e_sorter_model_to_sorted (reflow->selection->sorter, model_index); - if (book != NULL) { - if (e_card_evolution_list (e_minicard->card)) { - EContactListEditor *editor = e_addressbook_show_contact_list_editor (book, e_minicard->card, - FALSE, e_minicard->editable); - e_minicard->editor = GTK_OBJECT (editor); - } - else { - EContactEditor *editor = e_addressbook_show_contact_editor (book, e_minicard->card, - FALSE, e_minicard->editable); - e_minicard->editor = GTK_OBJECT (editor); - } - gtk_object_ref (e_minicard->editor); + if (view_index == 0) + view_index = row_count - 1; + else + view_index--; - gtk_signal_connect (e_minicard->editor, "editor_closed", - GTK_SIGNAL_FUNC (editor_closed_cb), e_minicard); + model_index = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), view_index); + if (reflow->items[model_index] == NULL) { + reflow->items[model_index] = e_reflow_model_incarnate (reflow->model, model_index, GNOME_CANVAS_GROUP (reflow)); + g_object_set ( + reflow->items[model_index], + "width", (gdouble) reflow->column_width, + NULL); + } + e_canvas_item_grab_focus (reflow->items[model_index], FALSE); + return TRUE; } } - return TRUE; - } - break; - case GDK_KEY_PRESS: - if (event->key.keyval == GDK_Tab || - event->key.keyval == GDK_KP_Tab || - event->key.keyval == GDK_ISO_Left_Tab) { - GList *list; - for (list = e_minicard->fields; list; list = list->next) { - EMinicardField *field = E_MINICARD_FIELD(list->data); - GnomeCanvasItem *item = field->label; - EFocus has_focus; - gtk_object_get(GTK_OBJECT(item), - "has_focus", &has_focus, - NULL); - if (has_focus != E_FOCUS_NONE) { - if (event->key.state & GDK_SHIFT_MASK) - list = list->prev; + else { + if (event->key.state & GDK_CONTROL_MASK) { + return FALSE; + } + else { + gint row_count = e_selection_model_row_count (reflow->selection); + gint model_index = e_selection_model_cursor_row (reflow->selection); + gint view_index = e_sorter_model_to_sorted (reflow->selection->sorter, model_index); + + if (view_index == row_count - 1) + view_index = 0; else - list = list->next; - if (list) { - EMinicardField *field = E_MINICARD_FIELD(list->data); - GnomeCanvasItem *item = field->label; - gnome_canvas_item_set(item, - "has_focus", (event->key.state & GDK_SHIFT_MASK) ? E_FOCUS_END : E_FOCUS_START, - NULL); - return 1; - } else { - return 0; + view_index++; + + model_index = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), view_index); + if (reflow->items[model_index] == NULL) { + reflow->items[model_index] = e_reflow_model_incarnate (reflow->model, model_index, GNOME_CANVAS_GROUP (reflow)); + g_object_set ( + reflow->items[model_index], + "width", (gdouble) reflow->column_width, + NULL); + } + e_canvas_item_grab_focus (reflow->items[model_index], FALSE); + return TRUE; } } } + else if (event->key.keyval == GDK_KEY_Return || + event->key.keyval == GDK_KEY_KP_Enter) { + e_minicard_activate_editor (e_minicard); + return TRUE; + } + break; default: break; } - - if (GNOME_CANVAS_ITEM_CLASS( parent_class )->event) - return (* GNOME_CANVAS_ITEM_CLASS( parent_class )->event) (item, event); - else - return 0; + + return FALSE; } static void -e_minicard_resize_children( EMinicard *e_minicard ) +e_minicard_resize_children (EMinicard *e_minicard) { GList *list; - + gboolean is_list = GPOINTER_TO_INT (e_contact_get (e_minicard->contact, E_CONTACT_IS_LIST)); + if (e_minicard->header_text) { - gnome_canvas_item_set( e_minicard->header_text, - "width", ((double) e_minicard->width - 12 - - (e_card_evolution_list (e_minicard->card) ? e_minicard->list_icon_size : 0.0)), - NULL ); + gnome_canvas_item_set ( + e_minicard->header_text, + "width", ((gdouble) e_minicard->width - 12 + - (is_list ? e_minicard->list_icon_size : 0.0)), + NULL); } if (e_minicard->list_icon) { - e_canvas_item_move_absolute(e_minicard->list_icon, - e_minicard->width - e_minicard->list_icon_size - 3, - 3); + e_canvas_item_move_absolute ( + e_minicard->list_icon, + e_minicard->width - e_minicard->list_icon_size - 3, + 3); } - for ( list = e_minicard->fields; list; list = g_list_next( list ) ) { - gnome_canvas_item_set( E_MINICARD_FIELD( list->data )->label, - "width", (double) e_minicard->width - 4.0, - NULL ); + for (list = e_minicard->fields; list; list = g_list_next (list)) { + gnome_canvas_item_set ( + E_MINICARD_FIELD (list->data)->label, + "width", (gdouble) e_minicard->width - 4.0, + NULL); } } static void -field_changed (EText *text, EMinicard *e_minicard) +add_field (EMinicard *e_minicard, + EContactField field, + gdouble left_width) { - ECardSimpleType type; - char *string; - - type = GPOINTER_TO_INT - (gtk_object_get_data(GTK_OBJECT(text), - "EMinicard:field")); - gtk_object_get(GTK_OBJECT(text), - "text", &string, - NULL); - e_card_simple_set(e_minicard->simple, - type, - string); - g_free(string); - e_minicard->changed = TRUE; + GnomeCanvasItem *new_item; + GnomeCanvasGroup *group; + EMinicardField *minicard_field; + gchar *name; + gchar *string; + gboolean is_rtl = (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL); + + group = GNOME_CANVAS_GROUP (e_minicard); + + name = g_strdup_printf ("%s:", e_contact_pretty_name (field)); + string = e_contact_get (e_minicard->contact, field); + + new_item = e_minicard_label_new (group); + + if (e_minicard->contact && e_contact_get (e_minicard->contact, E_CONTACT_IS_LIST)) + gnome_canvas_item_set ( + new_item, + "fieldname", is_rtl ? "" : string, + "field", is_rtl ? string : "", + "max_field_name_length", left_width, + "editable", FALSE /* e_minicard->editable */, + "width", e_minicard->width - 4.0, + NULL); + else + gnome_canvas_item_set ( + new_item, + "fieldname", is_rtl ? string : name, + "field", is_rtl ? name : string, + "max_field_name_length", left_width, + "editable", FALSE /* e_minicard->editable */, + "width", e_minicard->width - 4.0, + NULL); + +#ifdef notyet + g_object_set ( + E_MINICARD_LABEL (new_item)->field, + "allow_newlines", e_card_simple_get_allow_newlines (e_minicard->contact, field), + NULL); +#endif + g_object_set_data ( + G_OBJECT (E_MINICARD_LABEL (new_item)->field), + "EMinicard:field", + GINT_TO_POINTER (field)); + + minicard_field = g_new (EMinicardField, 1); + minicard_field->field = field; + minicard_field->label = new_item; + + e_minicard->fields = g_list_append (e_minicard->fields, minicard_field); + e_canvas_item_move_absolute (new_item, 2, e_minicard->height); + g_free (name); + g_free (string); } -static void -field_activated (EText *text, EMinicard *e_minicard) +static const gchar * +get_email_location (EVCardAttribute *attr) { - e_text_stop_editing (text); - e_canvas_item_grab_focus (GNOME_CANVAS_ITEM (e_minicard), FALSE); + gint i; + + for (i = 0; i < G_N_ELEMENTS (common_location); i++) { + if (e_vcard_attribute_has_type (attr, common_location[i].name)) + return _(common_location[i].pretty_name); + } + + return _("Other Email"); } static void -add_field (EMinicard *e_minicard, ECardSimpleField field, gdouble left_width) +add_email_field (EMinicard *e_minicard, + GList *email_list, + gdouble left_width, + gint limit, + gboolean is_list) { GnomeCanvasItem *new_item; GnomeCanvasGroup *group; - ECardSimpleType type; EMinicardField *minicard_field; - char *name; - char *string; - - group = GNOME_CANVAS_GROUP( e_minicard ); - - type = e_card_simple_type(e_minicard->simple, field); - name = g_strdup_printf("%s:", e_card_simple_get_name(e_minicard->simple, field)); - string = e_card_simple_get(e_minicard->simple, field); - - /* Magically convert embedded XML into an address. */ - if (!strncmp (string, "<?xml", 5)) { - EDestination *dest = e_destination_import (string); - if (dest != NULL) { - gchar *new_string = g_strdup (e_destination_get_address (dest)); - g_free (string); - string = new_string; - gtk_object_unref (GTK_OBJECT (dest)); + gchar *name; + GList *l, *le; + gint count =0; + gboolean is_rtl = (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL); + GList *emails = e_contact_get (e_minicard->contact, E_CONTACT_EMAIL); + group = GNOME_CANVAS_GROUP (e_minicard); + + for (l = email_list, le = emails; l != NULL && count < limit && le != NULL; l = l->next, le = le->next) { + const gchar *tmp; + gchar *email = NULL; + gchar *string = NULL; + gchar *parsed_name = NULL; + gboolean parser_check; + + /* do not use name for fields in the contact list */ + if (is_list) { + name = (gchar *)""; + } else { + tmp = get_email_location ((EVCardAttribute *) l->data); + name = g_strdup_printf ("%s:", tmp); } - } - new_item = e_minicard_label_new(group); - gnome_canvas_item_set( new_item, - "width", e_minicard->width - 4.0, - "fieldname", name, - "field", string, - "max_field_name_length", left_width, - "editable", e_minicard->editable, - NULL ); - gtk_signal_connect(GTK_OBJECT(E_MINICARD_LABEL(new_item)->field), - "changed", GTK_SIGNAL_FUNC(field_changed), e_minicard); - gtk_signal_connect(GTK_OBJECT(E_MINICARD_LABEL(new_item)->field), - "activate", GTK_SIGNAL_FUNC(field_activated), e_minicard); - gtk_object_set(GTK_OBJECT(E_MINICARD_LABEL(new_item)->field), - "allow_newlines", e_card_simple_get_allow_newlines (e_minicard->simple, field), - NULL); - gtk_object_set_data(GTK_OBJECT(E_MINICARD_LABEL(new_item)->field), - "EMinicard:field", - GINT_TO_POINTER(field)); - - minicard_field = g_new(EMinicardField, 1); - minicard_field->field = field; - minicard_field->label = new_item; + parser_check = eab_parse_qp_email ((const gchar *) le->data, &parsed_name, &email); + if (parser_check) { + /* if true, we had a quoted printable mail address */ + string = g_strdup_printf ("%s <%s>", parsed_name, email); + } else { + /* we got a NON-quoted printable string */ + string = g_strdup (le->data); + } - e_minicard->fields = g_list_append( e_minicard->fields, minicard_field); - e_canvas_item_move_absolute(new_item, 2, e_minicard->height); - g_free(name); - g_free(string); + new_item = e_minicard_label_new (group); + + gnome_canvas_item_set ( + new_item, + "fieldname", is_rtl ? string : name, + "field", is_rtl ? name : string, + "max_field_name_length", left_width, + "editable", FALSE /* e_minicard->editable */, + "width", e_minicard->width - 4.0, + NULL); + +#ifdef notyet + g_object_set ( + E_MINICARD_LABEL (new_item)->field, + "allow_newlines", e_card_simple_get_allow_newlines (e_minicard->contact, field), + NULL); +#endif + g_object_set_data ( + G_OBJECT (E_MINICARD_LABEL (new_item)->field), + "EMinicard:field", + GINT_TO_POINTER (E_CONTACT_EMAIL)); + + minicard_field = g_new (EMinicardField, 1); + minicard_field->field = E_CONTACT_EMAIL; + minicard_field->label = new_item; + + e_minicard->fields = g_list_append (e_minicard->fields, minicard_field); + e_canvas_item_move_absolute (new_item, 2, e_minicard->height); + count++; + if (!is_list) + g_free (name); + g_free (string); + g_free (parsed_name); + g_free (email); + } + g_list_foreach (emails, (GFunc) g_free, NULL); + g_list_free (emails); } -static gdouble -get_left_width(EMinicard *e_minicard) +static gint +get_left_width (EMinicard *e_minicard, + gboolean is_list) { gchar *name; - ECardSimpleField field; - gdouble width = -1; - GdkFont *font; + EContactField field; + gint width = -1; + PangoLayout *layout; + + if (is_list) + return 0; + + layout = gtk_widget_create_pango_layout (GTK_WIDGET (GNOME_CANVAS_ITEM (e_minicard)->canvas), ""); + for (field = E_CONTACT_FULL_NAME; field != E_CONTACT_LAST_SIMPLE_STRING; field++) { + gint this_width; - font = ((GtkWidget *) ((GnomeCanvasItem *) e_minicard)->canvas)->style->font; + if (field == E_CONTACT_FAMILY_NAME || field == E_CONTACT_GIVEN_NAME) + continue; - for(field = E_CARD_SIMPLE_FIELD_FULL_NAME; field != E_CARD_SIMPLE_FIELD_LAST; field++) { - gdouble this_width; - name = g_strdup_printf("%s:", e_card_simple_get_name(e_minicard->simple, field)); - this_width = gdk_text_width(font, name, strlen(name)); + name = g_strdup_printf ("%s:", e_contact_pretty_name (field)); + pango_layout_set_text (layout, name, -1); + pango_layout_get_pixel_size (layout, &this_width, NULL); if (width < this_width) width = this_width; - g_free(name); + g_free (name); } + g_object_unref (layout); return width; } static void -remodel( EMinicard *e_minicard ) +remodel (EMinicard *e_minicard) { - int count = 0; - if ( !(GTK_OBJECT_FLAGS( e_minicard ) & GNOME_CANVAS_ITEM_REALIZED) ) + GnomeCanvasItem *item = GNOME_CANVAS_ITEM (e_minicard); + gint count = 0; + + if (!(item->flags & GNOME_CANVAS_ITEM_REALIZED)) return; - if (e_minicard->simple) { - ECardSimpleField field; + + if (e_minicard->contact) { + EContactField field; GList *list; - char *file_as; - gdouble left_width = -1; + gchar *file_as; + gint left_width = -1; + gboolean is_list = FALSE; + gboolean email_rendered = FALSE; + gboolean has_voice = FALSE, has_fax = FALSE; if (e_minicard->header_text) { - file_as = e_card_simple_get(e_minicard->simple, E_CARD_SIMPLE_FIELD_FILE_AS); - gnome_canvas_item_set( e_minicard->header_text, - "text", file_as ? file_as : "", - NULL ); - g_free(file_as); + file_as = e_contact_get (e_minicard->contact, E_CONTACT_FILE_AS); + gnome_canvas_item_set ( + e_minicard->header_text, + "text", file_as ? file_as : "", + NULL); + g_free (file_as); } - if (e_minicard->card && e_card_evolution_list (e_minicard->card) ) { + if (e_minicard->contact && e_contact_get (e_minicard->contact, E_CONTACT_IS_LIST)) + is_list = TRUE; + + if (is_list) gnome_canvas_item_show (e_minicard->list_icon); - } - else { + else gnome_canvas_item_hide (e_minicard->list_icon); - } list = e_minicard->fields; e_minicard->fields = NULL; - for(field = E_CARD_SIMPLE_FIELD_FULL_NAME; field != E_CARD_SIMPLE_FIELD_LAST_SIMPLE_STRING && count < 5; field++) { + for (field = E_CONTACT_FULL_NAME; field != (E_CONTACT_LAST_SIMPLE_STRING -1) && count < 5; field++) { EMinicardField *minicard_field = NULL; + gboolean is_email = FALSE; + + if (field == E_CONTACT_FAMILY_NAME || field == E_CONTACT_GIVEN_NAME || + (has_voice && field == E_CONTACT_PHONE_OTHER) || + (has_fax && field == E_CONTACT_PHONE_OTHER_FAX)) + continue; + + if (field == E_CONTACT_FULL_NAME && is_list) + continue; + + if (field == E_CONTACT_EMAIL_1 || field == E_CONTACT_EMAIL_2 || field == E_CONTACT_EMAIL_3 || field == E_CONTACT_EMAIL_4) { + if (email_rendered) + continue; + email_rendered = TRUE; + is_email = TRUE; + } if (list) minicard_field = list->data; if (minicard_field && minicard_field->field == field) { GList *this_list = list; - char *string; + gchar *string; - string = e_card_simple_get(e_minicard->simple, field); + string = e_contact_get (e_minicard->contact, field); if (string && *string) { - /* Magically convert embedded XML into an address. */ - if (!strncmp (string, "<?xml", 4)) { - EDestination *dest = e_destination_import (string); - if (dest != NULL) { - gchar *new_string = g_strdup (e_destination_get_address (dest)); - g_free (string); - string = new_string; - gtk_object_unref (GTK_OBJECT (dest)); - } - } - - e_minicard->fields = g_list_append(e_minicard->fields, minicard_field); - gtk_object_set(GTK_OBJECT(minicard_field->label), - "field", string, - NULL); - count ++; + e_minicard->fields = g_list_append (e_minicard->fields, minicard_field); + g_object_set ( + minicard_field->label, + "field", string, + NULL); + count++; } else { - e_minicard_field_destroy(minicard_field); + e_minicard_field_destroy (minicard_field); } - list = g_list_remove_link(list, this_list); - g_list_free_1(this_list); - g_free(string); + list = g_list_delete_link (list, this_list); + g_free (string); } else { - char *string; + gchar *string; if (left_width == -1) { - left_width = get_left_width(e_minicard); + left_width = get_left_width (e_minicard, is_list); } - string = e_card_simple_get(e_minicard->simple, field); - if (string && *string) { - add_field(e_minicard, field, left_width); - count++; + if (is_email) { + GList *email; + gint limit; + + limit = 5 - count; + email = e_contact_get_attributes (e_minicard->contact, E_CONTACT_EMAIL); + add_email_field (e_minicard, email, left_width, limit, is_list); + if (count + limit >5) + count = 5; + else + count = count + g_list_length (email); + g_list_free_full (email, (GDestroyNotify) e_vcard_attribute_free); + } else { + string = e_contact_get (e_minicard->contact, field); + if (string && *string) { + add_field (e_minicard, field, left_width); + count++; + + has_voice = has_voice || + field == E_CONTACT_PHONE_BUSINESS || + field == E_CONTACT_PHONE_BUSINESS_2 || + field == E_CONTACT_PHONE_HOME || + field == E_CONTACT_PHONE_HOME_2; + has_fax = has_fax || + field == E_CONTACT_PHONE_BUSINESS_FAX || + field == E_CONTACT_PHONE_HOME_FAX; + } + g_free (string); } - g_free(string); } } - g_list_foreach(list, (GFunc) e_minicard_field_destroy, NULL); - g_list_free(list); + g_list_foreach (list, (GFunc) e_minicard_field_destroy, NULL); + g_list_free (list); } } static void -e_minicard_reflow( GnomeCanvasItem *item, int flags ) +e_minicard_reflow (GnomeCanvasItem *item, + gint flags) { - EMinicard *e_minicard = E_MINICARD(item); - if ( GTK_OBJECT_FLAGS( e_minicard ) & GNOME_CANVAS_ITEM_REALIZED ) { + EMinicard *e_minicard = E_MINICARD (item); + + if (item->flags & GNOME_CANVAS_ITEM_REALIZED) { GList *list; gdouble text_height; gint old_height; - + old_height = e_minicard->height; - gtk_object_get( GTK_OBJECT( e_minicard->header_text ), - "text_height", &text_height, - NULL ); - + g_object_get ( + e_minicard->header_text, + "text_height", &text_height, + NULL); + e_minicard->height = text_height + 10.0; - - gnome_canvas_item_set( e_minicard->header_rect, - "y2", text_height + 9.0, - NULL ); - - for(list = e_minicard->fields; list; list = g_list_next(list)) { - EMinicardField *field = E_MINICARD_FIELD(list->data); + + gnome_canvas_item_set ( + e_minicard->header_rect, + "y2", text_height + 9.0, + NULL); + + for (list = e_minicard->fields; list; list = g_list_next (list)) { + EMinicardField *field = E_MINICARD_FIELD (list->data); + /* Why not use the item that is passed in? */ GnomeCanvasItem *item = field->label; - gtk_object_get (GTK_OBJECT(item), - "height", &text_height, - NULL); - e_canvas_item_move_absolute(item, 2, e_minicard->height); + g_object_get ( + item, + "height", &text_height, + NULL); + e_canvas_item_move_absolute (item, 2, e_minicard->height); e_minicard->height += text_height; } e_minicard->height += 2; - - gnome_canvas_item_set( e_minicard->rect, - "y2", (double) e_minicard->height - 1, - NULL ); - - gnome_canvas_item_set( e_minicard->rect, - "x2", (double) e_minicard->width - 1.0, - "y2", (double) e_minicard->height - 1.0, - NULL ); - gnome_canvas_item_set( e_minicard->header_rect, - "x2", (double) e_minicard->width - 3.0, - NULL ); + + gnome_canvas_item_set ( + e_minicard->rect, + "x2", (gdouble) e_minicard->width - 1.0, + "y2", (gdouble) e_minicard->height - 1.0, + NULL); + gnome_canvas_item_set ( + e_minicard->header_rect, + "x2", (gdouble) e_minicard->width - 3.0, + NULL); if (old_height != e_minicard->height) - e_canvas_item_request_parent_reflow(item); + e_canvas_item_request_parent_reflow (item); } } -const char * +const gchar * e_minicard_get_card_id (EMinicard *minicard) { - g_return_val_if_fail(minicard != NULL, NULL); - g_return_val_if_fail(E_IS_MINICARD(minicard), NULL); + g_return_val_if_fail (minicard != NULL, NULL); + g_return_val_if_fail (E_IS_MINICARD (minicard), NULL); - if (minicard->card) { - return e_card_get_id(minicard->card); + if (minicard->contact) { + return e_contact_get_const (minicard->contact, E_CONTACT_UID); } else { return ""; } } -int -e_minicard_compare (EMinicard *minicard1, EMinicard *minicard2) +gint +e_minicard_compare (EMinicard *minicard1, + EMinicard *minicard2) { - g_return_val_if_fail(minicard1 != NULL, 0); - g_return_val_if_fail(E_IS_MINICARD(minicard1), 0); - g_return_val_if_fail(minicard2 != NULL, 0); - g_return_val_if_fail(E_IS_MINICARD(minicard2), 0); - - if (minicard1->card && minicard2->card) { - char *file_as1, *file_as2; - gtk_object_get(GTK_OBJECT(minicard1->card), - "file_as", &file_as1, - NULL); - gtk_object_get(GTK_OBJECT(minicard2->card), - "file_as", &file_as2, - NULL); + gint cmp = 0; + + g_return_val_if_fail (minicard1 != NULL, 0); + g_return_val_if_fail (E_IS_MINICARD (minicard1), 0); + g_return_val_if_fail (minicard2 != NULL, 0); + g_return_val_if_fail (E_IS_MINICARD (minicard2), 0); + + if (minicard1->contact && minicard2->contact) { + gchar *file_as1, *file_as2; + g_object_get ( + minicard1->contact, + "file_as", &file_as1, + NULL); + g_object_get ( + minicard2->contact, + "file_as", &file_as2, + NULL); + if (file_as1 && file_as2) - return g_utf8_collate(file_as1, file_as2); - if (file_as1) - return -1; - if (file_as2) - return 1; - return strcmp(e_minicard_get_card_id(minicard1), e_minicard_get_card_id(minicard2)); - } else { - return 0; + cmp = g_utf8_collate (file_as1, file_as2); + else if (file_as1) + cmp = -1; + else if (file_as2) + cmp = 1; + else + cmp = strcmp (e_minicard_get_card_id (minicard1), e_minicard_get_card_id (minicard2)); + + g_free (file_as1); + g_free (file_as2); } + + return cmp; } -int -e_minicard_selected (EMinicard *minicard, GdkEvent *event) +gint +e_minicard_selected (EMinicard *minicard, + GdkEvent *event) { gint ret_val = 0; GnomeCanvasItem *item = GNOME_CANVAS_ITEM (minicard); if (item->parent) { - guint signal_id = gtk_signal_lookup ("selection_event", GTK_OBJECT_TYPE (item->parent)); + guint signal_id = g_signal_lookup ("selection_event", G_OBJECT_TYPE (item->parent)); /* We should probably check the signature here, but I * don't think it's worth the time required to code * it. */ if (signal_id != 0) { - gtk_signal_emit(GTK_OBJECT(item->parent), - signal_id, - item, event, &ret_val); + g_signal_emit ( + item->parent, + signal_id, 0, + item, event, &ret_val); } } return ret_val; } static gint -e_minicard_drag_begin (EMinicard *minicard, GdkEvent *event) +e_minicard_drag_begin (EMinicard *minicard, + GdkEvent *event) { gint ret_val = 0; GnomeCanvasItem *parent; - gtk_signal_emit (GTK_OBJECT(minicard), - e_minicard_signals[DRAG_BEGIN], - event, &ret_val); + g_signal_emit ( + minicard, + signals[DRAG_BEGIN], 0, + event, &ret_val); parent = GNOME_CANVAS_ITEM (minicard)->parent; if (parent && E_IS_REFLOW (parent)) { diff --git a/addressbook/gui/widgets/e-minicard.h b/addressbook/gui/widgets/e-minicard.h index bb6a3c072e..986f47194a 100644 --- a/addressbook/gui/widgets/e-minicard.h +++ b/addressbook/gui/widgets/e-minicard.h @@ -1,56 +1,56 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* e-minicard.h - * Copyright (C) 2000 Ximian, Inc. - * Author: Chris Lahey <clahey@ximian.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. * * 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. + * Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#ifndef __E_MINICARD_H__ -#define __E_MINICARD_H__ - -#include <libgnomeui/gnome-canvas.h> -#include <gdk-pixbuf/gdk-pixbuf.h> -#include "addressbook/gui/contact-editor/e-contact-editor.h" -#include "addressbook/backend/ebook/e-card.h" -#include "addressbook/backend/ebook/e-card-simple.h" - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -/* EMinicard - A small card displaying information about a contact. + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Chris Lahey <clahey@ximian.com> * - * The following arguments are available: + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * - * name type read/write description - * -------------------------------------------------------------------------------- - * width double RW width of the card - * height double R height of the card - * card ECard* RW Pointer to the ECard */ -#define E_MINICARD_TYPE (e_minicard_get_type ()) -#define E_MINICARD(obj) (GTK_CHECK_CAST ((obj), E_MINICARD_TYPE, EMinicard)) -#define E_MINICARD_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_MINICARD_TYPE, EMinicardClass)) -#define E_IS_MINICARD(obj) (GTK_CHECK_TYPE ((obj), E_MINICARD_TYPE)) -#define E_IS_MINICARD_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_MINICARD_TYPE)) +#ifndef E_MINICARD_H +#define E_MINICARD_H + +#include <gtk/gtk.h> +#include <libebook/libebook.h> +#include <libgnomecanvas/libgnomecanvas.h> + +/* Standard GObject macros */ +#define E_TYPE_MINICARD \ + (e_minicard_get_type ()) +#define E_MINICARD(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MINICARD, EMinicard)) +#define E_MINICARD_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MINICARD, EMinicardClass)) +#define E_IS_MINICARD(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MINICARD)) +#define E_IS_MINICARD_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((obj), E_TYPE_MINICARD)) +#define E_MINICARD_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MINICARD, EMinicardClass)) + +G_BEGIN_DECLS + +typedef struct _EMinicard EMinicard; +typedef struct _EMinicardClass EMinicardClass; - -typedef struct _EMinicard EMinicard; -typedef struct _EMinicardClass EMinicardClass; typedef enum _EMinicardFocusType EMinicardFocusType; enum _EMinicardFocusType { @@ -61,20 +61,17 @@ enum _EMinicardFocusType { struct _EMinicard { GnomeCanvasGroup parent; - + /* item specific fields */ - ECard *card; - ECardSimple *simple; - + EContact *contact; + GnomeCanvasItem *rect; GnomeCanvasItem *header_rect; GnomeCanvasItem *header_text; GnomeCanvasItem *list_icon; GdkPixbuf *list_icon_pixbuf; - double list_icon_size; - - GtkObject *editor; + gdouble list_icon_size; GList *fields; /* Of type EMinicardField */ guint needs_remodeling : 1; @@ -94,8 +91,8 @@ struct _EMinicard gint button_x; gint button_y; - double width; - double height; + gdouble width; + gdouble height; }; struct _EMinicardClass @@ -104,20 +101,28 @@ struct _EMinicardClass gint (* selected) (EMinicard *minicard, GdkEvent *event); gint (* drag_begin) (EMinicard *minicard, GdkEvent *event); + void (* open_contact) (EMinicard *minicard, EContact *contact); + + void (* style_set) (EMinicard *minicard, GtkStyle *previous_style); }; +typedef struct _EMinicardField EMinicardField; -GtkType e_minicard_get_type (void); -const char *e_minicard_get_card_id (EMinicard *minicard); -int e_minicard_compare (EMinicard *minicard1, - EMinicard *minicard2); +struct _EMinicardField { + EContactField field; + GnomeCanvasItem *label; +}; -int e_minicard_selected (EMinicard *minicard, - GdkEvent *event); +#define E_MINICARD_FIELD(field) ((EMinicardField *)(field)) -#ifdef __cplusplus -} -#endif /* __cplusplus */ +GType e_minicard_get_type (void); +const gchar * e_minicard_get_card_id (EMinicard *minicard); +gint e_minicard_compare (EMinicard *minicard1, + EMinicard *minicard2); +gint e_minicard_selected (EMinicard *minicard, + GdkEvent *event); +void e_minicard_activate_editor (EMinicard *minicard); +G_END_DECLS -#endif /* __E_MINICARD_H__ */ +#endif /* E_MINICARD_H */ diff --git a/addressbook/gui/widgets/ea-addressbook-view.c b/addressbook/gui/widgets/ea-addressbook-view.c new file mode 100644 index 0000000000..f1c21d1001 --- /dev/null +++ b/addressbook/gui/widgets/ea-addressbook-view.c @@ -0,0 +1,123 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Leon Zhang <leon.zhang@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <glib/gi18n.h> +#include "ea-addressbook-view.h" + +static const gchar * ea_ab_view_get_name (AtkObject *accessible); +static const gchar * ea_ab_view_get_description (AtkObject *accessible); + +static void ea_ab_view_class_init (EAddressbookViewClass *class); + +GType +ea_ab_view_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EAddressbookViewClass), + (GBaseInitFunc) NULL, /* base_init */ + (GBaseFinalizeFunc) NULL, /* base_finalize */ + (GClassInitFunc) ea_ab_view_class_init, + (GClassFinalizeFunc) NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (EAddressbookView), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (GailWidget, in this case) */ + + factory = atk_registry_get_factory ( + atk_get_default_registry (), + GTK_TYPE_EVENT_BOX); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + type = g_type_register_static ( + derived_atk_type, + "EaABView", &tinfo, 0); + } + + return type; +} + +static void +ea_ab_view_class_init (EAddressbookViewClass *class) +{ + AtkObjectClass *atk_object_class; + + atk_object_class = ATK_OBJECT_CLASS (class); + atk_object_class->get_name = ea_ab_view_get_name; + atk_object_class->get_description = ea_ab_view_get_description; +} + +static const gchar * +ea_ab_view_get_name (AtkObject *accessible) +{ + g_return_val_if_fail (EA_IS_AB_VIEW (accessible), NULL); + if (accessible->name) + return accessible->name; + + return _("evolution address book"); +} + +static const gchar * +ea_ab_view_get_description (AtkObject *accessible) +{ + if (accessible->description) + return accessible->description; + + return _("evolution address book"); +} + +AtkObject * +ea_ab_view_new (GObject *obj) +{ + GObject *object; + AtkObject *accessible; + + g_return_val_if_fail (obj != NULL, NULL); + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (obj), NULL); + + object = g_object_new (EA_TYPE_AB_VIEW, NULL); + + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, obj); + accessible->role = ATK_ROLE_CANVAS; + + return accessible; +} diff --git a/addressbook/gui/widgets/ea-addressbook-view.h b/addressbook/gui/widgets/ea-addressbook-view.h new file mode 100644 index 0000000000..55da1d5e37 --- /dev/null +++ b/addressbook/gui/widgets/ea-addressbook-view.h @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Leon Zhang <leon.zhang@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_ADDRESSBOOK_VIEW_H__ +#define __EA_ADDRESSBOOK_VIEW_H__ + +#include <gtk/gtk.h> +#include "e-addressbook-view.h" + +G_BEGIN_DECLS + +#define EA_TYPE_AB_VIEW (ea_ab_view_get_type ()) +#define EA_AB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_AB_VIEW, EaABView)) +#define EA_AB_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_AB_VIEW, EaABViewClass)) +#define EA_IS_AB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_AB_VIEW)) +#define EA_IS_AB_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EA_TYPE_AB_VIEW)) + +typedef struct _EaABView EaABView; +typedef struct _EaABViewClass EaABViewClass; + +struct _EaABView +{ + GtkAccessible parent; +}; + +struct _EaABViewClass +{ + GtkAccessibleClass parent_class; +}; + +GType ea_ab_view_get_type (void); +AtkObject * ea_ab_view_new (GObject *obj); + +G_END_DECLS + +#endif /* __EA_ADDRESSBOOK_VIEW_H__ */ diff --git a/addressbook/gui/widgets/ea-addressbook.c b/addressbook/gui/widgets/ea-addressbook.c new file mode 100644 index 0000000000..51af22d0d4 --- /dev/null +++ b/addressbook/gui/widgets/ea-addressbook.c @@ -0,0 +1,90 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Leon Zhang <leon.zhang@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "e-util/e-util.h" + +#include "ea-addressbook.h" +#include "ea-minicard.h" +#include "ea-minicard-view.h" +#include "ea-addressbook-view.h" + +EA_FACTORY_GOBJECT (EA_TYPE_MINICARD, ea_minicard, ea_minicard_new) +EA_FACTORY_GOBJECT (EA_TYPE_MINICARD_VIEW, ea_minicard_view, ea_minicard_view_new) +EA_FACTORY_GOBJECT (EA_TYPE_AB_VIEW, ea_ab_view, ea_ab_view_new) + +static gboolean ea_addressbook_focus_watcher (GSignalInvocationHint *ihint, + guint n_param_values, + const GValue *param_values, + gpointer data); + +void e_minicard_a11y_init (void) +{ + EA_SET_FACTORY (e_minicard_get_type (), ea_minicard); +} + +void e_minicard_view_a11y_init (void) +{ + EA_SET_FACTORY (e_minicard_view_get_type (), ea_minicard_view); + + if (atk_get_root ()) { + g_signal_add_emission_hook ( + g_signal_lookup ("event", + e_minicard_get_type ()), + 0, ea_addressbook_focus_watcher, + NULL, (GDestroyNotify) NULL); + } +} + +void eab_view_a11y_init (void) +{ + EA_SET_FACTORY (E_TYPE_ADDRESSBOOK_VIEW, ea_ab_view); +} + +static gboolean +ea_addressbook_focus_watcher (GSignalInvocationHint *ihint, + guint n_param_values, + const GValue *param_values, + gpointer data) +{ + GObject *object; + GdkEvent *event; + AtkObject *ea_event = NULL; + + object = g_value_get_object (param_values + 0); + event = g_value_get_boxed (param_values + 1); + + if (E_IS_MINICARD (object)) { + GnomeCanvasItem *item = GNOME_CANVAS_ITEM (object); + ea_event = atk_gobject_accessible_for_object (object); + if (event->type == GDK_FOCUS_CHANGE) { + if ((event->focus_change.in) && + (E_IS_MINICARD (item->canvas->focused_item))) + atk_focus_tracker_notify (ea_event); + } + } + + return TRUE; +} diff --git a/addressbook/gui/widgets/ea-addressbook.h b/addressbook/gui/widgets/ea-addressbook.h new file mode 100644 index 0000000000..97b691dc18 --- /dev/null +++ b/addressbook/gui/widgets/ea-addressbook.h @@ -0,0 +1,33 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Leon Zhang <leon.zhang@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/* Evolution Accessibility +*/ + +#ifndef _EA_ADDRESSBOOK_H__ +#define _EA_ADDRESSBOOK_H__ + +void eab_view_a11y_init (void); +void e_minicard_view_a11y_init (void); +void e_minicard_a11y_init (void); + +#endif /* _EA_ADDRESSBOOK_H__ */ diff --git a/addressbook/gui/widgets/ea-minicard-view.c b/addressbook/gui/widgets/ea-minicard-view.c new file mode 100644 index 0000000000..d1592df69e --- /dev/null +++ b/addressbook/gui/widgets/ea-minicard-view.c @@ -0,0 +1,446 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Leon Zhang < leon.zhang@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <gtk/gtk.h> +#include <glib/gi18n.h> +#include "ea-minicard.h" +#include "ea-minicard-view.h" +#include "eab-gui-util.h" +#include "e-addressbook-view.h" + +static const gchar * action_name[] = { + N_("New Contact"), + N_("New Contact List") +}; + +static const gchar * ea_minicard_view_get_name (AtkObject *accessible); +static const gchar * ea_minicard_view_get_description (AtkObject *accessible); + +static void ea_minicard_view_class_init (EaMinicardViewClass *klass); + +static gint ea_minicard_view_get_n_children (AtkObject *obj); +static AtkObject *ea_minicard_view_ref_child (AtkObject *obj, gint i); + +static AtkStateSet *ea_minicard_view_ref_state_set (AtkObject *obj); + +static void atk_selection_interface_init (AtkSelectionIface *iface); +static gboolean selection_interface_add_selection (AtkSelection *selection, + gint i); +static gboolean selection_interface_clear_selection (AtkSelection *selection); +static AtkObject * selection_interface_ref_selection (AtkSelection *selection, + gint i); +static gint selection_interface_get_selection_count (AtkSelection *selection); +static gboolean selection_interface_is_child_selected (AtkSelection *selection, + gint i); + +static void atk_action_interface_init (AtkActionIface *iface); +static gboolean atk_action_interface_do_action (AtkAction *iface, gint i); +static gint atk_action_interface_get_n_action (AtkAction *iface); +static const gchar * + atk_action_interface_get_description + (AtkAction *iface, + gint i); +static const gchar * + atk_action_interface_get_name (AtkAction *iface, + gint i); + +static gpointer parent_class = NULL; + +GType +ea_minicard_view_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaMinicardViewClass), + (GBaseInitFunc) NULL, /* base_init */ + (GBaseFinalizeFunc) NULL, /* base_finalize */ + (GClassInitFunc) ea_minicard_view_class_init, + (GClassFinalizeFunc) NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (EaMinicardView), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + static const GInterfaceInfo atk_selection_info = { + (GInterfaceInitFunc) atk_selection_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + static const GInterfaceInfo atk_action_info = { + (GInterfaceInitFunc) atk_action_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (GailWidget, in this case) */ + + factory = atk_registry_get_factory ( + atk_get_default_registry (), + GNOME_TYPE_CANVAS_GROUP); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + type = g_type_register_static ( + derived_atk_type, + "EaMinicardView", &tinfo, 0); + g_type_add_interface_static ( + type, ATK_TYPE_SELECTION, + &atk_selection_info); + g_type_add_interface_static ( + type, ATK_TYPE_ACTION, + &atk_action_info); + + } + + return type; +} + +static void +ea_minicard_view_class_init (EaMinicardViewClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_minicard_view_get_name; + class->get_description = ea_minicard_view_get_description; + class->ref_state_set = ea_minicard_view_ref_state_set; + class->get_n_children = ea_minicard_view_get_n_children; + class->ref_child = ea_minicard_view_ref_child; +} + +static const gchar * +ea_minicard_view_get_name (AtkObject *accessible) +{ + EReflow *reflow; + gchar *string; + EMinicardView *card_view; + EBookClient *book_client = NULL; + ESource *source; + const gchar *display_name; + + g_return_val_if_fail (EA_IS_MINICARD_VIEW (accessible), NULL); + + reflow = E_REFLOW (atk_gobject_accessible_get_object ( + ATK_GOBJECT_ACCESSIBLE (accessible))); + + if (!reflow) + return NULL; + + /* Get the current name of minicard view*/ + card_view = E_MINICARD_VIEW (reflow); + g_object_get (card_view->adapter, "client", &book_client, NULL); + g_return_val_if_fail (E_IS_BOOK_CLIENT (book_client), NULL); + source = e_client_get_source (E_CLIENT (book_client)); + display_name = e_source_get_display_name (source); + if (display_name == NULL) + display_name = ""; + + string = g_strdup_printf ( + ngettext ("current address book folder %s has %d card", + "current address book folder %s has %d cards", + reflow->count), display_name, reflow->count); + + ATK_OBJECT_CLASS (parent_class)->set_name (accessible, string); + g_free (string); + g_object_unref (book_client); + return accessible->name; +} + +static const gchar * +ea_minicard_view_get_description (AtkObject *accessible) +{ + g_return_val_if_fail (EA_IS_MINICARD_VIEW (accessible), NULL); + if (accessible->description) + return accessible->description; + + return _("evolution address book"); +} + +AtkObject * +ea_minicard_view_new (GObject *obj) +{ + GObject *object; + AtkObject *accessible; + + g_return_val_if_fail (E_IS_MINICARD_VIEW (obj), NULL); + object = g_object_new (EA_TYPE_MINICARD_VIEW, NULL); + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, obj); + accessible->role = ATK_ROLE_PANEL; + return accessible; +} + +static gint +ea_minicard_view_get_n_children (AtkObject *accessible) +{ + EReflow *reflow; + + gint child_num = 0; + + g_return_val_if_fail (EA_IS_MINICARD_VIEW (accessible), -1); + + reflow = E_REFLOW (atk_gobject_accessible_get_object ( + ATK_GOBJECT_ACCESSIBLE (accessible))); + + if (!reflow) + return -1; + + child_num = reflow->count; + + return child_num; +} + +static AtkStateSet *ea_minicard_view_ref_state_set (AtkObject *obj) +{ + AtkStateSet *state_set = NULL; + GObject *gobj = NULL; + + state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (obj); + if (!state_set) + state_set = atk_state_set_new (); + + gobj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (obj)); + if (!gobj) + return state_set; + + atk_state_set_add_state (state_set, ATK_STATE_ENABLED); + atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (state_set, ATK_STATE_SHOWING); + + return state_set; +} + +static AtkObject * +ea_minicard_view_ref_child (AtkObject *accessible, + gint index) +{ + EReflow *reflow; + gint child_num; + AtkObject *atk_object = NULL; + EMinicard *card = NULL; + + g_return_val_if_fail (EA_IS_MINICARD_VIEW (accessible), NULL); + + child_num = atk_object_get_n_accessible_children (accessible); + if (child_num <= 0 || index < 0 || index >= child_num) + return NULL; + + reflow = E_REFLOW (atk_gobject_accessible_get_object ( + ATK_GOBJECT_ACCESSIBLE (accessible))); + if (!reflow) + return NULL; + if (!reflow->items) + return NULL; + /* a minicard */ + if (index < child_num) { + if (reflow->items[index] == NULL) { + reflow->items[index] = e_reflow_model_incarnate (reflow->model, index, GNOME_CANVAS_GROUP (reflow)); + g_object_set ( + reflow->items[index], + "width", (double) reflow->column_width, + NULL); + } + card = E_MINICARD (reflow->items[index]); + atk_object = atk_gobject_accessible_for_object (G_OBJECT (card)); + } else { + return NULL; + } + + g_object_ref (atk_object); + return atk_object; +} + +/* atkselection interface */ + +static void +atk_selection_interface_init (AtkSelectionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->add_selection = selection_interface_add_selection; + iface->clear_selection = selection_interface_clear_selection; + iface->ref_selection = selection_interface_ref_selection; + iface->get_selection_count = selection_interface_get_selection_count; + iface->is_child_selected = selection_interface_is_child_selected; +} + +static gboolean +selection_interface_add_selection (AtkSelection *selection, + gint i) +{ + AtkGObjectAccessible *atk_gobj= NULL; + EReflow *reflow = NULL; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (selection); + reflow = E_REFLOW (atk_gobject_accessible_get_object (atk_gobj)); + + if (!reflow) + return FALSE; + + selection_interface_clear_selection (selection); + e_selection_model_select_single_row (reflow->selection, i); + + return TRUE; +} + +static gboolean +selection_interface_clear_selection (AtkSelection *selection) +{ + AtkGObjectAccessible *atk_gobj = NULL; + EReflow *reflow = NULL; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (selection); + reflow = E_REFLOW (atk_gobject_accessible_get_object (atk_gobj)); + + if (!reflow) + return FALSE; + + e_selection_model_clear (reflow->selection); + + return TRUE; +} + +static AtkObject * +selection_interface_ref_selection (AtkSelection *selection, + gint i) +{ + return ea_minicard_view_ref_child (ATK_OBJECT (selection), i); +} + +static gint +selection_interface_get_selection_count (AtkSelection *selection) +{ + AtkGObjectAccessible *atk_gobj = NULL; + EReflow *reflow = NULL; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (selection); + reflow = E_REFLOW (atk_gobject_accessible_get_object (atk_gobj)); + + if (!reflow) + return FALSE; + + return e_selection_model_selected_count (reflow->selection); +} + +static gboolean +selection_interface_is_child_selected (AtkSelection *selection, + gint i) +{ + AtkGObjectAccessible *atk_gobj = NULL; + EReflow *reflow = NULL; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (selection); + reflow = E_REFLOW (atk_gobject_accessible_get_object (atk_gobj)); + + if (!reflow) + return FALSE; + + return e_selection_model_is_row_selected (reflow->selection, i); +} + +static void atk_action_interface_init (AtkActionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->do_action = atk_action_interface_do_action; + iface->get_n_actions = atk_action_interface_get_n_action; + iface->get_description = atk_action_interface_get_description; + iface->get_name = atk_action_interface_get_name; +} + +static gboolean +atk_action_interface_do_action (AtkAction *action, + gint i) +{ + gboolean return_value = TRUE; + EMinicardView *card_view; + + AtkGObjectAccessible *atk_gobj= NULL; + EReflow *reflow = NULL; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (action); + reflow = E_REFLOW (atk_gobject_accessible_get_object (atk_gobj)); + + if (reflow == NULL) + return FALSE; + + card_view = E_MINICARD_VIEW (reflow); + + switch (i) { + case 0: + /* New Contact */ + e_minicard_view_create_contact (card_view); + break; + case 1: + /* New Contact List */ + e_minicard_view_create_contact_list (card_view); + break; + default: + return_value = FALSE; + break; + } + + return return_value; +} + +static gint +atk_action_interface_get_n_action (AtkAction *iface) +{ + return G_N_ELEMENTS (action_name); +} + +static const gchar * +atk_action_interface_get_description (AtkAction *iface, + gint i) +{ + return atk_action_interface_get_name (iface, i); +} + +static const gchar * +atk_action_interface_get_name (AtkAction *iface, + gint i) +{ + if (i >= G_N_ELEMENTS (action_name) || i < 0) + return NULL; + + return action_name[i]; +} + diff --git a/addressbook/gui/widgets/ea-minicard-view.h b/addressbook/gui/widgets/ea-minicard-view.h new file mode 100644 index 0000000000..889674bb92 --- /dev/null +++ b/addressbook/gui/widgets/ea-minicard-view.h @@ -0,0 +1,56 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Leon Zhang <leon.zhang@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_MINICARD_VIEW_H__ +#define __EA_MINICARD_VIEW_H__ + +#include <atk/atkgobjectaccessible.h> +#include "e-minicard-view.h" + +G_BEGIN_DECLS + +#define EA_TYPE_MINICARD_VIEW (ea_minicard_view_get_type ()) +#define EA_MINICARD_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_MINICARD_VIEW, EaMinicardView)) +#define EA_MINICARD_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_MINICARD_VIEW, EaMiniCardViewClass)) +#define EA_IS_MINICARD_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_MINICARD_VIEW)) +#define EA_IS_MINICARD_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EA_TYPE_MINICARD_VIEW)) + +typedef struct _EaMinicardView EaMinicardView; +typedef struct _EaMinicardViewClass EaMinicardViewClass; + +struct _EaMinicardView +{ + AtkGObjectAccessible parent; +}; + +struct _EaMinicardViewClass +{ + AtkGObjectAccessibleClass parent_class; +}; + +GType ea_minicard_view_get_type (void); + +AtkObject * ea_minicard_view_new (GObject *obj); + +G_END_DECLS + +#endif /* __EA_MINICARD_VIEW_H__ */ diff --git a/addressbook/gui/widgets/ea-minicard.c b/addressbook/gui/widgets/ea-minicard.c new file mode 100644 index 0000000000..cfa35db349 --- /dev/null +++ b/addressbook/gui/widgets/ea-minicard.c @@ -0,0 +1,303 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Leon Zhang <leon.zhang@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <glib/gi18n.h> +#include "ea-minicard.h" +#include "ea-minicard-view.h" +#include "e-minicard.h" + +static const gchar * action_name[] = { + N_("Open") +}; + +static const gchar * + ea_minicard_get_name (AtkObject *accessible); +static const gchar * + ea_minicard_get_description (AtkObject *accessible); + +static void ea_minicard_class_init (EaMinicardClass *klass); + +static gint ea_minicard_get_n_children (AtkObject *obj); +static AtkObject * + ea_minicard_ref_child (AtkObject *obj, + gint i); + +static AtkStateSet * + ea_minicard_ref_state_set (AtkObject *obj); + +static void atk_action_interface_init (AtkActionIface *iface); +static gboolean atk_action_interface_do_action (AtkAction *iface, + gint i); +static gint atk_action_interface_get_n_action + (AtkAction *iface); +static const gchar * + atk_action_interface_get_description + (AtkAction *iface, + gint i); +static const gchar * + atk_action_interface_get_name (AtkAction *iface, + gint i); + +static gpointer parent_class = NULL; + +GType +ea_minicard_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaMinicardClass), + (GBaseInitFunc) NULL, /* base_init */ + (GBaseFinalizeFunc) NULL, /* base_finalize */ + (GClassInitFunc) ea_minicard_class_init, + (GClassFinalizeFunc) NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (EaMinicard), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + static const GInterfaceInfo atk_action_info = { + (GInterfaceInitFunc) atk_action_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (GailWidget, in this case) + */ + + factory = atk_registry_get_factory ( + atk_get_default_registry (), + GNOME_TYPE_CANVAS_GROUP); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + type = g_type_register_static ( + derived_atk_type, + "EaMinicard", &tinfo, 0); + g_type_add_interface_static ( + type, ATK_TYPE_ACTION, + &atk_action_info); + } + + return type; +} + +static void +ea_minicard_class_init (EaMinicardClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_minicard_get_name; + class->get_description = ea_minicard_get_description; + class->ref_state_set = ea_minicard_ref_state_set; + class->get_n_children = ea_minicard_get_n_children; + class->ref_child = ea_minicard_ref_child; +} + +/* + * we access the main content of current minicard, including + * header text, label(field, field name) + */ +static const gchar * +ea_minicard_get_name (AtkObject *accessible) +{ +#define BUFFERSIZE 500 + + static gchar name[BUFFERSIZE + 1]; + GString *new_str = g_string_new (NULL); + gchar *string; + EMinicard *card; + + g_return_val_if_fail (EA_IS_MINICARD (accessible), NULL); + memset (name, '\0', BUFFERSIZE); + + card = E_MINICARD ( + atk_gobject_accessible_get_object ( + ATK_GOBJECT_ACCESSIBLE (accessible))); + if (!card) + return NULL; + + g_object_get (card->header_text, "text", &string, NULL); + + if (e_contact_get (card->contact, E_CONTACT_IS_LIST)) + g_string_append (new_str, _("Contact List: ")); + else g_string_append (new_str, _("Contact: ")); + + /* get header of current card */ + g_string_append (new_str, string); + g_free (string); + + /* if there exist no enough space for remain info, return */ + if (new_str->len >= BUFFERSIZE) { + strncpy (name, new_str->str, BUFFERSIZE); + name[BUFFERSIZE] = '\0'; + return name; + } + + strcpy (name, new_str->str); + g_string_free (new_str, TRUE); + + ATK_OBJECT_CLASS (parent_class)->set_name (accessible, name); + + return accessible->name; +} + +static const gchar * +ea_minicard_get_description (AtkObject *accessible) +{ + if (accessible->description) + return accessible->description; + + return _("evolution minicard"); +} + +AtkObject * +ea_minicard_new (GObject *obj) +{ + GObject *object; + AtkObject *accessible; + + g_return_val_if_fail (obj != NULL, NULL); + g_return_val_if_fail (E_IS_MINICARD (obj), NULL); + + object = g_object_new (EA_TYPE_MINICARD, NULL); + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, obj); + + accessible->role = ATK_ROLE_PANEL; + return accessible; +} + +static AtkStateSet * +ea_minicard_ref_state_set (AtkObject *obj) +{ + AtkStateSet *state_set = NULL; + GObject *gobj = NULL; + + state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (obj); + if (!state_set) + state_set = atk_state_set_new (); + + gobj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (obj)); + if (!gobj) + return state_set; + + atk_state_set_add_state (state_set, ATK_STATE_SELECTABLE); + atk_state_set_add_state (state_set, ATK_STATE_ENABLED); + atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (state_set, ATK_STATE_SHOWING); + + return state_set; +} + +static gint +ea_minicard_get_n_children (AtkObject *accessible) +{ + return 0; +} + +static AtkObject * +ea_minicard_ref_child (AtkObject *accessible, + gint index) +{ + return NULL; +} + +static void +atk_action_interface_init (AtkActionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->do_action = atk_action_interface_do_action; + iface->get_n_actions = atk_action_interface_get_n_action; + iface->get_description = atk_action_interface_get_description; + iface->get_name = atk_action_interface_get_name; +} + +static gboolean +atk_action_interface_do_action (AtkAction *iface, + gint i) +{ + EMinicard *minicard = NULL; + + minicard = E_MINICARD ( + atk_gobject_accessible_get_object ( + ATK_GOBJECT_ACCESSIBLE (iface))); + if (minicard == NULL) + return FALSE; + + if (i >= G_N_ELEMENTS (action_name) || i < 0) + return FALSE; + + switch (i) { + /* open card */ + case 0: + e_minicard_activate_editor (minicard); + break; + default: + return FALSE; + } + + return TRUE; +} + +static gint +atk_action_interface_get_n_action (AtkAction *iface) +{ + return G_N_ELEMENTS (action_name); +} + +static const gchar * +atk_action_interface_get_description (AtkAction *iface, + gint i) +{ + return atk_action_interface_get_name (iface, i); +} + +static const gchar * +atk_action_interface_get_name (AtkAction *iface, + gint i) +{ + if (i >= G_N_ELEMENTS (action_name) || i < 0) + return NULL; + + return action_name[i]; +} + diff --git a/addressbook/gui/widgets/ea-minicard.h b/addressbook/gui/widgets/ea-minicard.h new file mode 100644 index 0000000000..ea27158011 --- /dev/null +++ b/addressbook/gui/widgets/ea-minicard.h @@ -0,0 +1,56 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Leon Zhang <leon.zhang@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_MINICARD_H__ +#define __EA_MINICARD_H__ + +#include <atk/atkgobjectaccessible.h> +#include "e-minicard.h" +#include "e-minicard-label.h" + +G_BEGIN_DECLS + +#define EA_TYPE_MINICARD (ea_minicard_get_type ()) +#define EA_MINICARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_MINICARD, EaMinicard)) +#define EA_MINICARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_MINICARD, EaMiniCardClass)) +#define EA_IS_MINICARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_MINICARD)) +#define EA_IS_MINICARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EA_TYPE_MINICARD)) + +typedef struct _EaMinicard EaMinicard; +typedef struct _EaMinicardClass EaMinicardClass; + +struct _EaMinicard +{ + AtkGObjectAccessible parent; +}; + +struct _EaMinicardClass +{ + AtkGObjectAccessibleClass parent_class; +}; + +GType ea_minicard_get_type (void); +AtkObject * ea_minicard_new (GObject *obj); + +G_END_DECLS + +#endif /* __EA_MINICARD_H__ */ diff --git a/addressbook/gui/widgets/eab-config.c b/addressbook/gui/widgets/eab-config.c new file mode 100644 index 0000000000..ad15f1cca9 --- /dev/null +++ b/addressbook/gui/widgets/eab-config.c @@ -0,0 +1,160 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * David Trowbridge <trowbrds@cs.colorado.edu> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "eab-config.h" + +#define EAB_CONFIG_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EAB_TYPE_CONFIG, EABConfigPrivate)) + +struct _EABConfigPrivate { + guint source_changed_id; +}; + +G_DEFINE_TYPE (EABConfig, eab_config, E_TYPE_CONFIG) + +static void +eab_config_init (EABConfig *cfg) +{ + cfg->priv = EAB_CONFIG_GET_PRIVATE (cfg); +} + +static void +ecp_target_free (EConfig *ec, + EConfigTarget *t) +{ + struct _EABConfigPrivate *p = EAB_CONFIG (ec)->priv; + + if (ec->target == t) { + switch (t->type) { + case EAB_CONFIG_TARGET_SOURCE: { + EABConfigTargetSource *s = (EABConfigTargetSource *) t; + + if (p->source_changed_id) { + g_signal_handler_disconnect (s->source, p->source_changed_id); + p->source_changed_id = 0; + } + break; } + case EAB_CONFIG_TARGET_PREFS: + break; + } + } + + switch (t->type) { + case EAB_CONFIG_TARGET_SOURCE: { + EABConfigTargetSource *s = (EABConfigTargetSource *) t; + + if (s->source) + g_object_unref (s->source); + break; } + case EAB_CONFIG_TARGET_PREFS: { + EABConfigTargetPrefs *s = (EABConfigTargetPrefs *) t; + + if (s->settings) + g_object_unref (s->settings); + break; } + } + + ((EConfigClass *) eab_config_parent_class)->target_free (ec, t); +} + +static void +ecp_source_changed (ESource *source, + EConfig *ec) +{ + e_config_target_changed (ec, E_CONFIG_TARGET_CHANGED_STATE); +} + +static void +ecp_set_target (EConfig *ec, + EConfigTarget *t) +{ + struct _EABConfigPrivate *p = EAB_CONFIG_GET_PRIVATE (ec); + + ((EConfigClass *) eab_config_parent_class)->set_target (ec, t); + + if (t) { + switch (t->type) { + case EAB_CONFIG_TARGET_SOURCE: { + EABConfigTargetSource *s = (EABConfigTargetSource *) t; + + p->source_changed_id = g_signal_connect ( + s->source, "changed", + G_CALLBACK (ecp_source_changed), ec); + break; } + case EAB_CONFIG_TARGET_PREFS: + break; + } + } +} + +static void +eab_config_class_init (EABConfigClass *class) +{ + EConfigClass *config_class; + + g_type_class_add_private (class, sizeof (struct _EABConfigPrivate)); + + config_class = E_CONFIG_CLASS (class); + config_class->set_target = ecp_set_target; + config_class->target_free = ecp_target_free; +} + +EABConfig * +eab_config_new (const gchar *menuid) +{ + EABConfig *ecp = g_object_new (eab_config_get_type (), NULL); + e_config_construct (&ecp->config, menuid); + return ecp; +} + +EABConfigTargetSource * +eab_config_target_new_source (EABConfig *ecp, + ESource *source) +{ + EABConfigTargetSource *t = e_config_target_new ( + &ecp->config, EAB_CONFIG_TARGET_SOURCE, sizeof (*t)); + + t->source = source; + g_object_ref (source); + + return t; +} + +EABConfigTargetPrefs * +eab_config_target_new_prefs (EABConfig *ecp, + GSettings *settings) +{ + EABConfigTargetPrefs *t = e_config_target_new ( + &ecp->config, EAB_CONFIG_TARGET_PREFS, sizeof (*t)); + + if (settings) + t->settings = g_object_ref (settings); + else + t->settings = NULL; + + return t; +} diff --git a/addressbook/gui/widgets/eab-config.h b/addressbook/gui/widgets/eab-config.h new file mode 100644 index 0000000000..55612ec65a --- /dev/null +++ b/addressbook/gui/widgets/eab-config.h @@ -0,0 +1,82 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * David Trowbridge <trowbrds@cs.colorado.edu> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EAB_CONFIG_H__ +#define __EAB_CONFIG_H__ + +#include <libedataserver/libedataserver.h> + +#include <e-util/e-util.h> + +#define EAB_TYPE_CONFIG (eab_config_get_type ()) +#define EAB_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EAB_TYPE_CONFIG, EABConfig)) + +G_BEGIN_DECLS + +typedef struct _EABConfig EABConfig; +typedef struct _EABConfigClass EABConfigClass; +typedef struct _EABConfigPrivate EABConfigPrivate; + +struct _EABConfig { + EConfig config; + + EABConfigPrivate *priv; +}; + +struct _EABConfigClass { + EConfigClass config_class; +}; + +enum _eab_config_target_t { + EAB_CONFIG_TARGET_SOURCE, + EAB_CONFIG_TARGET_PREFS +}; + +typedef struct _EABConfigTargetSource EABConfigTargetSource; + +struct _EABConfigTargetSource { + EConfigTarget target; + + ESource *source; +}; + +typedef struct _EABConfigTargetPrefs EABConfigTargetPrefs; + +struct _EABConfigTargetPrefs { + EConfigTarget target; + + /* preferences are global from GSettings */ + GSettings *settings; +}; + +typedef struct _EConfigItem EABConfigItem; + +GType eab_config_get_type (void); +EABConfig *eab_config_new (const gchar *menuid); + +EABConfigTargetSource *eab_config_target_new_source (EABConfig *ecp, ESource *source); +EABConfigTargetPrefs *eab_config_target_new_prefs (EABConfig *ecp, GSettings *settings); + +G_END_DECLS + +#endif diff --git a/addressbook/gui/widgets/eab-contact-display.c b/addressbook/gui/widgets/eab-contact-display.c new file mode 100644 index 0000000000..c467e385e4 --- /dev/null +++ b/addressbook/gui/widgets/eab-contact-display.c @@ -0,0 +1,626 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Chris Toshok <toshok@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "eab-contact-display.h" + +#include <string.h> +#include <glib/gi18n.h> + +#include <webkit/webkit.h> + +#include "e-contact-map.h" +#include "eab-contact-formatter.h" +#include "eab-gui-util.h" + +#define EAB_CONTACT_DISPLAY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EAB_TYPE_CONTACT_DISPLAY, EABContactDisplayPrivate)) + +#define TEXT_IS_RIGHT_TO_LEFT \ + (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL) + +struct _EABContactDisplayPrivate { + EContact *contact; + + EABContactDisplayMode mode; + gboolean show_maps; +}; + +enum { + PROP_0, + PROP_CONTACT, + PROP_MODE, + PROP_SHOW_MAPS +}; + +enum { + SEND_MESSAGE, + LAST_SIGNAL +}; + +static const gchar *ui = +"<ui>" +" <popup name='context'>" +" <placeholder name='custom-actions-1'>" +" <menuitem action='contact-send-message'/>" +" </placeholder>" +" <placeholder name='custom-actions-2'>" +" <menuitem action='contact-mailto-copy'/>" +" </placeholder>" +" </popup>" +"</ui>"; + +static guint signals[LAST_SIGNAL]; + +G_DEFINE_TYPE ( + EABContactDisplay, + eab_contact_display, + E_TYPE_WEB_VIEW) + +static void +contact_display_emit_send_message (EABContactDisplay *display, + gint email_num) +{ + EDestination *destination; + EContact *contact; + + g_return_if_fail (email_num >= 0); + + destination = e_destination_new (); + contact = eab_contact_display_get_contact (display); + e_destination_set_contact (destination, contact, email_num); + g_signal_emit (display, signals[SEND_MESSAGE], 0, destination); + g_object_unref (destination); +} + +static void +action_contact_mailto_copy_cb (GtkAction *action, + EABContactDisplay *display) +{ + GtkClipboard *clipboard; + EWebView *web_view; + EContact *contact; + GList *list; + const gchar *text; + const gchar *uri; + gint index; + + web_view = E_WEB_VIEW (display); + uri = e_web_view_get_selected_uri (web_view); + g_return_if_fail (uri != NULL); + + index = atoi (uri + strlen ("internal-mailto:")); + g_return_if_fail (index >= 0); + + contact = eab_contact_display_get_contact (display); + list = e_contact_get (contact, E_CONTACT_EMAIL); + text = g_list_nth_data (list, index); + + clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); + gtk_clipboard_set_text (clipboard, text, -1); + gtk_clipboard_store (clipboard); + + g_list_foreach (list, (GFunc) g_free, NULL); + g_list_free (list); +} + +static void +action_contact_send_message_cb (GtkAction *action, + EABContactDisplay *display) +{ + EWebView *web_view; + const gchar *uri; + gint index; + + web_view = E_WEB_VIEW (display); + uri = e_web_view_get_selected_uri (web_view); + g_return_if_fail (uri != NULL); + + index = atoi (uri + strlen ("internal-mailto:")); + contact_display_emit_send_message (display, index); +} + +static GtkActionEntry internal_mailto_entries[] = { + + { "contact-mailto-copy", + GTK_STOCK_COPY, + N_("Copy _Email Address"), + NULL, + N_("Copy the email address to the clipboard"), + G_CALLBACK (action_contact_mailto_copy_cb) }, + + { "contact-send-message", + "mail-message-new", + N_("_Send New Message To..."), + NULL, + N_("Send a mail message to this address"), + G_CALLBACK (action_contact_send_message_cb) } +}; + +static void +load_contact (EABContactDisplay *display) +{ + EABContactFormatter *formatter; + GString *buffer; + + if (!display->priv->contact) { + e_web_view_clear (E_WEB_VIEW (display)); + return; + } + + formatter = eab_contact_formatter_new (); + g_object_set ( + G_OBJECT (formatter), + "display-mode", display->priv->mode, + "render-maps", display->priv->show_maps, + NULL); + + buffer = g_string_sized_new (1024); + + eab_contact_formatter_format_contact ( + formatter, display->priv->contact, buffer); + e_web_view_load_string (E_WEB_VIEW (display), buffer->str); + + g_string_free (buffer, TRUE); + + g_object_unref (formatter); +} + +static void +contact_display_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CONTACT: + eab_contact_display_set_contact ( + EAB_CONTACT_DISPLAY (object), + g_value_get_object (value)); + return; + + case PROP_MODE: + eab_contact_display_set_mode ( + EAB_CONTACT_DISPLAY (object), + g_value_get_int (value)); + return; + + case PROP_SHOW_MAPS: + eab_contact_display_set_show_maps ( + EAB_CONTACT_DISPLAY (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +contact_display_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CONTACT: + g_value_set_object ( + value, eab_contact_display_get_contact ( + EAB_CONTACT_DISPLAY (object))); + return; + + case PROP_MODE: + g_value_set_int ( + value, eab_contact_display_get_mode ( + EAB_CONTACT_DISPLAY (object))); + return; + + case PROP_SHOW_MAPS: + g_value_set_boolean ( + value, eab_contact_display_get_show_maps ( + EAB_CONTACT_DISPLAY (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +contact_display_dispose (GObject *object) +{ + EABContactDisplayPrivate *priv; + + priv = EAB_CONTACT_DISPLAY_GET_PRIVATE (object); + + if (priv->contact != NULL) { + g_object_unref (priv->contact); + priv->contact = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (eab_contact_display_parent_class)->dispose (object); +} + +static void +contact_display_hovering_over_link (EWebView *web_view, + const gchar *title, + const gchar *uri) +{ + EWebViewClass *web_view_class; + EABContactDisplay *display; + EContact *contact; + const gchar *name; + gchar *message; + + if (uri == NULL || *uri == '\0') + goto chainup; + + if (!g_str_has_prefix (uri, "internal-mailto:")) + goto chainup; + + display = EAB_CONTACT_DISPLAY (web_view); + contact = eab_contact_display_get_contact (display); + + name = e_contact_get_const (contact, E_CONTACT_FILE_AS); + if (name == NULL) + e_contact_get_const (contact, E_CONTACT_FULL_NAME); + g_return_if_fail (name != NULL); + + message = g_strdup_printf (_("Click to mail %s"), name); + e_web_view_status_message (web_view, message); + g_free (message); + + return; + +chainup: + /* Chain up to parent's hovering_over_link() method. */ + web_view_class = E_WEB_VIEW_CLASS (eab_contact_display_parent_class); + web_view_class->hovering_over_link (web_view, title, uri); +} + +static void +contact_display_link_clicked (EWebView *web_view, + const gchar *uri) +{ + EABContactDisplay *display; + gsize length; + + display = EAB_CONTACT_DISPLAY (web_view); + + length = strlen ("internal-mailto:"); + if (g_ascii_strncasecmp (uri, "internal-mailto:", length) == 0) { + gint index; + + index = atoi (uri + length); + contact_display_emit_send_message (display, index); + return; + } + + /* Chain up to parent's link_clicked() method. */ + E_WEB_VIEW_CLASS (eab_contact_display_parent_class)-> + link_clicked (web_view, uri); +} + +#ifdef WITH_CONTACT_MAPS +/* XXX Clutter event handling workaround. Clutter-gtk propagates events down + * to parent widgets. In this case it leads to GtkHTML scrolling up and + * down while user's trying to zoom in the champlain widget. This + * workaround stops the propagation from map widget down to GtkHTML. */ +static gboolean +handle_map_scroll_event (GtkWidget *widget, + GdkEvent *event) +{ + return TRUE; +} + +static GtkWidget * +contact_display_object_requested (WebKitWebView *web_view, + gchar *mime_type, + gchar *uri, + GHashTable *param, + EABContactDisplay *display) +{ + EContact *contact = display->priv->contact; + const gchar *name = e_contact_get_const (contact, E_CONTACT_FILE_AS); + const gchar *contact_uid = e_contact_get_const (contact, E_CONTACT_UID); + gchar *full_name; + EContactAddress *address; + GtkWidget *map = NULL; + + if (strstr (mime_type, "work") != NULL) { + address = e_contact_get (contact, E_CONTACT_ADDRESS_WORK); + full_name = g_strconcat (name, " (", _("Work"), ")", NULL); + } else if (strstr (mime_type, "home") != NULL) { + address = e_contact_get (contact, E_CONTACT_ADDRESS_HOME); + full_name = g_strconcat (name, " (", _("Home"), ")", NULL); + } + + if (address) { + map = e_contact_map_new (); + gtk_widget_set_size_request (map, 250, 250); + g_signal_connect ( + E_CONTACT_MAP (map), "contact-added", + G_CALLBACK (e_contact_map_zoom_on_marker), NULL); + g_signal_connect_swapped ( + E_CONTACT_MAP (map), "contact-added", + G_CALLBACK (gtk_widget_show_all), map); + g_signal_connect ( + GTK_CHAMPLAIN_EMBED (map), "scroll-event", + G_CALLBACK (handle_map_scroll_event), NULL); + + /* No need to display photo in contact preview. */ + e_contact_map_add_marker ( + E_CONTACT_MAP (map), full_name, + contact_uid, address, NULL); + + gtk_widget_show_all (map); + + e_contact_address_free (address); + } + + g_free (full_name); + + return map; +} +#endif + +static void +contact_display_load_status_changed (WebKitWebView *web_view, + GParamSpec *pspec, + gpointer user_data) +{ + WebKitLoadStatus load_status; + WebKitDOMDocument *document; + + load_status = webkit_web_view_get_load_status (web_view); + if (load_status != WEBKIT_LOAD_FINISHED) + return; + + document = webkit_web_view_get_dom_document (web_view); + eab_contact_formatter_bind_dom (document); +} + +static void +contact_display_update_actions (EWebView *web_view) +{ + GtkActionGroup *action_group; + gboolean scheme_is_internal_mailto; + gboolean visible; + const gchar *group_name; + const gchar *uri; + + /* Chain up to parent's update_actions() method. */ + E_WEB_VIEW_CLASS (eab_contact_display_parent_class)-> + update_actions (web_view); + + uri = e_web_view_get_selected_uri (web_view); + + scheme_is_internal_mailto = (uri == NULL) ? FALSE : + (g_ascii_strncasecmp (uri, "internal-mailto:", 16) == 0); + + /* Override how EWebView treats internal-mailto URIs. */ + group_name = "uri"; + action_group = e_web_view_get_action_group (web_view, group_name); + visible = gtk_action_group_get_visible (action_group); + visible &= !scheme_is_internal_mailto; + gtk_action_group_set_visible (action_group, visible); + + group_name = "internal-mailto"; + visible = scheme_is_internal_mailto; + action_group = e_web_view_get_action_group (web_view, group_name); + gtk_action_group_set_visible (action_group, visible); +} + +static void +eab_contact_display_class_init (EABContactDisplayClass *class) +{ + GObjectClass *object_class; + EWebViewClass *web_view_class; + + g_type_class_add_private (class, sizeof (EABContactDisplayPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = contact_display_set_property; + object_class->get_property = contact_display_get_property; + object_class->dispose = contact_display_dispose; + + web_view_class = E_WEB_VIEW_CLASS (class); + web_view_class->hovering_over_link = contact_display_hovering_over_link; + web_view_class->link_clicked = contact_display_link_clicked; + web_view_class->update_actions = contact_display_update_actions; + + g_object_class_install_property ( + object_class, + PROP_CONTACT, + g_param_spec_object ( + "contact", + NULL, + NULL, + E_TYPE_CONTACT, + G_PARAM_READWRITE)); + + /* XXX Make this a real enum property. */ + g_object_class_install_property ( + object_class, + PROP_MODE, + g_param_spec_int ( + "mode", + NULL, + NULL, + EAB_CONTACT_DISPLAY_RENDER_NORMAL, + EAB_CONTACT_DISPLAY_RENDER_COMPACT, + EAB_CONTACT_DISPLAY_RENDER_NORMAL, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SHOW_MAPS, + g_param_spec_boolean ( + "show-maps", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + signals[SEND_MESSAGE] = g_signal_new ( + "send-message", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EABContactDisplayClass, send_message), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_DESTINATION); +} + +static void +eab_contact_display_init (EABContactDisplay *display) +{ + EWebView *web_view; + GtkUIManager *ui_manager; + GtkActionGroup *action_group; + const gchar *domain = GETTEXT_PACKAGE; + GError *error = NULL; + + display->priv = EAB_CONTACT_DISPLAY_GET_PRIVATE (display); + + web_view = E_WEB_VIEW (display); + ui_manager = e_web_view_get_ui_manager (web_view); + +#ifdef WITH_CONTACT_MAPS + g_signal_connect ( + web_view, "create-plugin-widget", + G_CALLBACK (contact_display_object_requested), display); +#endif + g_signal_connect ( + web_view, "notify::load-status", + G_CALLBACK (contact_display_load_status_changed), NULL); + g_signal_connect ( + web_view, "style-set", + G_CALLBACK (load_contact), NULL); + + e_web_view_install_request_handler (E_WEB_VIEW (display), E_TYPE_FILE_REQUEST); + e_web_view_install_request_handler (E_WEB_VIEW (display), E_TYPE_STOCK_REQUEST); + + action_group = gtk_action_group_new ("internal-mailto"); + gtk_action_group_set_translation_domain (action_group, domain); + gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); + g_object_unref (action_group); + + gtk_action_group_add_actions ( + action_group, internal_mailto_entries, + G_N_ELEMENTS (internal_mailto_entries), display); + + /* Because we are loading from a hard-coded string, there is + * no chance of I/O errors. Failure here implies a malformed + * UI definition. Full stop. */ + gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); + if (error != NULL) + g_error ("%s", error->message); +} + +GtkWidget * +eab_contact_display_new (void) +{ + return g_object_new (EAB_TYPE_CONTACT_DISPLAY, NULL); +} + +EContact * +eab_contact_display_get_contact (EABContactDisplay *display) +{ + g_return_val_if_fail (EAB_IS_CONTACT_DISPLAY (display), NULL); + + return display->priv->contact; +} + +void +eab_contact_display_set_contact (EABContactDisplay *display, + EContact *contact) +{ + g_return_if_fail (EAB_IS_CONTACT_DISPLAY (display)); + + if (display->priv->contact == contact) + return; + + if (contact != NULL) + g_object_ref (contact); + + if (display->priv->contact != NULL) + g_object_unref (display->priv->contact); + + display->priv->contact = contact; + + load_contact (display); + + g_object_notify (G_OBJECT (display), "contact"); +} + +EABContactDisplayMode +eab_contact_display_get_mode (EABContactDisplay *display) +{ + g_return_val_if_fail (EAB_IS_CONTACT_DISPLAY (display), 0); + + return display->priv->mode; +} + +void +eab_contact_display_set_mode (EABContactDisplay *display, + EABContactDisplayMode mode) +{ + g_return_if_fail (EAB_IS_CONTACT_DISPLAY (display)); + + if (display->priv->mode == mode) + return; + + display->priv->mode = mode; + + load_contact (display); + + g_object_notify (G_OBJECT (display), "mode"); +} + +gboolean +eab_contact_display_get_show_maps (EABContactDisplay *display) +{ + g_return_val_if_fail (EAB_IS_CONTACT_DISPLAY (display), FALSE); + + return display->priv->show_maps; +} + +void +eab_contact_display_set_show_maps (EABContactDisplay *display, + gboolean show_maps) +{ + g_return_if_fail (EAB_IS_CONTACT_DISPLAY (display)); + + if (display->priv->show_maps == show_maps) + return; + + display->priv->show_maps = show_maps; + + load_contact (display); + + g_object_notify (G_OBJECT (display), "show-maps"); +} diff --git a/addressbook/gui/widgets/eab-contact-display.h b/addressbook/gui/widgets/eab-contact-display.h new file mode 100644 index 0000000000..484e312b6b --- /dev/null +++ b/addressbook/gui/widgets/eab-contact-display.h @@ -0,0 +1,103 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Chris Toshok <toshok@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef EAB_CONTACT_DISPLAY_H +#define EAB_CONTACT_DISPLAY_H + +#include <libebook/libebook.h> + +#include <e-util/e-util.h> + +/* Standard GObject macros */ +#define EAB_TYPE_CONTACT_DISPLAY \ + (eab_contact_display_get_type ()) +#define EAB_CONTACT_DISPLAY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EAB_TYPE_CONTACT_DISPLAY, EABContactDisplay)) +#define EAB_CONTACT_DISPLAY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EAB_TYPE_CONTACT_DISPLAY, EABContactDisplayClass)) +#define EAB_IS_CONTACT_DISPLAY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EAB_TYPE_CONTACT_DISPLAY)) +#define EAB_IS_CONTACT_DISPLAY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EAB_TYPE_CONTACT_DISPLAY)) +#define EAB_CONTACT_DISPLAY_GET_CLASS(obj) \ + (G_TYPE_ISNTANCE_GET_CLASS \ + ((obj), EAB_TYPE_CONTACT_DISPLAY, EABContactDisplayClass)) + +G_BEGIN_DECLS + +typedef struct _EABContactDisplay EABContactDisplay; +typedef struct _EABContactDisplayClass EABContactDisplayClass; +typedef struct _EABContactDisplayPrivate EABContactDisplayPrivate; + +/** + * EABContactDisplayMode: + * @EAB_CONTACT_DISPLAY_RENDER_NORMAL: + * For use in the preview pane. + * @EAB_CONTACT_DISPLAY_RENDER_COMPACT: + * For use with embedded vcards. + **/ +typedef enum { + EAB_CONTACT_DISPLAY_RENDER_NORMAL, + EAB_CONTACT_DISPLAY_RENDER_COMPACT +} EABContactDisplayMode; + +struct _EABContactDisplay { + EWebView parent; + EABContactDisplayPrivate *priv; +}; + +struct _EABContactDisplayClass { + EWebViewClass parent_class; + + /* Signals */ + void (*send_message) (EABContactDisplay *display, + EDestination *destination); +}; + +GType eab_contact_display_get_type (void); +GtkWidget * eab_contact_display_new (void); + +EContact * eab_contact_display_get_contact (EABContactDisplay *display); +void eab_contact_display_set_contact (EABContactDisplay *display, + EContact *contact); +EABContactDisplayMode + eab_contact_display_get_mode (EABContactDisplay *display); +void eab_contact_display_set_mode (EABContactDisplay *display, + EABContactDisplayMode mode); +GtkOrientation eab_contact_display_get_orientation + (EABContactDisplay *display); +void eab_contact_display_set_orientation + (EABContactDisplay *display, + GtkOrientation orientation); +gboolean eab_contact_display_get_show_maps + (EABContactDisplay *display); +void eab_contact_display_set_show_maps + (EABContactDisplay *display, + gboolean display_maps); + +G_END_DECLS + +#endif /* EAB_CONTACT_DISPLAY_H */ diff --git a/addressbook/gui/widgets/eab-contact-formatter.c b/addressbook/gui/widgets/eab-contact-formatter.c new file mode 100644 index 0000000000..60beefa5c3 --- /dev/null +++ b/addressbook/gui/widgets/eab-contact-formatter.c @@ -0,0 +1,1207 @@ +/* + * eab-contact-formatter.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + */ + +#include "eab-contact-formatter.h" + +#include <config.h> +#include <string.h> +#include <glib/gi18n.h> + +#include <e-util/e-util.h> + +#include "eab-book-util.h" +#include "eab-gui-util.h" + +#define EAB_CONTACT_FORMATTER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EAB_TYPE_CONTACT_FORMATTER, EABContactFormatterPrivate)) + +#define TEXT_IS_RIGHT_TO_LEFT \ + (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL) + +#define IMAGE_COL_WIDTH "20" +#define CONTACT_LIST_ICON "stock_contact-list" +#define AIM_ICON "im-aim" +#define GROUPWISE_ICON "im-nov" +#define ICQ_ICON "im-icq" +#define JABBER_ICON "im-jabber" +#define MSN_ICON "im-msn" +#define YAHOO_ICON "im-yahoo" +#define GADUGADU_ICON "im-gadugadu" +#define SKYPE_ICON "stock_people" +#define TWITTER_ICON "im-twitter" +#define VIDEOCONF_ICON "stock_video-conferencing" + +#define MAX_COMPACT_IMAGE_DIMENSION 48 + +#define HTML_HEADER "<!doctype html public \"-//W3C//DTD HTML 4.0 TRANSITIONAL//EN\">\n<html>\n" \ +"<head>\n<meta name=\"generator\" content=\"Evolution Addressbook Component\">\n" \ +"<link type=\"text/css\" rel=\"stylesheet\" href=\"evo-file://" EVOLUTION_PRIVDATADIR "/theme/webview.css\">" \ +"<style type=\"text/css\">\n" \ +" div#header { width:100%; clear: both; }\n" \ +" div#columns { width: 100%; clear: both; }\n" \ +" div#footer { width: 100%; clear: both; }\n" \ +" div.column { width: auto; float: left; margin-right: 15px; }\n" \ +" img#contact-photo { float: left; }\n" \ +" div#contact-name { float: left; margin-left: 20px; }\n" \ +"</style>\n" \ +"</head>\n" + +struct _EABContactFormatterPrivate { + EABContactDisplayMode mode; + gboolean render_maps; +}; + +enum { + PROP_0, + PROP_DISPLAY_MODE, + PROP_RENDER_MAPS +}; + +static struct { + const gchar *name; + const gchar *pretty_name; +} common_location[] = { + { "WORK", N_ ("Work") }, + { "HOME", N_ ("Home") }, + { "OTHER", N_ ("Other") } +}; + +G_DEFINE_TYPE ( + EABContactFormatter, + eab_contact_formatter, + G_TYPE_OBJECT); + +static gboolean +icon_available (const gchar *icon) +{ + GtkIconTheme *icon_theme; + GtkIconInfo *icon_info; + + if (!icon) + return FALSE; + + icon_theme = gtk_icon_theme_get_default (); + icon_info = gtk_icon_theme_lookup_icon (icon_theme, icon, 16, 0); + if (icon_info != NULL) + gtk_icon_info_free (icon_info); + + return icon_info != NULL; +} + +static void +render_address_link (GString *buffer, + EContact *contact, + gint map_type) +{ + EContactAddress *adr; + GString *link = g_string_new (""); + + adr = e_contact_get (contact, map_type); + if (adr && + (adr->street || adr->locality || adr->region || adr->country)) { + gchar *escaped; + + if (adr->street && *adr->street) + g_string_append_printf (link, "%s, ", adr->street); + + if (adr->locality && *adr->locality) + g_string_append_printf (link, "%s, ", adr->locality); + + if (adr->region && *adr->region) + g_string_append_printf (link, "%s, ", adr->region); + + if (adr->country && *adr->country) + g_string_append_printf (link, "%s", adr->country); + + escaped = g_uri_escape_string (link->str, NULL, TRUE); + g_string_assign (link, escaped); + g_free (escaped); + + g_string_prepend (link, "<a href=\"http://maps.google.com?q="); + g_string_append_printf (link, "\">%s</a>", _("Open map")); + } + + if (adr) + e_contact_address_free (adr); + + g_string_append (buffer, link->str); + g_string_free (link, TRUE); +} + +static void +accum_address (GString *buffer, + EContact *contact, + const gchar *html_label, + EContactField adr_field, + EContactField label_field) +{ + EContactAddress *adr; + const gchar *label; + GString *map_link = g_string_new ("<br>"); + + render_address_link (map_link, contact, adr_field); + + label = e_contact_get_const (contact, label_field); + if (label) { + gchar *html = e_text_to_html (label, E_TEXT_TO_HTML_CONVERT_NL); + + if (TEXT_IS_RIGHT_TO_LEFT) { + g_string_append_printf ( + buffer, + "<tr>" + "<td align=\"right\" valign=\"top\" nowrap>%s</td>" + "<th>%s:<br>%s</th>" + "<td valign=\"top\" width=\"" IMAGE_COL_WIDTH "\"></td>" + "</tr>", + html, html_label, map_link->str); + } else { + g_string_append_printf ( + buffer, + "<tr>" + "<td width=\"" IMAGE_COL_WIDTH "\"></td>" + "<th>%s:<br>%s</th>" + "<td valign=\"top\" nowrap>%s</td>" + "</tr>", + html_label, map_link->str, html); + } + + g_free (html); + g_string_free (map_link, TRUE); + return; + } + + adr = e_contact_get (contact, adr_field); + if (adr && + (adr->po || adr->ext || adr->street || adr->locality || + adr->region || adr->code || adr->country)) { + + if (TEXT_IS_RIGHT_TO_LEFT) { + g_string_append_printf ( + buffer, "<tr><td align=\"right\" valign=\"top\" nowrap>"); + } else { + g_string_append_printf ( + buffer, + "<tr>" + "<td valign=\"top\" width=\"" IMAGE_COL_WIDTH "\"></td>" + "<th>%s:<br>%s</th>" + "<td valign=\"top\" nowrap>", + html_label, map_link->str); + } + + if (adr->po && *adr->po) + g_string_append_printf (buffer, "%s<br>", adr->po); + + if (adr->ext && *adr->ext) + g_string_append_printf (buffer, "%s<br>", adr->ext); + + if (adr->street && *adr->street) + g_string_append_printf (buffer, "%s<br>", adr->street); + + if (adr->locality && *adr->locality) + g_string_append_printf (buffer, "%s<br>", adr->locality); + + if (adr->region && *adr->region) + g_string_append_printf (buffer, "%s<br>", adr->region); + + if (adr->code && *adr->code) + g_string_append_printf (buffer, "%s<br>", adr->code); + + if (adr->country && *adr->country) + g_string_append_printf (buffer, "%s<br>", adr->country); + + if (TEXT_IS_RIGHT_TO_LEFT) { + g_string_append_printf ( + buffer, + "</td><th%s:<br>%s</th>" + "<td width=\"" IMAGE_COL_WIDTH "\"></td>" + "</tr>", html_label, map_link->str); + } else { + g_string_append_printf (buffer, "</td></tr>"); + } + + } + + if (adr) + e_contact_address_free (adr); + + g_string_free (map_link, TRUE); +} + +static void +render_table_row (GString *buffer, + const gchar *label, + const gchar *str, + const gchar *icon, + guint html_flags) +{ + const gchar *icon_html; + gchar *value; + + if (html_flags) + value = e_text_to_html (str, html_flags); + else + value = (gchar *) str; + + if (icon && icon_available (icon)) { + icon_html = g_strdup_printf ("<img src=\"gtk-stock://%s\" width=\"16\" height=\"16\" />", icon); + } else { + icon_html = ""; + } + + if (TEXT_IS_RIGHT_TO_LEFT) { + g_string_append_printf ( + buffer, "<tr>" + "<td valign=\"top\" align=\"right\">%s</td>" + "<th align=\"right\" valign=\"top\" width=\"100\" nowrap>:%s</th>" + "<td valign=\"top\" width=\"" IMAGE_COL_WIDTH "\">%s</td>" + "</tr>", + value, label, icon_html); + } else { + g_string_append_printf ( + buffer, "<tr>" + "<td valign=\"top\" width=\"" IMAGE_COL_WIDTH "\">%s</td>" + "<th valign=\"top\" width=\"100\" nowrap>%s:</th>" + "<td valign=\"top\">%s</td>" + "</tr>", + icon_html, label, value); + } + + if (html_flags) + g_free (value); +} + +static void +accum_attribute (GString *buffer, + EContact *contact, + const gchar *html_label, + EContactField field, + const gchar *icon, + guint html_flags) +{ + const gchar *str; + + str = e_contact_get_const (contact, field); + + if (str != NULL && *str != '\0') + render_table_row (buffer, html_label, str, icon, html_flags); +} + +static void +accum_time_attribute (GString *buffer, + EContact *contact, + const gchar *html_label, + EContactField field, + const gchar *icon, + guint html_flags) +{ + EContactDate *date; + GDate *gdate = NULL; + gchar sdate[100]; + + date = e_contact_get (contact, field); + if (date) { + gdate = g_date_new_dmy ( + date->day, + date->month, + date->year); + g_date_strftime (sdate, 100, "%x", gdate); + g_date_free (gdate); + render_table_row (buffer, html_label, sdate, icon, html_flags); + e_contact_date_free (date); + } +} + +static void +accum_attribute_multival (GString *buffer, + EContact *contact, + const gchar *html_label, + EContactField field, + const gchar *icon, + guint html_flags) +{ + GList *val_list, *l; + GString *val = g_string_new (""); + + val_list = e_contact_get (contact, field); + + for (l = val_list; l; l = l->next) { + if (l != val_list) + g_string_append (val, "<br>"); + + g_string_append (val, l->data); + } + + if (val->str && *val->str) + render_table_row (buffer, html_label, val->str, icon, html_flags); + + g_string_free (val, TRUE); + g_list_foreach (val_list, (GFunc) g_free, NULL); + g_list_free (val_list); +} + +static const gchar * +get_email_location (EVCardAttribute *attr) +{ + gint i; + + for (i = 0; i < G_N_ELEMENTS (common_location); i++) { + if (e_vcard_attribute_has_type (attr, common_location[i].name)) + return _(common_location[i].pretty_name); + } + + return _("Other"); +} + +static void +render_title_block (EABContactFormatter *formatter, + EContact *contact, + GString *buffer) +{ + const gchar *str; + gchar *html; + EContactPhoto *photo; + + g_string_append_printf ( + buffer, + "<table border=\"0\"><tr>" + "<td %s valign=\"middle\">", TEXT_IS_RIGHT_TO_LEFT ? + "align=\"right\"" : ""); + + photo = e_contact_get (contact, E_CONTACT_PHOTO); + if (!photo) + photo = e_contact_get (contact, E_CONTACT_LOGO); + + if (photo && photo->type == E_CONTACT_PHOTO_TYPE_INLINED) { + gchar *photo_data; + photo_data = g_base64_encode ( + photo->data.inlined.data, + photo->data.inlined.length); + g_string_append_printf ( + buffer, "<img border=\"1\" src=\"data:%s;base64,%s\">", + photo->data.inlined.mime_type, + photo_data); + } else if (photo && photo->type == E_CONTACT_PHOTO_TYPE_URI && photo->data.uri && *photo->data.uri) { + gboolean is_local = g_str_has_prefix (photo->data.uri, "file://"); + gchar *unescaped = g_uri_unescape_string (photo->data.uri, NULL); + g_string_append_printf ( + buffer, "<img border=\"1\" src=\"%s%s\">", + is_local ? "evo-" : "", unescaped); + g_free (unescaped); + } + + if (photo) + e_contact_photo_free (photo); + + if (e_contact_get (contact, E_CONTACT_IS_LIST)) { + g_string_append_printf (buffer, "<img src=\"gtk-stock://%s\">", CONTACT_LIST_ICON); + } + + g_string_append_printf ( + buffer, + "</td><td width=\"20\"></td><td %s valign=\"top\">\n", + TEXT_IS_RIGHT_TO_LEFT ? "align=\"right\"" : ""); + + str = e_contact_get_const (contact, E_CONTACT_FILE_AS); + if (!str) + str = e_contact_get_const (contact, E_CONTACT_FULL_NAME); + + if (str) { + html = e_text_to_html (str, 0); + if (e_contact_get (contact, E_CONTACT_IS_LIST)) { + g_string_append_printf ( + buffer, + "<h2><a href=\"internal-mailto:0\">%s</a></h2>", + html); + } else { + g_string_append_printf (buffer, "<h2>%s</h2>", html); + } + g_free (html); + } + + g_string_append (buffer, "</td></tr></table>"); +} + +static void +render_contact_list_row (EABContactFormatter *formatter, + EDestination *destination, + GString *buffer) +{ + gchar *evolution_imagesdir; + gboolean list_collapsed = FALSE; + const gchar *textrep; + gchar *name = NULL, *email_addr = NULL; + + evolution_imagesdir = g_filename_to_uri (EVOLUTION_IMAGESDIR, NULL, NULL); + + textrep = e_destination_get_textrep (destination, TRUE); + if (!eab_parse_qp_email (textrep, &name, &email_addr)) + email_addr = g_strdup (textrep); + + g_string_append (buffer, "<tr>"); + if (e_destination_is_evolution_list (destination)) { + g_string_append_printf ( + buffer, + "<td width=" IMAGE_COL_WIDTH " valign=\"top\" align=\"left\">" + "<img src=\"evo-file://%s/minus.png\" " + "id=\"%s\" " + "class=\"navigable _evo_collapse_button\">" + "</td><td width=\"100%%\" align=\"left\">%s", + evolution_imagesdir, + e_destination_get_contact_uid (destination), + name ? name : email_addr); + + if (!list_collapsed) { + const GList *dest, *dests; + g_string_append_printf ( + buffer, + "<br><table cellspacing=\"1\" id=\"list-%s\">", + e_destination_get_contact_uid (destination)); + + dests = e_destination_list_get_root_dests (destination); + for (dest = dests; dest; dest = dest->next) { + render_contact_list_row ( + formatter, dest->data, buffer); + } + + g_string_append (buffer, "</table>"); + } + + g_string_append (buffer, "</td>"); + + } else { + if (name && *name) { + g_string_append_printf ( + buffer, + "<td colspan=\"2\">%s <" + "<a href=\"mailto:%s\">%s</a>>" + "</td>", + name, email_addr, email_addr); + } else { + g_string_append_printf ( + buffer, + "<td colspan=\"2\">" + "<a href=\"mailto:%s\">%s</a>" + "</td>", + email_addr, email_addr); + } + } + + g_string_append (buffer, "</tr>"); + + g_free (evolution_imagesdir); + g_free (name); + g_free (email_addr); +} + +static void +render_contact_list (EABContactFormatter *formatter, + EContact *contact, + GString *buffer) +{ + EDestination *destination; + const GList *dest, *dests; + + destination = e_destination_new (); + e_destination_set_contact (destination, contact, 0); + dests = e_destination_list_get_root_dests (destination); + + render_title_block (formatter, contact, buffer); + + g_string_append_printf ( + buffer, + "<table border=\"0\"><tr><th colspan=\"2\">%s</th></tr>" + "<tr><td with=" IMAGE_COL_WIDTH "></td><td>", _("List Members:")); + + g_string_append (buffer, "<table border=\"0\" cellspacing=\"1\">"); + + for (dest = dests; dest; dest = dest->next) + render_contact_list_row (formatter, dest->data, buffer); + + g_string_append (buffer, "</table>"); + g_string_append (buffer, "</td></tr></table>"); + + g_object_unref (destination); +} + +static void +render_contact_column (EABContactFormatter *formatter, + EContact *contact, + GString *buffer) +{ + GString *accum, *email; + GList *email_list, *l, *email_attr_list, *al; + gint email_num = 0; + const gchar *nl; + + email = g_string_new (""); + nl = ""; + + email_list = e_contact_get (contact, E_CONTACT_EMAIL); + email_attr_list = e_contact_get_attributes (contact, E_CONTACT_EMAIL); + + for (l = email_list, al = email_attr_list; l && al; l = l->next, al = al->next) { + gchar *name = NULL, *mail = NULL; + gchar *attr_str = (gchar *) get_email_location ((EVCardAttribute *) al->data); + + if (!eab_parse_qp_email (l->data, &name, &mail)) + mail = e_text_to_html (l->data, 0); + + g_string_append_printf ( + email, + "%s%s%s<a href=\"internal-mailto:%d\">%s</a>%s " + "<span class=\"header\">(%s)</span>", + nl, + name ? name : "", + name ? " <" : "", + email_num, + mail, + name ? ">" : "", + attr_str ? attr_str : ""); + email_num++; + nl = "<br>"; + + g_free (name); + g_free (mail); + } + g_list_foreach (email_list, (GFunc) g_free, NULL); + g_list_foreach (email_attr_list, (GFunc) e_vcard_attribute_free, NULL); + g_list_free (email_list); + g_list_free (email_attr_list); + + accum = g_string_new (""); + + if (email->len) + render_table_row (accum, _("Email"), email->str, NULL, 0); + + accum_attribute (accum, contact, _("Nickname"), E_CONTACT_NICKNAME, NULL, 0); + accum_attribute_multival (accum, contact, _("AIM"), E_CONTACT_IM_AIM, AIM_ICON, 0); + accum_attribute_multival (accum, contact, _("GroupWise"), E_CONTACT_IM_GROUPWISE, GROUPWISE_ICON, 0); + accum_attribute_multival (accum, contact, _("ICQ"), E_CONTACT_IM_ICQ, ICQ_ICON, 0); + accum_attribute_multival (accum, contact, _("Jabber"), E_CONTACT_IM_JABBER, JABBER_ICON, 0); + accum_attribute_multival (accum, contact, _("MSN"), E_CONTACT_IM_MSN, MSN_ICON, 0); + accum_attribute_multival (accum, contact, _("Yahoo"), E_CONTACT_IM_YAHOO, YAHOO_ICON, 0); + accum_attribute_multival (accum, contact, _("Gadu-Gadu"), E_CONTACT_IM_GADUGADU, GADUGADU_ICON, 0); + accum_attribute_multival (accum, contact, _("Skype"), E_CONTACT_IM_SKYPE, SKYPE_ICON, 0); + accum_attribute_multival (accum, contact, _("Twitter"), E_CONTACT_IM_TWITTER, TWITTER_ICON, 0); + + if (accum->len) + g_string_append_printf ( + buffer, + "<div class=\"column\" id=\"contact-internet\">" + "<table border=\"0\" cellspacing=\"5\">%s</table>" + "</div>", accum->str); + + g_string_free (accum, TRUE); + g_string_free (email, TRUE); +} + +static void +accum_address_map (GString *buffer, + EContact *contact, + gint map_type) +{ +#ifdef WITH_CONTACT_MAPS + g_string_append (buffer, "<tr><td colspan=\"3\">"); + + if (map_type == E_CONTACT_ADDRESS_WORK) { + g_string_append ( + buffer, + "<object type=\"application/x-work-map-widget\" " + "width=\"250\" height=\"250\"></object>"); + } else { + g_string_append ( + buffer, + "<object type=\"application/x-home-map-widget\" " + "width=\"250\" height=\"250\"></object>"); + } + + g_string_append (buffer, "</td></tr>"); +#endif /* WITH_CONTACT_MAPS */ +} + +static void +render_work_column (EABContactFormatter *formatter, + EContact *contact, + GString *buffer) +{ + GString *accum = g_string_new (""); + + accum_attribute (accum, contact, _("Company"), E_CONTACT_ORG, NULL, 0); + accum_attribute (accum, contact, _("Department"), E_CONTACT_ORG_UNIT, NULL, 0); + accum_attribute (accum, contact, _("Profession"), E_CONTACT_ROLE, NULL, 0); + accum_attribute (accum, contact, _("Position"), E_CONTACT_TITLE, NULL, 0); + accum_attribute (accum, contact, _("Manager"), E_CONTACT_MANAGER, NULL, 0); + accum_attribute (accum, contact, _("Assistant"), E_CONTACT_ASSISTANT, NULL, 0); + accum_attribute (accum, contact, _("Video Chat"), E_CONTACT_VIDEO_URL, VIDEOCONF_ICON, E_TEXT_TO_HTML_CONVERT_URLS); + accum_attribute (accum, contact, _("Calendar"), E_CONTACT_CALENDAR_URI, NULL, E_TEXT_TO_HTML_CONVERT_URLS); + accum_attribute (accum, contact, _("Free/Busy"), E_CONTACT_FREEBUSY_URL, NULL, E_TEXT_TO_HTML_CONVERT_URLS); + accum_attribute (accum, contact, _("Phone"), E_CONTACT_PHONE_BUSINESS, NULL, 0); + accum_attribute (accum, contact, _("Fax"), E_CONTACT_PHONE_BUSINESS_FAX, NULL, 0); + accum_address (accum, contact, _("Address"), E_CONTACT_ADDRESS_WORK, E_CONTACT_ADDRESS_LABEL_WORK); + if (formatter->priv->render_maps) + accum_address_map (accum, contact, E_CONTACT_ADDRESS_WORK); + + if (accum->len > 0) { + g_string_append_printf ( + buffer, + "<div class=\"column\" id=\"contact-work\">" + "<h3>%s</h3>" + "<table border=\"0\" cellspacing=\"5\">%s</table>" + "</div>", _("Work"), accum->str); + } + + g_string_free (accum, TRUE); +} + +static void +render_personal_column (EABContactFormatter *formatter, + EContact *contact, + GString *buffer) +{ + GString *accum = g_string_new (""); + + accum_attribute (accum, contact, _("Home Page"), E_CONTACT_HOMEPAGE_URL, NULL, E_TEXT_TO_HTML_CONVERT_URLS); + accum_attribute (accum, contact, _("Web Log"), E_CONTACT_BLOG_URL, NULL, E_TEXT_TO_HTML_CONVERT_URLS); + accum_attribute (accum, contact, _("Phone"), E_CONTACT_PHONE_HOME, NULL, 0); + accum_attribute (accum, contact, _("Mobile Phone"), E_CONTACT_PHONE_MOBILE, NULL, 0); + accum_address (accum, contact, _("Address"), E_CONTACT_ADDRESS_HOME, E_CONTACT_ADDRESS_LABEL_HOME); + accum_time_attribute (accum, contact, _("Birthday"), E_CONTACT_BIRTH_DATE, NULL, 0); + accum_time_attribute (accum, contact, _("Anniversary"), E_CONTACT_ANNIVERSARY, NULL, 0); + accum_attribute (accum, contact, _("Spouse"), E_CONTACT_SPOUSE, NULL, 0); + if (formatter->priv->render_maps) + accum_address_map (accum, contact, E_CONTACT_ADDRESS_HOME); + + if (accum->len > 0) { + g_string_append_printf ( + buffer, + "<div class=\"column\" id=\"contact-personal\">" + "<h3>%s</h3>" + "<table border=\"0\" cellspacing=\"5\">%s</table>" + "</div>", _("Personal"), accum->str); + } + + g_string_free (accum, TRUE); +} + +static void +render_footer (EABContactFormatter *formatter, + EContact *contact, + GString *buffer) +{ + const gchar *str; + + str = e_contact_get_const (contact, E_CONTACT_NOTE); + if (!str || !*str) + return; + + g_string_append ( + buffer, + "<div id=\"footer\"><table border=\"0\" cellspacing=\"5\">"); + + render_table_row ( + buffer, _("Note"), + e_contact_get_const (contact, E_CONTACT_NOTE), + NULL, + E_TEXT_TO_HTML_CONVERT_ADDRESSES | + E_TEXT_TO_HTML_CONVERT_URLS | + E_TEXT_TO_HTML_CONVERT_NL); + + g_string_append (buffer, "</table></div>"); +} + +static void +render_contact (EABContactFormatter *formatter, + EContact *contact, + GString *buffer) +{ + render_title_block (formatter, contact, buffer); + + g_string_append (buffer, "<div id=\"columns\">"); + render_contact_column (formatter, contact, buffer); + render_work_column (formatter, contact, buffer); + render_personal_column (formatter, contact, buffer); + g_string_append (buffer, "</div>"); + + render_footer (formatter, contact, buffer); +} + +static void +render_normal (EABContactFormatter *formatter, + EContact *contact, + GString *buffer) +{ + g_string_append (buffer, HTML_HEADER); + g_string_append (buffer, "<body bgcolor=\"white\">"); + + if (contact != NULL) { + if (e_contact_get (contact, E_CONTACT_IS_LIST)) + render_contact_list (formatter, contact, buffer); + else + render_contact (formatter, contact, buffer); + } + + g_string_append (buffer, "</body></html>\n"); +} + +static void +render_compact (EABContactFormatter *formatter, + EContact *contact, + GString *buffer) +{ + const gchar *str; + gchar *html; + EContactPhoto *photo; + + g_string_append (buffer, HTML_HEADER); + g_string_append (buffer, "<body>\n"); + + if (contact == NULL) { + g_string_append (buffer, "</body></html>"); + return; + } + + g_string_append_printf ( + buffer, + "<table><tr><td valign=\"top\">"); + + photo = e_contact_get (contact, E_CONTACT_PHOTO); + + if (photo == NULL) + photo = e_contact_get (contact, E_CONTACT_LOGO); + + if (photo != NULL) { + gint calced_width = MAX_COMPACT_IMAGE_DIMENSION; + gint calced_height = MAX_COMPACT_IMAGE_DIMENSION; + GdkPixbufLoader *loader = gdk_pixbuf_loader_new (); + GdkPixbuf *pixbuf; + + /* figure out if we need to downscale the + * image here. we don't scale the pixbuf + * itself, just insert width/height tags in + * the html */ + if (photo->type == E_CONTACT_PHOTO_TYPE_INLINED) { + gdk_pixbuf_loader_write ( + loader, photo->data.inlined.data, + photo->data.inlined.length, NULL); + } else if (photo->type == E_CONTACT_PHOTO_TYPE_URI && + photo->data.uri && + g_ascii_strncasecmp (photo->data.uri, "file://", 7) == 0) { + gchar *filename, *contents = NULL; + gsize length; + + filename = g_filename_from_uri (photo->data.uri, NULL, NULL); + + if (filename) { + if (g_file_get_contents (filename, &contents, &length, NULL)) { + gdk_pixbuf_loader_write (loader, (const guchar *) contents, length, NULL); + g_free (contents); + } + + g_free (filename); + } + } + + gdk_pixbuf_loader_close (loader, NULL); + pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); + + if (pixbuf) + g_object_ref (pixbuf); + + g_object_unref (loader); + + if (pixbuf) { + gint max_dimension; + + calced_width = gdk_pixbuf_get_width (pixbuf); + calced_height = gdk_pixbuf_get_height (pixbuf); + + max_dimension = calced_width; + + if (max_dimension < calced_height) + max_dimension = calced_height; + + if (max_dimension > MAX_COMPACT_IMAGE_DIMENSION) { + calced_width *= ((gfloat) MAX_COMPACT_IMAGE_DIMENSION / max_dimension); + calced_height *= ((gfloat) MAX_COMPACT_IMAGE_DIMENSION / max_dimension); + } + + g_object_unref (pixbuf); + } + + if (photo->type == E_CONTACT_PHOTO_TYPE_URI && + photo->data.uri && *photo->data.uri) { + gboolean is_local = g_str_has_prefix (photo->data.uri, "file://"); + gchar *unescaped = g_uri_unescape_string (photo->data.uri, NULL); + g_string_append_printf ( + buffer, + "<img width=\"%d\" height=\"%d\" src=\"%s%s\">", + calced_width, calced_height, + is_local ? "evo-" : "", unescaped); + g_free (unescaped); + } else { + gchar *photo_data; + + photo_data = g_base64_encode ( + photo->data.inlined.data, + photo->data.inlined.length); + g_string_append_printf ( + buffer, + "<img border=\"1\" src=\"data:%s;base64,%s\" " + "width=\"%d\" height=\"%d\">", + photo->data.inlined.mime_type, + photo_data, + calced_width, calced_height); + g_free (photo_data); + } + + e_contact_photo_free (photo); + } + + g_string_append (buffer, "</td><td width=\"5\"></td><td valign=\"top\">\n"); + + str = e_contact_get_const (contact, E_CONTACT_FILE_AS); + + if (str) { + html = e_text_to_html (str, 0); + g_string_append_printf (buffer, "<b>%s</b>", html); + g_free (html); + } else { + str = e_contact_get_const (contact, E_CONTACT_FULL_NAME); + + if (str) { + html = e_text_to_html (str, 0); + g_string_append_printf (buffer, "<b>%s</b>", html); + g_free (html); + } + } + + g_string_append (buffer, "<hr>"); + + if (e_contact_get (contact, E_CONTACT_IS_LIST)) { + GList *email_list; + GList *l; + + g_string_append ( + buffer, + "<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">" + "<tr><td valign=\"top\">"); + g_string_append_printf ( + buffer, + "<b>%s:</b> <td>", _ ("List Members")); + + email_list = e_contact_get (contact, E_CONTACT_EMAIL); + + for (l = email_list; l; l = l->next) { + if (l->data) { + html = e_text_to_html (l->data, 0); + g_string_append_printf (buffer, "%s, ", html); + g_free (html); + } + } + + g_string_append (buffer, "</td></tr></table>"); + + } else { + + gboolean comma = FALSE; + str = e_contact_get_const (contact, E_CONTACT_TITLE); + + if (str) { + html = e_text_to_html (str, 0); + g_string_append_printf (buffer, "<b>%s:</b> %s<br>", _ ("Job Title"), str); + g_free (html); + } + + #define print_email() { \ + html = eab_parse_qp_email_to_html (str); \ + \ + if (!html) \ + html = e_text_to_html (str, 0); \ + \ + g_string_append_printf (buffer, "%s%s", comma ? ", " : "", html); \ + g_free (html); \ + comma = TRUE; \ + } + + g_string_append_printf (buffer, "<b>%s:</b> ", _ ("Email")); + str = e_contact_get_const (contact, E_CONTACT_EMAIL_1); + + if (str) + print_email (); + + str = e_contact_get_const (contact, E_CONTACT_EMAIL_2); + + if (str) + print_email (); + + str = e_contact_get_const (contact, E_CONTACT_EMAIL_3); + + if (str) + print_email (); + + g_string_append (buffer, "<br>"); + + #undef print_email + + str = e_contact_get_const (contact, E_CONTACT_HOMEPAGE_URL); + + if (str) { + html = e_text_to_html (str, E_TEXT_TO_HTML_CONVERT_URLS); + g_string_append_printf ( + buffer, "<b>%s:</b> %s<br>", + _ ("Home page"), html); + g_free (html); + } + + str = e_contact_get_const (contact, E_CONTACT_BLOG_URL); + + if (str) { + html = e_text_to_html (str, E_TEXT_TO_HTML_CONVERT_URLS); + g_string_append_printf ( + buffer, "<b>%s:</b> %s<br>", + _ ("Blog"), html); + } + } + + g_string_append (buffer, "</td></tr></table>\n"); + + g_string_append (buffer, "</body></html>\n"); +} + +static void +eab_contact_formatter_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_DISPLAY_MODE: + eab_contact_formatter_set_display_mode ( + EAB_CONTACT_FORMATTER (object), + g_value_get_int (value)); + return; + + case PROP_RENDER_MAPS: + eab_contact_formatter_set_render_maps ( + EAB_CONTACT_FORMATTER (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +eab_contact_formatter_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_DISPLAY_MODE: + g_value_set_int ( + value, + eab_contact_formatter_get_display_mode ( + EAB_CONTACT_FORMATTER (object))); + return; + + case PROP_RENDER_MAPS: + g_value_set_boolean ( + value, + eab_contact_formatter_get_render_maps ( + EAB_CONTACT_FORMATTER (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +eab_contact_formatter_class_init (EABContactFormatterClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (EABContactFormatterClass)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = eab_contact_formatter_set_property; + object_class->get_property = eab_contact_formatter_get_property; + + g_object_class_install_property ( + object_class, + PROP_DISPLAY_MODE, + g_param_spec_int ( + "display-mode", + "Display Mode", + NULL, + EAB_CONTACT_DISPLAY_RENDER_NORMAL, + EAB_CONTACT_DISPLAY_RENDER_COMPACT, + EAB_CONTACT_DISPLAY_RENDER_NORMAL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_RENDER_MAPS, + g_param_spec_boolean ( + "render-maps", + "Render Maps", + NULL, + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); +} + +static void +eab_contact_formatter_init (EABContactFormatter *formatter) +{ + formatter->priv = EAB_CONTACT_FORMATTER_GET_PRIVATE (formatter); + + formatter->priv->mode = EAB_CONTACT_DISPLAY_RENDER_NORMAL; + formatter->priv->render_maps = FALSE; +} + +EABContactFormatter * +eab_contact_formatter_new (void) +{ + return g_object_new (EAB_TYPE_CONTACT_FORMATTER, NULL); +} + +gboolean +eab_contact_formatter_get_render_maps (EABContactFormatter *formatter) +{ + g_return_val_if_fail (EAB_IS_CONTACT_FORMATTER (formatter), FALSE); + + return formatter->priv->render_maps; +} + +void +eab_contact_formatter_set_render_maps (EABContactFormatter *formatter, + gboolean render_maps) +{ + g_return_if_fail (EAB_IS_CONTACT_FORMATTER (formatter)); + + if (formatter->priv->render_maps == render_maps) + return; + + formatter->priv->render_maps = render_maps; + + g_object_notify (G_OBJECT (formatter), "render-maps"); +} + +EABContactDisplayMode +eab_contact_formatter_get_display_mode (EABContactFormatter *formatter) +{ + g_return_val_if_fail ( + EAB_IS_CONTACT_FORMATTER (formatter), + EAB_CONTACT_DISPLAY_RENDER_NORMAL); + + return formatter->priv->mode; +} + +void +eab_contact_formatter_set_display_mode (EABContactFormatter *formatter, + EABContactDisplayMode mode) +{ + g_return_if_fail (EAB_IS_CONTACT_FORMATTER (formatter)); + + if (formatter->priv->mode == mode) + return; + + formatter->priv->mode = mode; + + g_object_notify (G_OBJECT (formatter), "display-mode"); +} + +void +eab_contact_formatter_format_contact (EABContactFormatter *formatter, + EContact *contact, + GString *output_buffer) +{ + g_return_if_fail (EAB_IS_CONTACT_FORMATTER (formatter)); + g_return_if_fail (E_IS_CONTACT (contact)); + g_return_if_fail (output_buffer != NULL); + + if (formatter->priv->mode == EAB_CONTACT_DISPLAY_RENDER_NORMAL) + render_normal (formatter, contact, output_buffer); + else + render_compact (formatter, contact, output_buffer); +} + +static void +collapse_contacts_list (WebKitDOMEventTarget *event_target, + WebKitDOMEvent *event, + gpointer user_data) +{ + WebKitDOMDocument *document; + WebKitDOMElement *list; + gchar *id, *list_id; + gchar *imagesdir, *src; + gboolean hidden; + + document = user_data; + id = webkit_dom_html_element_get_id (WEBKIT_DOM_HTML_ELEMENT (event_target)); + + list_id = g_strconcat ("list-", id, NULL); + list = webkit_dom_document_get_element_by_id (document, list_id); + g_free (id); + g_free (list_id); + + if (list == NULL) + return; + + imagesdir = g_filename_to_uri (EVOLUTION_IMAGESDIR, NULL, NULL); + hidden = webkit_dom_html_element_get_hidden (WEBKIT_DOM_HTML_ELEMENT (list)); + + if (hidden) + src = g_strdup_printf ("evo-file://%s/minus.png", imagesdir); + else + src = g_strdup_printf ("evo-file://%s/plus.png", imagesdir); + + webkit_dom_html_element_set_hidden ( + WEBKIT_DOM_HTML_ELEMENT (list), !hidden); + webkit_dom_html_image_element_set_src ( + WEBKIT_DOM_HTML_IMAGE_ELEMENT (event_target), src); + + g_free (src); + g_free (imagesdir); +} + +void +eab_contact_formatter_bind_dom (WebKitDOMDocument *document) +{ + WebKitDOMNodeList *nodes; + gulong ii, length; + + nodes = webkit_dom_document_get_elements_by_class_name ( + document, "_evo_collapse_button"); + + length = webkit_dom_node_list_get_length (nodes); + for (ii = 0; ii < length; ii++) { + + WebKitDOMNode *node; + + node = webkit_dom_node_list_item (nodes, ii); + webkit_dom_event_target_add_event_listener ( + WEBKIT_DOM_EVENT_TARGET (node), "click", + G_CALLBACK (collapse_contacts_list), FALSE, document); + } +} diff --git a/addressbook/gui/widgets/eab-contact-formatter.h b/addressbook/gui/widgets/eab-contact-formatter.h new file mode 100644 index 0000000000..4dc1427960 --- /dev/null +++ b/addressbook/gui/widgets/eab-contact-formatter.h @@ -0,0 +1,84 @@ +/* + * eab-contact-formatter.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + */ + +#ifndef EAB_CONTACT_FORMATTER_H +#define EAB_CONTACT_FORMATTER_H + +#include <camel/camel.h> +#include <libebook/libebook.h> + +#include <addressbook/gui/widgets/eab-contact-display.h> + +/* Standard GObject macros */ +#define EAB_TYPE_CONTACT_FORMATTER \ + (eab_contact_formatter_get_type ()) +#define EAB_CONTACT_FORMATTER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EAB_TYPE_CONTACT_FORMATTER, EABContactFormatter)) +#define EAB_CONTACT_FORMATTER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EAB_TYPE_CONTACT_FORMATTER, EABContactFormatterClass)) +#define EAB_IS_CONTACT_FORMATTER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EAB_TYPE_CONTACT_FORMATTER)) +#define EAB_IS_CONTACT_FORMATTER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EAB_TYPE_CONTACT_FORMATTER)) +#define EAB_CONTACT_FORMATTER_GET_CLASS(obj) \ + (G_TYPE_ISNTANCE_GET_CLASS \ + ((obj), EAB_TYPE_CONTACT_FORMATTER, EABContactFormatterClass)) + +G_BEGIN_DECLS + +typedef struct _EABContactFormatter EABContactFormatter; +typedef struct _EABContactFormatterClass EABContactFormatterClass; +typedef struct _EABContactFormatterPrivate EABContactFormatterPrivate; + +struct _EABContactFormatter { + GObject parent; + EABContactFormatterPrivate *priv; +}; + +struct _EABContactFormatterClass { + GObjectClass parent_class; +}; + +GType eab_contact_formatter_get_type (void) G_GNUC_CONST; +EABContactFormatter * + eab_contact_formatter_new (void); +gboolean eab_contact_formatter_get_render_maps + (EABContactFormatter *formatter); +void eab_contact_formatter_set_render_maps + (EABContactFormatter *formatter, + gboolean render_maps); +EABContactDisplayMode + eab_contact_formatter_get_display_mode + (EABContactFormatter *formatter); +void eab_contact_formatter_set_display_mode + (EABContactFormatter *formatter, + EABContactDisplayMode mode); +void eab_contact_formatter_format_contact + (EABContactFormatter *formatter, + EContact *contact, + GString *output_buffer); +void eab_contact_formatter_bind_dom (WebKitDOMDocument *document); + +G_END_DECLS + +#endif /* EAB_CONTACT_FORMATTER_H */ + diff --git a/addressbook/gui/widgets/eab-gui-util.c b/addressbook/gui/widgets/eab-gui-util.c new file mode 100644 index 0000000000..5f155ad1b1 --- /dev/null +++ b/addressbook/gui/widgets/eab-gui-util.c @@ -0,0 +1,1119 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Chris Toshok <toshok@ximian.com> + * Dan Vratil <dvratil@redhat.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <locale.h> +#include <string.h> + +#include <gtk/gtk.h> +#include <glib/gi18n.h> + +#include "shell/e-shell.h" + +#include "eab-gui-util.h" +#include "util/eab-book-util.h" +#include "eab-contact-merging.h" + +/* we link to camel for decoding quoted printable email addresses */ +#include <camel/camel.h> + +/* Template tags for address format localization */ +#define ADDRESS_REALNAME "%n" /* this is not used intentionally */ +#define ADDRESS_REALNAME_UPPER "%N" /* this is not used intentionally */ +#define ADDRESS_COMPANY "%m" +#define ADDRESS_COMPANY_UPPER "%M" +#define ADDRESS_POBOX "%p" +#define ADDRESS_STREET "%s" +#define ADDRESS_STREET_UPPER "%S" +#define ADDRESS_ZIPCODE "%z" +#define ADDRESS_LOCATION "%l" +#define ADDRESS_LOCATION_UPPER "%L" +#define ADDRESS_REGION "%r" +#define ADDRESS_REGION_UPPER "%R" +#define ADDRESS_CONDCOMMA "%," /* Conditional comma is removed when a surrounding tag is evaluated to zero */ +#define ADDRESS_CONDWHITE "%w" /* Conditional whitespace is removed when a surrounding tag is evaluated to zero */ +#define ADDRESS_COND_PURGEEMPTY "%0" /* Purge empty has following syntax: %0(...) and is removed when no tag within () is evaluated non-zero */ + +/* Fallback formats */ +#define ADDRESS_DEFAULT_FORMAT "%0(%n\n)%0(%m\n)%0(%s\n)%0(PO BOX %p\n)%0(%l%w%r)%,%z" +#define ADDRESS_DEFAULT_COUNTRY_POSITION "below" + +enum { + LOCALES_LANGUAGE = 0, + LOCALES_COUNTRY = 1 +}; + +typedef enum { + ADDRESS_FORMAT_HOME = 0, + ADDRESS_FORMAT_BUSINESS = 1 +} AddressFormat; + +void +eab_error_dialog (EAlertSink *alert_sink, + GtkWindow *parent, + const gchar *msg, + const GError *error) +{ + if (error && error->message) { + if (alert_sink) + e_alert_submit ( + alert_sink, + "addressbook:generic-error", + msg, error->message, NULL); + else { + if (!parent) + parent = e_shell_get_active_window (NULL); + + e_alert_run_dialog_for_args ( + parent, + "addressbook:generic-error", + msg, error->message, NULL); + } + } +} + +void +eab_load_error_dialog (GtkWidget *parent, + EAlertSink *alert_sink, + ESource *source, + const GError *error) +{ + ESourceBackend *extension; + gchar *label_string, *label = NULL; + gboolean can_detail_error = TRUE; + const gchar *backend_name; + const gchar *extension_name; + + g_return_if_fail (source != NULL); + + extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK; + extension = e_source_get_extension (source, extension_name); + backend_name = e_source_backend_get_backend_name (extension); + + if (g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_OFFLINE_UNAVAILABLE)) { + can_detail_error = FALSE; + label_string = + _("This address book cannot be opened. This either " + "means this book is not marked for offline usage " + "or not yet downloaded for offline usage. Please " + "load the address book once in online mode to " + "download its contents."); + } + + else if (g_strcmp0 (backend_name, "local") == 0) { + const gchar *user_data_dir; + const gchar *uid; + gchar *path; + + uid = e_source_get_uid (source); + user_data_dir = e_get_user_data_dir (); + + path = g_build_filename ( + user_data_dir, "addressbook", uid, NULL); + + label = g_strdup_printf ( + _("This address book cannot be opened. Please check that the " + "path %s exists and that permissions are set to access it."), path); + + g_free (path); + label_string = label; + } + +#ifndef HAVE_LDAP + else if (g_strcmp0 (backend_name, "ldap") == 0) { + /* special case for ldap: contact folders so we can tell the user about openldap */ + + can_detail_error = FALSE; + label_string = + _("This version of Evolution does not have LDAP support " + "compiled in to it. To use LDAP in Evolution " + "an LDAP-enabled Evolution package must be installed."); + + } +#endif + else { + /* other network folders (or if ldap is enabled and server is unreachable) */ + label_string = + _("This address book cannot be opened. This either " + "means that an incorrect URI was entered, or the server " + "is unreachable."); + } + + if (can_detail_error) { + /* do not show repository offline message, it's kind of generic error */ + if (error && !g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_REPOSITORY_OFFLINE)) { + label = g_strconcat (label_string, "\n\n", _("Detailed error message:"), " ", error->message, NULL); + label_string = label; + } + } + + if (alert_sink) { + e_alert_submit ( + alert_sink, "addressbook:load-error", + label_string, NULL); + } else { + GtkWidget *dialog; + + dialog = e_alert_dialog_new_for_args ( + (GtkWindow *) parent, + "addressbook:load-error", + label_string, NULL); + g_signal_connect ( + dialog, "response", + G_CALLBACK (gtk_widget_destroy), NULL); + gtk_widget_show (dialog); + } + + g_free (label); +} + +void +eab_search_result_dialog (EAlertSink *alert_sink, + const GError *error) +{ + gchar *str = NULL; + + if (!error) + return; + + if (error->domain == E_CLIENT_ERROR) { + switch (error->code) { + case E_CLIENT_ERROR_SEARCH_SIZE_LIMIT_EXCEEDED: + str = _("More cards matched this query than either the server is \n" + "configured to return or Evolution is configured to display.\n" + "Please make your search more specific or raise the result limit in\n" + "the directory server preferences for this address book."); + str = g_strdup (str); + break; + case E_CLIENT_ERROR_SEARCH_TIME_LIMIT_EXCEEDED: + str = _("The time to execute this query exceeded the server limit or the limit\n" + "configured for this address book. Please make your search\n" + "more specific or raise the time limit in the directory server\n" + "preferences for this address book."); + str = g_strdup (str); + break; + case E_CLIENT_ERROR_INVALID_QUERY: + /* Translators: %s is replaced with a detailed error message, or an empty string, if not provided */ + str = _("The backend for this address book was unable to parse this query. %s"); + str = g_strdup_printf (str, error->message); + break; + case E_CLIENT_ERROR_QUERY_REFUSED: + /* Translators: %s is replaced with a detailed error message, or an empty string, if not provided */ + str = _("The backend for this address book refused to perform this query. %s"); + str = g_strdup_printf (str, error->message); + break; + case E_CLIENT_ERROR_OTHER_ERROR: + default: + /* Translators: %s is replaced with a detailed error message, or an empty string, if not provided */ + str = _("This query did not complete successfully. %s"); + str = g_strdup_printf (str, error->message); + break; + } + } else { + /* Translators: %s is replaced with a detailed error message, or an empty string, if not provided */ + str = _("This query did not complete successfully. %s"); + str = g_strdup_printf (str, error->message); + } + + e_alert_submit (alert_sink, "addressbook:search-error", str, NULL); + + g_free (str); +} + +gint +eab_prompt_save_dialog (GtkWindow *parent) +{ + return e_alert_run_dialog_for_args (parent, "addressbook:prompt-save", NULL); +} + +static gchar * +make_safe_filename (gchar *name) +{ + gchar *safe; + + if (!name) { + /* This is a filename. Translators take note. */ + name = _("card.vcf"); + } + + if (!g_strrstr (name, ".vcf")) + safe = g_strdup_printf ("%s%s", name, ".vcf"); + else + safe = g_strdup (name); + + e_filename_make_safe (safe); + + return safe; +} + +static void +source_selection_changed_cb (ESourceSelector *selector, + GtkWidget *ok_button) +{ + ESource *except_source = NULL, *selected; + gboolean sensitive; + + except_source = g_object_get_data (G_OBJECT (ok_button), "except-source"); + selected = e_source_selector_ref_primary_selection (selector); + + sensitive = (selected != NULL && selected != except_source); + gtk_widget_set_sensitive (ok_button, sensitive); + + if (selected != NULL) + g_object_unref (selected); +} + +ESource * +eab_select_source (ESourceRegistry *registry, + ESource *except_source, + const gchar *title, + const gchar *message, + const gchar *select_uid, + GtkWindow *parent) +{ + ESource *source; + GtkWidget *content_area; + GtkWidget *dialog; + GtkWidget *ok_button; + /* GtkWidget *label; */ + GtkWidget *selector; + GtkWidget *scrolled_window; + const gchar *extension_name; + gint response; + + g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL); + + dialog = gtk_dialog_new_with_buttons ( + _("Select Address Book"), parent, + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + NULL); + gtk_window_set_default_size (GTK_WINDOW (dialog), 350, 300); + + gtk_dialog_set_response_sensitive ( + GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT, FALSE); + + /* label = gtk_label_new (message); */ + + extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK; + selector = e_source_selector_new (registry, extension_name); + e_source_selector_set_show_toggles ( + E_SOURCE_SELECTOR (selector), FALSE); + + ok_button = gtk_dialog_get_widget_for_response ( + GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); + + if (except_source) + g_object_set_data ( + G_OBJECT (ok_button), "except-source", except_source); + + g_signal_connect ( + selector, "primary_selection_changed", + G_CALLBACK (source_selection_changed_cb), ok_button); + + if (select_uid) { + source = e_source_registry_ref_source (registry, select_uid); + if (source != NULL) { + e_source_selector_set_primary_selection ( + E_SOURCE_SELECTOR (selector), source); + g_object_unref (source); + } + } + + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN); + gtk_container_add (GTK_CONTAINER (scrolled_window), selector); + + content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + gtk_box_pack_start (GTK_BOX (content_area), scrolled_window, TRUE, TRUE, 4); + + gtk_widget_show_all (dialog); + response = gtk_dialog_run (GTK_DIALOG (dialog)); + + if (response == GTK_RESPONSE_ACCEPT) + source = e_source_selector_ref_primary_selection ( + E_SOURCE_SELECTOR (selector)); + else + source = NULL; + + gtk_widget_destroy (dialog); + + /* XXX Return a borrowed reference for backward-compatibility. */ + if (source != NULL) + g_object_unref (source); + + return source; +} + +gchar * +eab_suggest_filename (const GSList *contact_list) +{ + gchar *res = NULL; + + g_return_val_if_fail (contact_list != NULL, NULL); + + if (!contact_list->next) { + EContact *contact = E_CONTACT (contact_list->data); + gchar *string; + + string = e_contact_get (contact, E_CONTACT_FILE_AS); + if (string == NULL) + string = e_contact_get (contact, E_CONTACT_FULL_NAME); + if (string != NULL) + res = make_safe_filename (string); + g_free (string); + } + + if (res == NULL) + res = make_safe_filename (_("list")); + + return res; +} + +typedef struct ContactCopyProcess_ ContactCopyProcess; + +struct ContactCopyProcess_ { + gint count; + gboolean book_status; + GSList *contacts; + EBookClient *source; + EBookClient *destination; + ESourceRegistry *registry; + gboolean delete_from_source; + EAlertSink *alert_sink; +}; + +static void process_unref (ContactCopyProcess *process); + +static void +remove_contact_ready_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + EBookClient *book_client = E_BOOK_CLIENT (source_object); + ContactCopyProcess *process = user_data; + GError *error = NULL; + + e_book_client_remove_contact_by_uid_finish (book_client, result, &error); + + if (error != NULL) { + g_warning ( + "%s: Remove contact by uid failed: %s", + G_STRFUNC, error->message); + g_error_free (error); + } + + process_unref (process); +} + +static void +do_delete_from_source (gpointer data, + gpointer user_data) +{ + ContactCopyProcess *process = user_data; + EContact *contact = data; + const gchar *id; + EBookClient *book_client = process->source; + + id = e_contact_get_const (contact, E_CONTACT_UID); + g_return_if_fail (id != NULL); + g_return_if_fail (book_client != NULL); + + process->count++; + e_book_client_remove_contact_by_uid (book_client, id, NULL, remove_contact_ready_cb, process); +} + +static void +delete_contacts (ContactCopyProcess *process) +{ + if (process->book_status == TRUE) { + g_slist_foreach (process->contacts, + do_delete_from_source, + process); + } +} + +static void +process_unref (ContactCopyProcess *process) +{ + process->count--; + if (process->count == 0) { + if (process->delete_from_source) { + delete_contacts (process); + /* to not repeate this again */ + process->delete_from_source = FALSE; + + if (process->count > 0) + return; + } + g_slist_free_full ( + process->contacts, + (GDestroyNotify) g_object_unref); + g_object_unref (process->source); + g_object_unref (process->destination); + g_object_unref (process->registry); + g_free (process); + } +} + +static void +contact_added_cb (EBookClient *book_client, + const GError *error, + const gchar *id, + gpointer user_data) +{ + ContactCopyProcess *process = user_data; + + if (error && !g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED) && + !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + process->book_status = FALSE; + eab_error_dialog (process->alert_sink, NULL, _("Error adding contact"), error); + } else if (g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED) || + g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + process->book_status = FALSE; + } + else { + /* success */ + process->book_status = TRUE; + } + + process_unref (process); +} + +static void +do_copy (gpointer data, + gpointer user_data) +{ + EBookClient *book_client; + EContact *contact; + ContactCopyProcess *process; + + process = user_data; + contact = data; + + book_client = process->destination; + e_contact_inline_local_photos (contact, NULL); + + process->count++; + eab_merging_book_add_contact ( + process->registry, book_client, + contact, contact_added_cb, process); +} + +static void +book_client_connect_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + ContactCopyProcess *process = user_data; + EClient *client; + GError *error = NULL; + + client = e_book_client_connect_finish (result, &error); + + /* Sanity check. */ + g_return_if_fail ( + ((client != NULL) && (error == NULL)) || + ((client == NULL) && (error != NULL))); + + if (error != NULL) { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_error_free (error); + goto exit; + } + + process->destination = E_BOOK_CLIENT (client); + process->book_status = TRUE; + g_slist_foreach (process->contacts, do_copy, process); + +exit: + process_unref (process); +} + +void +eab_transfer_contacts (ESourceRegistry *registry, + EBookClient *source_client, + GSList *contacts /* adopted */, + gboolean delete_from_source, + EAlertSink *alert_sink) +{ + ESource *source; + ESource *destination; + static gchar *last_uid = NULL; + ContactCopyProcess *process; + gchar *desc; + GtkWindow *window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (alert_sink))); + + g_return_if_fail (E_IS_SOURCE_REGISTRY (registry)); + g_return_if_fail (E_IS_BOOK_CLIENT (source_client)); + + if (contacts == NULL) + return; + + if (last_uid == NULL) + last_uid = g_strdup (""); + + if (contacts->next == NULL) { + if (delete_from_source) + desc = _("Move contact to"); + else + desc = _("Copy contact to"); + } else { + if (delete_from_source) + desc = _("Move contacts to"); + else + desc = _("Copy contacts to"); + } + + source = e_client_get_source (E_CLIENT (source_client)); + + destination = eab_select_source ( + registry, source, desc, NULL, last_uid, window); + + if (!destination) + return; + + if (strcmp (last_uid, e_source_get_uid (destination)) != 0) { + g_free (last_uid); + last_uid = g_strdup (e_source_get_uid (destination)); + } + + process = g_new (ContactCopyProcess, 1); + process->count = 1; + process->book_status = FALSE; + process->source = g_object_ref (source_client); + process->contacts = contacts; + process->destination = NULL; + process->registry = g_object_ref (registry); + process->alert_sink = alert_sink; + process->delete_from_source = delete_from_source; + + e_book_client_connect ( + destination, NULL, book_client_connect_cb, process); +} + +/* + * eab_format_address helper function + * + * Splits locales from en_US to array "en","us",NULL. When + * locales don't have the second part (for example "C"), + * the output array is "c",NULL + */ +static gchar ** +get_locales (void) +{ + gchar *locale, *l_locale; + gchar *dot; + gchar **split; + +#ifdef LC_ADDRESS + locale = g_strdup (setlocale (LC_ADDRESS, NULL)); +#else + locale = NULL; +#endif + if (!locale) + return NULL; + + l_locale = g_utf8_strdown (locale, -1); + g_free (locale); + + dot = strchr (l_locale, '.'); + if (dot != NULL) { + gchar *p = l_locale; + l_locale = g_strndup (l_locale, dot - l_locale); + g_free (p); + } + + split = g_strsplit (l_locale, "_", 2); + + g_free (l_locale); + return split; + +} + +static gchar * +get_locales_str (void) +{ + gchar *ret; + gchar **loc = get_locales (); + + if (!loc) + return g_strdup ("C"); + + if (!loc[0] || + (loc[0] && !loc[1])) /* We don't care about language now, we need a country at first! */ + ret = g_strdup ("C"); + else if (loc[0] && loc[1]) { + if (*loc[0]) + ret = g_strconcat (loc[LOCALES_COUNTRY], "_", loc[LOCALES_LANGUAGE], NULL); + else + ret = g_strdup (loc[LOCALES_COUNTRY]); + } + + g_strfreev (loc); + return ret; +} + +/* + * Reads countrytransl.map file, which contains map of localized + * country names and their ISO codes and tries to find matching record + * for given country. The search is case insensitive. + * When no record is found (country is probably in untranslated language), returns + * code of local computer country (from locales) + */ +static gchar * +country_to_ISO (const gchar *country) +{ + FILE *file = fopen (EVOLUTION_RULEDIR "/countrytransl.map", "r"); + gchar buffer[100]; + gint length = 100; + gchar **pair; + gchar *res; + gchar *l_country = g_utf8_strdown (country, -1); + + if (!file) { + gchar **loc; + g_warning ("%s: Failed to open countrytransl.map. Check your installation.", G_STRFUNC); + loc = get_locales (); + res = g_strdup (loc ? loc[LOCALES_COUNTRY] : NULL); + g_free (l_country); + g_strfreev (loc); + return res; + } + + while (fgets (buffer, length, file) != NULL) { + gchar *low = NULL; + pair = g_strsplit (buffer, "\t", 2); + + if (pair[0]) { + low = g_utf8_strdown (pair[0], -1); + if (g_utf8_collate (low, l_country) == 0) { + gchar *ret = g_strdup (pair[1]); + gchar *pos; + /* Remove trailing newline character */ + if ((pos = g_strrstr (ret, "\n")) != NULL) + pos[0] = '\0'; + fclose (file); + g_strfreev (pair); + g_free (low); + g_free (l_country); + return ret; + } + } + + g_strfreev (pair); + g_free (low); + } + + /* If we get here, then no match was found in the map file and we + * fallback to local system locales */ + fclose (file); + + pair = get_locales (); + res = g_strdup (pair ? pair[LOCALES_COUNTRY] : NULL); + g_strfreev (pair); + g_free (l_country); + return res; +} + +/* + * Tries to find given key in "country_LANGUAGE" group. When fails to find + * such group, then fallbacks to "country" group. When such group does not + * exist either, NULL is returned + */ +static gchar * +get_key_file_locale_string (GKeyFile *key_file, + const gchar *key, + const gchar *locale) +{ + gchar *result; + gchar *group; + + g_return_val_if_fail (locale, NULL); + + /* Default locale is in "country_lang", but such group may not exist. In such case use group "country" */ + if (g_key_file_has_group (key_file, locale)) + group = g_strdup (locale); + else { + gchar **locales = g_strsplit (locale, "_", 0); + group = g_strdup (locales[LOCALES_COUNTRY]); + g_strfreev (locales); + } + + /* When group or key does not exist, returns NULL and fallback string will be used */ + result = g_key_file_get_string (key_file, group, key, NULL); + g_free (group); + return result; +} + +static void +get_address_format (AddressFormat address_format, + const gchar *locale, + gchar **format, + gchar **country_position) +{ + GKeyFile *key_file; + GError *error; + gchar *loc; + const gchar *addr_key, *country_key; + + if (address_format == ADDRESS_FORMAT_HOME) { + addr_key = "AddressFormat"; + country_key = "CountryPosition"; + } else if (address_format == ADDRESS_FORMAT_BUSINESS) { + addr_key = "BusinessAddressFormat"; + country_key = "BusinessCountryPosition"; + } else { + return; + } + + if (locale == NULL) + loc = get_locales_str (); + else + loc = g_strdup (locale); + + error = NULL; + key_file = g_key_file_new (); + g_key_file_load_from_file (key_file, EVOLUTION_RULEDIR "/address_formats.dat", 0, &error); + if (error) { + g_warning ("%s: Failed to load address_formats.dat file: %s", G_STRFUNC, error->message); + *format = g_strdup (ADDRESS_DEFAULT_FORMAT); + *country_position = g_strdup (ADDRESS_DEFAULT_COUNTRY_POSITION); + g_key_file_free (key_file); + g_free (loc); + g_error_free (error); + return; + } + + if (format) { + if (*format) + g_free (*format); + *format = get_key_file_locale_string (key_file, addr_key, loc); + if (!*format && address_format == ADDRESS_FORMAT_HOME) { + *format = g_strdup (ADDRESS_DEFAULT_FORMAT); + } else if (!*format && address_format == ADDRESS_FORMAT_BUSINESS) + get_address_format (ADDRESS_FORMAT_HOME, loc, format, NULL); + } + + if (country_position) { + if (*country_position) + g_free (*country_position); + *country_position = get_key_file_locale_string (key_file, country_key, loc); + if (!*country_position && address_format == ADDRESS_FORMAT_HOME) + *country_position = g_strdup (ADDRESS_DEFAULT_COUNTRY_POSITION); + else if (!*country_position && address_format == ADDRESS_FORMAT_BUSINESS) + get_address_format (ADDRESS_FORMAT_HOME, loc, NULL, country_position); + } + + g_free (loc); + g_key_file_free (key_file); +} + +static const gchar * +find_balanced_bracket (const gchar *str) +{ + gint balance_counter = 0; + gint i = 0; + + do { + if (str[i] == '(') + balance_counter++; + + if (str[i] == ')') + balance_counter--; + + i++; + + } while ((balance_counter > 0) && (str[i])); + + if (balance_counter > 0) + return str; + + return str + i; +} + +static GString * +string_append_upper (GString *str, + const gchar *c) +{ + gchar *up_c; + + g_return_val_if_fail (str, NULL); + + if (!c || !*c) + return str; + + up_c = g_utf8_strup (c, -1); + str = g_string_append (str, up_c); + g_free (up_c); + + return str; +} + +static gboolean +parse_address_template_section (const gchar *format, + const gchar *realname, + const gchar *org_name, + EContactAddress *address, + gchar **result) + +{ + const gchar *pos, *old_pos; + gboolean ret = FALSE; /* Indicates, wheter at least something was replaced */ + + GString *res = g_string_new (""); + + pos = format; + old_pos = pos; + while ((pos = strchr (pos, '%')) != NULL) { + + if (old_pos != pos) + g_string_append_len (res, old_pos, pos - old_pos); + + switch (pos[1]) { + case 'n': + if (realname && *realname) { + g_string_append (res, realname); + ret = TRUE; + } + pos += 2; /* Jump behind the modifier, see what's next */ + break; + case 'N': + if (realname && *realname) { + string_append_upper (res, realname); + ret = TRUE; + } + pos += 2; + break; + case 'm': + if (org_name && *org_name) { + g_string_append (res, org_name); + ret = TRUE; + } + pos += 2; + break; + case 'M': + if (org_name && *org_name) { + string_append_upper (res, org_name); + ret = TRUE; + } + pos += 2; + break; + case 'p': + if (address->po && *(address->po)) { + g_string_append (res, address->po); + ret = TRUE; + } + pos += 2; + break; + case 's': + if (address->street && *(address->street)) { + g_string_append (res, address->street); + if (address->ext && *(address->ext)) + g_string_append_printf ( + res, "\n%s", + address->ext); + ret = TRUE; + } + pos += 2; + break; + case 'S': + if (address->street && *(address->street)) { + string_append_upper (res, address->street); + if (address->ext && *(address->ext)) { + g_string_append (res, "\n"); + string_append_upper (res, address->ext); + } + ret = TRUE; + } + pos += 2; + break; + case 'z': + if (address->code && *(address->code)) { + g_string_append (res, address->code); + ret = TRUE; + } + pos += 2; + break; + case 'l': + if (address->locality && *(address->locality)) { + g_string_append (res, address->locality); + ret = TRUE; + } + pos += 2; + break; + case 'L': + if (address->locality && *(address->locality)) { + string_append_upper (res, address->locality); + ret = TRUE; + } + pos += 2; + break; + case 'r': + if (address->region && *(address->region)) { + g_string_append (res, address->region); + ret = TRUE; + } + pos += 2; + break; + case 'R': + if (address->region && *(address->region)) { + string_append_upper (res, address->region); + ret = TRUE; + } + pos += 2; + break; + case ',': + if (ret && (pos >= format + 2) && /* If there's something before %, */ + (g_ascii_strcasecmp (pos - 2, "\n") != 0) && /* And if it is not a newline */ + (g_ascii_strcasecmp (pos - 2, "%w") != 0)) /* Nor whitespace */ + g_string_append (res, ", "); + pos += 2; + break; + case 'w': + if (ret && (pos >= format + 2) && + (g_ascii_strcasecmp (pos - 2, "\n") != 0) && + (g_ascii_strcasecmp (pos - 1, " ") != 0)) + g_string_append (res, " "); + pos += 2; + break; + case '0': { + const gchar *bpos1, *bpos2; + gchar *inner; + gchar *ires; + gboolean replaced; + + bpos1 = pos + 2; + bpos2 = find_balanced_bracket (bpos1); + + inner = g_strndup (bpos1 + 1, bpos2 - bpos1 - 2); /* Get inner content of the %0 (...) */ + replaced = parse_address_template_section (inner, realname, org_name, address, &ires); + if (replaced) + g_string_append (res, ires); + + g_free (ires); + g_free (inner); + + ret = replaced; + pos += (bpos2 - bpos1 + 2); + } break; + } + + old_pos = pos; + } + g_string_append (res, old_pos); + + *result = g_strdup (res->str); + + g_string_free (res, TRUE); + + return ret; +} + +gchar * +eab_format_address (EContact *contact, + EContactField address_type) +{ + gchar *result; + gchar *format = NULL; + gchar *country_position = NULL; + gchar *locale; + EContactAddress *addr = e_contact_get (contact, address_type); + + if (!addr) + return NULL; + + if (!addr->po && !addr->ext && !addr->street && !addr->locality && !addr->region && + !addr->code && !addr->country) { + e_contact_address_free (addr); + return NULL; + } + + if (addr->country) { + gchar *cntry = country_to_ISO (addr->country); + gchar **loc = get_locales (); + locale = g_strconcat (loc ? loc[LOCALES_LANGUAGE] : "C", "_", cntry, NULL); + g_strfreev (loc); + g_free (cntry); + } else + locale = get_locales_str (); + + if (address_type == E_CONTACT_ADDRESS_HOME) + get_address_format (ADDRESS_FORMAT_HOME, locale, &format, &country_position); + else if (address_type == E_CONTACT_ADDRESS_WORK) + get_address_format (ADDRESS_FORMAT_BUSINESS, locale, &format, &country_position); + else { + e_contact_address_free (addr); + g_free (locale); + return NULL; + } + + /* Expand all the variables in format. + * Don't display organization in home address; + * and skip full names, as it's part of the EContact itself, + * check this bug for reason: https://bugzilla.gnome.org/show_bug.cgi?id=667912 + */ + parse_address_template_section ( + format, + NULL, + (address_type == E_CONTACT_ADDRESS_WORK) ? + e_contact_get_const (contact, E_CONTACT_ORG) : NULL, + addr, + &result); + + /* Add the country line. In some countries, the address can be located above the + * rest of the address */ + if (addr->country && country_position) { + gchar *country_upper = g_utf8_strup (addr->country, -1); + gchar *p = result; + if (g_strcmp0 (country_position, "BELOW") == 0) { + result = g_strconcat (p, "\n\n", country_upper, NULL); + g_free (p); + } else if (g_strcmp0 (country_position, "below") == 0) { + result = g_strconcat (p, "\n\n", addr->country, NULL); + g_free (p); + } else if (g_strcmp0 (country_position, "ABOVE") == 0) { + result = g_strconcat (country_upper, "\n\n", p, NULL); + g_free (p); + } else if (g_strcmp0 (country_position, "above") == 0) { + result = g_strconcat (addr->country, "\n\n", p, NULL); + g_free (p); + } + g_free (country_upper); + } + + e_contact_address_free (addr); + g_free (locale); + g_free (format); + g_free (country_position); + + return result; +} diff --git a/addressbook/gui/widgets/eab-gui-util.h b/addressbook/gui/widgets/eab-gui-util.h new file mode 100644 index 0000000000..f169f8b8d3 --- /dev/null +++ b/addressbook/gui/widgets/eab-gui-util.h @@ -0,0 +1,63 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Chris Toshok <toshok@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __E_ADDRESSBOOK_UTIL_H__ +#define __E_ADDRESSBOOK_UTIL_H__ + +#include <gtk/gtk.h> +#include <libebook/libebook.h> + +#include <e-util/e-util.h> + +G_BEGIN_DECLS + +void eab_error_dialog (EAlertSink *alert_sink, + GtkWindow *parent, + const gchar *msg, + const GError *error); +void eab_load_error_dialog (GtkWidget *parent, + EAlertSink *alert_sink, + ESource *source, + const GError *error); +void eab_search_result_dialog (EAlertSink *alert_sink, + const GError *error); +gint eab_prompt_save_dialog (GtkWindow *parent); +void eab_transfer_contacts (ESourceRegistry *registry, + EBookClient *source_client, + GSList *contacts, /* adopted */ + gboolean delete_from_source, + EAlertSink *alert_sink); +gchar * eab_suggest_filename (const GSList *contact_list); +ESource * eab_select_source (ESourceRegistry *registry, + ESource *except_source, + const gchar *title, + const gchar *message, + const gchar *select_uid, + GtkWindow *parent); + +gchar * eab_format_address (EContact *contact, + EContactField address_type); + +G_END_DECLS + +#endif /* __E_ADDRESSBOOK_UTIL_H__ */ diff --git a/addressbook/gui/widgets/gal-view-factory-minicard.c b/addressbook/gui/widgets/gal-view-factory-minicard.c deleted file mode 100644 index 10e13d9bdf..0000000000 --- a/addressbook/gui/widgets/gal-view-factory-minicard.c +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * gal-view-factory-minicard.c: A View Factory - * - * Authors: - * Chris Lahey <clahey@ximian.com> - * - * (C) 2000, 2001 Ximian, Inc. - */ -#include <config.h> -#include <glib.h> -#include <libgnome/gnome-defs.h> -#include <libgnome/gnome-i18n.h> -#include "gal-view-factory-minicard.h" -#include "gal-view-minicard.h" - -#define GVFE_CLASS(e) ((GalViewFactoryMinicardClass *)((GtkObject *)e)->klass) - -#define PARENT_TYPE gal_view_factory_get_type () - -static GalViewFactoryClass *gal_view_factory_minicard_parent_class; - -static const char * -gal_view_factory_minicard_get_title (GalViewFactory *factory) -{ - return _("Card View"); -} - -static GalView * -gal_view_factory_minicard_new_view (GalViewFactory *factory, - const char *name) -{ - return gal_view_minicard_new(name); -} - -static const char * -gal_view_factory_minicard_get_type_code (GalViewFactory *factory) -{ - return "minicard"; -} - -static void -gal_view_factory_minicard_destroy (GtkObject *object) -{ -#if 0 - GalViewFactoryMinicard *factory = GAL_VIEW_FACTORY_MINICARD(object); -#endif -} - -static void -gal_view_factory_minicard_class_init (GtkObjectClass *object_class) -{ - GalViewFactoryClass *view_factory_class = GAL_VIEW_FACTORY_CLASS(object_class); - gal_view_factory_minicard_parent_class = gtk_type_class (PARENT_TYPE); - - view_factory_class->get_title = gal_view_factory_minicard_get_title; - view_factory_class->new_view = gal_view_factory_minicard_new_view; - view_factory_class->get_type_code = gal_view_factory_minicard_get_type_code; - - object_class->destroy = gal_view_factory_minicard_destroy; -} - -static void -gal_view_factory_minicard_init (GalViewFactoryMinicard *factory) -{ -} - -/** - * gal_view_minicard_new - * - * A new GalViewFactory for creating Minicard views. Create one of - * these and pass it to GalViewCollection for use. - * - * Returns: The new GalViewFactoryMinicard. - */ -GalViewFactory * -gal_view_factory_minicard_new (void) -{ - return gal_view_factory_minicard_construct (gtk_type_new (gal_view_factory_minicard_get_type ())); -} - -/** - * gal_view_minicard_construct - * @factory: The factory to construct - * - * constructs the GalViewFactoryMinicard. To be used by subclasses and - * language bindings. - * - * Returns: The GalViewFactoryMinicard. - */ -GalViewFactory * -gal_view_factory_minicard_construct (GalViewFactoryMinicard *factory) -{ - return GAL_VIEW_FACTORY(factory); -} - -GtkType -gal_view_factory_minicard_get_type (void) -{ - static guint type = 0; - - if (!type) - { - GtkTypeInfo info = - { - "GalViewFactoryMinicard", - sizeof (GalViewFactoryMinicard), - sizeof (GalViewFactoryMinicardClass), - (GtkClassInitFunc) gal_view_factory_minicard_class_init, - (GtkObjectInitFunc) gal_view_factory_minicard_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - type = gtk_type_unique (PARENT_TYPE, &info); - } - - return type; -} diff --git a/addressbook/gui/widgets/gal-view-factory-minicard.h b/addressbook/gui/widgets/gal-view-factory-minicard.h deleted file mode 100644 index 3816fdba46..0000000000 --- a/addressbook/gui/widgets/gal-view-factory-minicard.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * gal-view-factory-minicard.c: A View Factory - * - * Authors: - * Chris Lahey <clahey@ximian.com> - * - * (C) 2000, 2001 Ximian, Inc. - */ -#ifndef _GAL_VIEW_FACTORY_MINICARD_H_ -#define _GAL_VIEW_FACTORY_MINICARD_H_ - -#include <gtk/gtkobject.h> -#include <gal/menus/gal-view-factory.h> - -#define GAL_VIEW_FACTORY_MINICARD_TYPE (gal_view_factory_minicard_get_type ()) -#define GAL_VIEW_FACTORY_MINICARD(o) (GTK_CHECK_CAST ((o), GAL_VIEW_FACTORY_MINICARD_TYPE, GalViewFactoryMinicard)) -#define GAL_VIEW_FACTORY_MINICARD_CLASS(k) (GTK_CHECK_CLASS_CAST((k), GAL_VIEW_FACTORY_MINICARD_TYPE, GalViewFactoryMinicardClass)) -#define GAL_IS_VIEW_FACTORY_MINICARD(o) (GTK_CHECK_TYPE ((o), GAL_VIEW_FACTORY_MINICARD_TYPE)) -#define GAL_IS_VIEW_FACTORY_MINICARD_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), GAL_VIEW_FACTORY_MINICARD_TYPE)) - -typedef struct { - GalViewFactory base; -} GalViewFactoryMinicard; - -typedef struct { - GalViewFactoryClass parent_class; -} GalViewFactoryMinicardClass; - -/* Standard functions */ -GtkType gal_view_factory_minicard_get_type (void); -GalViewFactory *gal_view_factory_minicard_new (void); -GalViewFactory *gal_view_factory_minicard_construct (GalViewFactoryMinicard *factory); - -#endif /* _GAL_VIEW_FACTORY_MINICARD_H_ */ diff --git a/addressbook/gui/widgets/gal-view-minicard.c b/addressbook/gui/widgets/gal-view-minicard.c index b3162e51d1..99e8686675 100644 --- a/addressbook/gui/widgets/gal-view-minicard.c +++ b/addressbook/gui/widgets/gal-view-minicard.c @@ -1,120 +1,146 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* + * * gal-view-minicard.c: An Minicard View * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * * Authors: - * Chris Lahey <clahey@ximian.com> + * Chris Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * - * (C) 2000, 2001 Ximian, Inc. */ + +#ifdef HAVE_CONFIG_H #include <config.h> -#include "gal-view-minicard.h" -#include <gnome-xml/parser.h> -#include <gal/util/e-xml-utils.h> +#endif + +#include <libxml/parser.h> -#define PARENT_TYPE gal_view_get_type () -#define d(x) x +#include "gal-view-minicard.h" -static GalViewClass *gal_view_minicard_parent_class; +G_DEFINE_TYPE ( + GalViewMinicard, + gal_view_minicard, + GAL_TYPE_VIEW) static void -gal_view_minicard_edit (GalView *view) +view_minicard_column_width_changed (EAddressbookView *address_view, + gdouble width) { - /* GalViewMinicard *minicard_view = GAL_VIEW_MINICARD(view); */ + GalView *view; + GalViewInstance *view_instance; + GalViewMinicard *view_minicard; + + view_instance = e_addressbook_view_get_view_instance (address_view); + view = gal_view_instance_get_current_view (view_instance); + view_minicard = GAL_VIEW_MINICARD (view); + + if (view_minicard->column_width != width) { + view_minicard->column_width = width; + gal_view_changed (view); + } } -static void -gal_view_minicard_load (GalView *view, - const char *filename) +static void +view_minicard_finalize (GObject *object) { - xmlDoc *doc; - doc = xmlParseFile (filename); - if (doc) { - xmlNode *root = xmlDocGetRootElement(doc); - GAL_VIEW_MINICARD (view)->column_width = e_xml_get_double_prop_by_name_with_default (root, "column_width", 150); - xmlFreeDoc(doc); - } + GalViewMinicard *view = GAL_VIEW_MINICARD (object); + + gal_view_minicard_detach (view); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (gal_view_minicard_parent_class)->finalize (object); } static void -gal_view_minicard_save (GalView *view, - const char *filename) +view_minicard_load (GalView *view, + const gchar *filename) { + GalViewMinicard *view_minicard; xmlDoc *doc; xmlNode *root; - doc = xmlNewDoc("1.0"); - root = xmlNewNode (NULL, "EMinicardViewState"); - e_xml_set_double_prop_by_name (root, "column_width", GAL_VIEW_MINICARD (view)->column_width); - xmlDocSetRootElement(doc, root); - xmlSaveFile(filename, doc); - xmlFreeDoc(doc); -} + view_minicard = GAL_VIEW_MINICARD (view); -static const char * -gal_view_minicard_get_title (GalView *view) -{ - return GAL_VIEW_MINICARD(view)->title; + doc = e_xml_parse_file (filename); + g_return_if_fail (doc != NULL); + + root = xmlDocGetRootElement (doc); + view_minicard->column_width = + e_xml_get_double_prop_by_name_with_default ( + root, (guchar *) "column_width", 225); + xmlFreeDoc (doc); } static void -gal_view_minicard_set_title (GalView *view, - const char *title) +view_minicard_save (GalView *view, + const gchar *filename) { - g_free(GAL_VIEW_MINICARD(view)->title); - GAL_VIEW_MINICARD(view)->title = g_strdup(title); -} + GalViewMinicard *view_minicard; + xmlDoc *doc; + xmlNode *root; -static const char * -gal_view_minicard_get_type_code (GalView *view) -{ - return "minicard"; + view_minicard = GAL_VIEW_MINICARD (view); + + doc = xmlNewDoc ((guchar *) "1.0"); + root = xmlNewNode (NULL, (guchar *) "EMinicardViewState"); + e_xml_set_double_prop_by_name ( + root, (guchar *) "column_width", + view_minicard->column_width); + xmlDocSetRootElement (doc, root); + e_xml_save_file (filename, doc); + xmlFreeDoc (doc); } static GalView * -gal_view_minicard_clone (GalView *view) +view_minicard_clone (GalView *view) { - GalViewMinicard *gvm, *new; + GalViewMinicard *view_minicard; + GalView *clone; - gvm = GAL_VIEW_MINICARD(view); + /* Chain up to parent's clone() method. */ + clone = GAL_VIEW_CLASS (gal_view_minicard_parent_class)->clone (view); - new = gtk_type_new (gal_view_minicard_get_type ()); - new->title = g_strdup (gvm->title); - new->column_width = gvm->column_width; + view_minicard = GAL_VIEW_MINICARD (view); + GAL_VIEW_MINICARD (clone)->column_width = view_minicard->column_width; - return GAL_VIEW(new); + return clone; } static void -gal_view_minicard_destroy (GtkObject *object) +gal_view_minicard_class_init (GalViewMinicardClass *class) { - GalViewMinicard *view = GAL_VIEW_MINICARD(object); - gal_view_minicard_detach (view); - g_free(view->title); -} + GObjectClass *object_class; + GalViewClass *gal_view_class; + + object_class = G_OBJECT_CLASS (class); + object_class->finalize = view_minicard_finalize; + + gal_view_class = GAL_VIEW_CLASS (class); + gal_view_class->type_code = "minicard"; + gal_view_class->load = view_minicard_load; + gal_view_class->save = view_minicard_save; + gal_view_class->clone = view_minicard_clone; -static void -gal_view_minicard_class_init (GtkObjectClass *object_class) -{ - GalViewClass *gal_view_class = GAL_VIEW_CLASS(object_class); - gal_view_minicard_parent_class = gtk_type_class (PARENT_TYPE); - - gal_view_class->edit = gal_view_minicard_edit ; - gal_view_class->load = gal_view_minicard_load ; - gal_view_class->save = gal_view_minicard_save ; - gal_view_class->get_title = gal_view_minicard_get_title ; - gal_view_class->set_title = gal_view_minicard_set_title ; - gal_view_class->get_type_code = gal_view_minicard_get_type_code; - gal_view_class->clone = gal_view_minicard_clone ; - - object_class->destroy = gal_view_minicard_destroy ; } static void -gal_view_minicard_init (GalViewMinicard *gvm) +gal_view_minicard_init (GalViewMinicard *gvm) { - gvm->title = NULL; - gvm->column_width = 150.0; + gvm->column_width = 225.0; gvm->emvw = NULL; gvm->emvw_column_width_changed_id = 0; @@ -132,90 +158,47 @@ gal_view_minicard_init (GalViewMinicard *gvm) GalView * gal_view_minicard_new (const gchar *title) { - return gal_view_minicard_construct (gtk_type_new (gal_view_minicard_get_type ()), title); -} - -/** - * gal_view_minicard_construct - * @view: The view to construct. - * @title: The name of the new view. - * - * constructs the GalViewMinicard. To be used by subclasses and - * language bindings. - * - * Returns: The GalViewMinicard. - */ -GalView * -gal_view_minicard_construct (GalViewMinicard *view, - const gchar *title) -{ - view->title = g_strdup(title); - return GAL_VIEW(view); + return g_object_new (GAL_TYPE_VIEW_MINICARD, "title", title, NULL); } -GtkType -gal_view_minicard_get_type (void) +void +gal_view_minicard_attach (GalViewMinicard *view, + EAddressbookView *address_view) { - static guint type = 0; - - if (!type) - { - GtkTypeInfo info = - { - "GalViewMinicard", - sizeof (GalViewMinicard), - sizeof (GalViewMinicardClass), - (GtkClassInitFunc) gal_view_minicard_class_init, - (GtkObjectInitFunc) gal_view_minicard_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - type = gtk_type_unique (PARENT_TYPE, &info); - } + GObject *object; - return type; -} + g_return_if_fail (GAL_IS_VIEW_MINICARD (view)); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (address_view)); -static void -column_width_changed (ETable *table, double width, GalViewMinicard *view) -{ - d(g_print("%s: Old width = %f, New width = %f\n", __FUNCTION__, view->column_width, width)); - if (view->column_width != width) { - view->column_width = width; - gal_view_changed(GAL_VIEW(view)); - } -} + object = e_addressbook_view_get_view_object (address_view); + g_return_if_fail (E_IS_MINICARD_VIEW_WIDGET (object)); -void -gal_view_minicard_attach (GalViewMinicard *view, EMinicardViewWidget *emvw) -{ gal_view_minicard_detach (view); + view->emvw = g_object_ref (object); - view->emvw = emvw; - - gtk_object_ref (GTK_OBJECT (view->emvw)); - - gtk_object_set (GTK_OBJECT (view->emvw), - "column_width", (int) view->column_width, - NULL); + g_object_set (view->emvw, "column-width", view->column_width, NULL); view->emvw_column_width_changed_id = - gtk_signal_connect(GTK_OBJECT(view->emvw), "column_width_changed", - GTK_SIGNAL_FUNC (column_width_changed), view); + g_signal_connect_swapped ( + view->emvw, "column-width-changed", + G_CALLBACK (view_minicard_column_width_changed), + address_view); } void gal_view_minicard_detach (GalViewMinicard *view) { + g_return_if_fail (GAL_IS_VIEW_MINICARD (view)); + if (view->emvw == NULL) return; - if (view->emvw_column_width_changed_id) { - gtk_signal_disconnect (GTK_OBJECT (view->emvw), - view->emvw_column_width_changed_id); + + if (view->emvw_column_width_changed_id > 0) { + g_signal_handler_disconnect ( + view->emvw, view->emvw_column_width_changed_id); view->emvw_column_width_changed_id = 0; } - gtk_object_unref (GTK_OBJECT (view->emvw)); + + g_object_unref (view->emvw); view->emvw = NULL; } diff --git a/addressbook/gui/widgets/gal-view-minicard.h b/addressbook/gui/widgets/gal-view-minicard.h index 31a28c56d9..4cec9568ca 100644 --- a/addressbook/gui/widgets/gal-view-minicard.h +++ b/addressbook/gui/widgets/gal-view-minicard.h @@ -1,46 +1,77 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gal-view-minicard.h: An Minicard View * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * * Authors: - * Chris Lahey <clahey@ximian.com> + * Chris Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * - * (C) 2000, 2001 Ximian, Inc. */ -#ifndef _GAL_VIEW_MINICARD_H_ -#define _GAL_VIEW_MINICARD_H_ -#include <gtk/gtkobject.h> -#include <gal/menus/gal-view.h> +#ifndef GAL_VIEW_MINICARD_H +#define GAL_VIEW_MINICARD_H + +#include <e-util/e-util.h> #include <e-minicard-view-widget.h> +#include "e-addressbook-view.h" -#define GAL_VIEW_MINICARD_TYPE (gal_view_minicard_get_type ()) -#define GAL_VIEW_MINICARD(o) (GTK_CHECK_CAST ((o), GAL_VIEW_MINICARD_TYPE, GalViewMinicard)) -#define GAL_VIEW_MINICARD_CLASS(k) (GTK_CHECK_CLASS_CAST((k), GAL_VIEW_MINICARD_TYPE, GalViewMinicardClass)) -#define GAL_IS_VIEW_MINICARD(o) (GTK_CHECK_TYPE ((o), GAL_VIEW_MINICARD_TYPE)) -#define GAL_IS_VIEW_MINICARD_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), GAL_VIEW_MINICARD_TYPE)) +/* Standard GObject macros */ +#define GAL_TYPE_VIEW_MINICARD \ + (gal_view_minicard_get_type ()) +#define GAL_VIEW_MINICARD(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), GAL_TYPE_VIEW_MINICARD, GalViewMinicard)) +#define GAL_VIEW_MINICARD_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), GAL_TYPE_VIEW_MINICARD, GalViewMinicardClass)) +#define GAL_IS_VIEW_MINICARD(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), GAL_TYPE_VIEW_MINICARD)) +#define GAL_IS_VIEW_MINICARD_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), GAL_TYPE_VIEW_MINICARD)) +#define GAL_VIEW_MINICARD_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), GAL_TYPE_VIEW_MINICARD, GalViewMinicardClass)) -typedef struct { - GalView base; +G_BEGIN_DECLS - char *title; - double column_width; +typedef struct _GalViewMinicard GalViewMinicard; +typedef struct _GalViewMinicardClass GalViewMinicardClass; + +struct _GalViewMinicard { + GalView parent; + + gdouble column_width; EMinicardViewWidget *emvw; guint emvw_column_width_changed_id; -} GalViewMinicard; +}; -typedef struct { +struct _GalViewMinicardClass { GalViewClass parent_class; -} GalViewMinicardClass; - -/* Standard functions */ -GtkType gal_view_minicard_get_type (void); -GalView *gal_view_minicard_new (const gchar *title); -GalView *gal_view_minicard_construct (GalViewMinicard *view, - const gchar *title); -void gal_view_minicard_attach (GalViewMinicard *view, - EMinicardViewWidget *emvw); -void gal_view_minicard_detach (GalViewMinicard *view); - -#endif /* _GAL_VIEW_MINICARD_H_ */ +}; + +GType gal_view_minicard_get_type (void); +GalView * gal_view_minicard_new (const gchar *title); +void gal_view_minicard_attach (GalViewMinicard *view, + EAddressbookView *address_view); +void gal_view_minicard_detach (GalViewMinicard *view); + +G_END_DECLS + +#endif /* GAL_VIEW_MINICARD_H */ diff --git a/addressbook/gui/widgets/test-minicard-label.c b/addressbook/gui/widgets/test-minicard-label.c deleted file mode 100644 index 7b1919aef4..0000000000 --- a/addressbook/gui/widgets/test-minicard-label.c +++ /dev/null @@ -1,131 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* test-minicard-label.c - * - * Copyright (C) 2000 Ximian, Inc. - * Author: Chris Lahey <clahey@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 <gtk/gtkmain.h> -#include <libgnomeui/gnome-app.h> -#include <libgnomeui/gnome-canvas-rect-ellipse.h> -#include <libgnomeui/gnome-init.h> -#include <gal/widgets/e-canvas.h> -#include "e-minicard-label.h" - -/* This is a horrible thing to do, but it is just a test. */ -GnomeCanvasItem *label; -GnomeCanvasItem *rect; - -static void destroy_callback(GtkWidget *app, gpointer data) -{ - exit(0); -} - -static void allocate_callback(GtkWidget *canvas, GtkAllocation *allocation, gpointer data) -{ - gnome_canvas_set_scroll_region(GNOME_CANVAS( canvas ), 0, 0, allocation->width, allocation->height ); - gnome_canvas_item_set( label, - "width", (double) allocation->width, - "height", (double) allocation->height, - NULL ); - gnome_canvas_item_set( rect, - "x2", (double) allocation->width, - "y2", (double) allocation->height, - NULL ); -} - -#if 0 -static void about_callback( GtkWidget *widget, gpointer data ) -{ - - const gchar *authors[] = - { - "Christopher James Lahey <clahey@umich.edu>", - NULL - }; - - GtkWidget *about = - gnome_about_new ( _( "Minicard Label Test" ), VERSION, - _( "Copyright (C) 2000, Ximian, Inc." ), - authors, - _( "This should test the minicard label canvas item" ), - NULL); - gtk_widget_show (about); -} -#endif - -static void button_press_callback( GtkWidget *widget, gpointer data ) -{ - gnome_canvas_item_grab_focus( label ); -} - -int main( int argc, char *argv[] ) -{ - GtkWidget *app; - GtkWidget *canvas; - - /* bindtextdomain (PACKAGE, GNOMELOCALEDIR); - textdomain (PACKAGE);*/ - - gnome_init( "Minicard Label Test", VERSION, argc, argv); - app = gnome_app_new("Minicard Label Test", NULL); - - canvas = e_canvas_new(); - rect = gnome_canvas_item_new( gnome_canvas_root( GNOME_CANVAS( canvas ) ), - gnome_canvas_rect_get_type(), - "x1", (double) 0, - "y1", (double) 0, - "x2", (double) 100, - "y2", (double) 100, - "fill_color", "white", - NULL ); - label = e_minicard_label_new(gnome_canvas_root( GNOME_CANVAS( canvas ) )); - gnome_canvas_item_set( label, - "width", (double) 100, - "height", (double) 100, - "fieldname", "Full Name:", - "field", "Christopher James Lahey", - NULL ); - gnome_canvas_set_scroll_region ( GNOME_CANVAS( canvas ), - 0, 0, - 100, 100 ); - - gnome_app_set_contents( GNOME_APP( app ), canvas ); - - - /* Connect the signals */ - gtk_signal_connect( GTK_OBJECT( app ), "destroy", - GTK_SIGNAL_FUNC( destroy_callback ), - ( gpointer ) app ); - - gtk_signal_connect( GTK_OBJECT( canvas ), "size_allocate", - GTK_SIGNAL_FUNC( allocate_callback ), - ( gpointer ) app ); - - gtk_signal_connect( GTK_OBJECT( canvas ), "button_press_event", - GTK_SIGNAL_FUNC( button_press_callback ), - ( gpointer ) app ); - - gtk_widget_show_all( app ); - - gtk_main(); - - /* Not reached. */ - return 0; -} diff --git a/addressbook/gui/widgets/test-minicard-view.c b/addressbook/gui/widgets/test-minicard-view.c deleted file mode 100644 index caa9dac270..0000000000 --- a/addressbook/gui/widgets/test-minicard-view.c +++ /dev/null @@ -1,208 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* test-reflow.c - * - * Copyright (C) 2000 Ximian, Inc. - * Author: Chris Lahey <clahey@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 <libgnorba/gnorba.h> -#include <e-util/e-canvas.h> -#include "e-minicard-view.h" - -/* This is a horrible thing to do, but it is just a test. */ -GnomeCanvasItem *reflow; -GnomeCanvasItem *rect; -GtkAllocation last_alloc; - -CORBA_Environment ev; -CORBA_ORB orb; - -static void -init_bonobo (int argc, char **argv) -{ - - gnome_CORBA_init_with_popt_table ( - "Reflow Test", VERSION, - &argc, argv, NULL, 0, NULL, GNORBA_INIT_SERVER_FUNC, &ev); - - orb = gnome_CORBA_ORB (); - - if (bonobo_init (orb, NULL, NULL) == FALSE) - g_error (_("Could not initialize Bonobo")); - -} - -static void destroy_callback(GtkWidget *app, gpointer data) -{ - exit(0); -} - -static void allocate_callback(GtkWidget *canvas, GtkAllocation *allocation, gpointer data) -{ - double width; - last_alloc = *allocation; - gnome_canvas_item_set( reflow, - "height", (double) allocation->height, - NULL ); - gnome_canvas_item_set( reflow, - "minimum_width", (double) allocation->width, - NULL ); - gtk_object_get(GTK_OBJECT(reflow), - "width", &width, - NULL); - width = MAX(width, allocation->width); - gnome_canvas_set_scroll_region(GNOME_CANVAS( canvas ), 0, 0, width, allocation->height ); - gnome_canvas_item_set( rect, - "x2", (double) width, - "y2", (double) allocation->height, - NULL ); -} - -static void resize(GnomeCanvas *canvas, gpointer data) -{ - double width; - gtk_object_get(GTK_OBJECT(reflow), - "width", &width, - NULL); - width = MAX(width, last_alloc.width); - gnome_canvas_set_scroll_region(canvas , 0, 0, width, last_alloc.height ); - gnome_canvas_item_set( rect, - "x2", (double) width, - "y2", (double) last_alloc.height, - NULL ); -} - -#if 0 -static void about_callback( GtkWidget *widget, gpointer data ) -{ - - const gchar *authors[] = - { - "Christopher James Lahey <clahey@umich.edu>", - NULL - }; - - GtkWidget *about = - gnome_about_new ( _( "Reflow Test" ), VERSION, - _( "Copyright (C) 2000, Ximian, Inc." ), - authors, - _( "This should test the reflow canvas item" ), - NULL); - gtk_widget_show (about); -} -#endif - -static void -book_open_cb (EBook *book, EBookStatus status, gpointer closure) -{ - if (status == E_BOOK_STATUS_SUCCESS) - gnome_canvas_item_set(reflow, - "book", book, - NULL); -} - -static guint -ebook_create (void) -{ - EBook *book; - - book = e_book_new (); - - if (!book) { - printf ("%s: %s(): Couldn't create EBook, bailing.\n", - __FILE__, - __FUNCTION__); - return FALSE; - } - - - if (! e_book_load_uri (book, "file:/tmp/test.db", book_open_cb, NULL)) { - printf ("error calling load_uri!\n"); - } - - - return FALSE; -} - -int main( int argc, char *argv[] ) -{ - GtkWidget *app; - GtkWidget *canvas; - GtkWidget *vbox; - GtkWidget *scrollbar; - - /* bindtextdomain (PACKAGE, GNOMELOCALEDIR); - textdomain (PACKAGE);*/ - - CORBA_exception_init (&ev); - init_bonobo (argc, argv); - - app = gnome_app_new("Reflow Test", NULL); - - vbox = gtk_vbox_new(FALSE, 0); - - canvas = e_canvas_new(); - rect = gnome_canvas_item_new( gnome_canvas_root( GNOME_CANVAS( canvas ) ), - gnome_canvas_rect_get_type(), - "x1", (double) 0, - "y1", (double) 0, - "x2", (double) 100, - "y2", (double) 100, - "fill_color", "white", - NULL ); - reflow = gnome_canvas_item_new( gnome_canvas_root( GNOME_CANVAS( canvas ) ), - e_minicard_view_get_type(), - "height", (double) 100, - "minimum_width", (double) 100, - NULL ); - gtk_signal_connect( GTK_OBJECT( canvas ), "reflow", - GTK_SIGNAL_FUNC( resize ), - ( gpointer ) app); - - gnome_canvas_set_scroll_region ( GNOME_CANVAS( canvas ), - 0, 0, - 100, 100 ); - - gtk_box_pack_start(GTK_BOX(vbox), canvas, TRUE, TRUE, 0); - - scrollbar = gtk_hscrollbar_new(gtk_layout_get_hadjustment(GTK_LAYOUT(canvas))); - - gtk_box_pack_start(GTK_BOX(vbox), scrollbar, FALSE, FALSE, 0); - - gnome_app_set_contents( GNOME_APP( app ), vbox ); - - /* Connect the signals */ - gtk_signal_connect( GTK_OBJECT( app ), "destroy", - GTK_SIGNAL_FUNC( destroy_callback ), - ( gpointer ) app ); - - gtk_signal_connect( GTK_OBJECT( canvas ), "size_allocate", - GTK_SIGNAL_FUNC( allocate_callback ), - ( gpointer ) app ); - - gtk_widget_show_all( app ); - gdk_window_set_back_pixmap( GTK_LAYOUT(canvas)->bin_window, NULL, FALSE); - - gtk_idle_add ((GtkFunction) ebook_create, NULL); - - bonobo_main (); - - /* Not reached. */ - return 0; -} diff --git a/addressbook/gui/widgets/test-minicard.c b/addressbook/gui/widgets/test-minicard.c deleted file mode 100644 index b84a591bbb..0000000000 --- a/addressbook/gui/widgets/test-minicard.c +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* test-minicard.c - * - * Copyright (C) 2000 Ximian, Inc. - * Author: Chris Lahey <clahey@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 <gtk/gtkmain.h> -#include <libgnomeui/gnome-app.h> -#include <libgnomeui/gnome-init.h> -#include <libgnomeui/gnome-canvas-rect-ellipse.h> - -#include "e-minicard.h" - -/* This is a horrible thing to do, but it is just a test. */ -GnomeCanvasItem *card; -GnomeCanvasItem *rect; - -static void destroy_callback(GtkWidget *app, gpointer data) -{ - exit(0); -} - -static void allocate_callback(GtkWidget *canvas, GtkAllocation *allocation, gpointer data) -{ - gnome_canvas_set_scroll_region(GNOME_CANVAS( canvas ), 0, 0, allocation->width, allocation->height ); - gnome_canvas_item_set( card, - "width", (double) allocation->width, - NULL ); - gnome_canvas_item_set( rect, - "x2", (double) allocation->width, - "y2", (double) allocation->height, - NULL ); -} - -#if 0 -static void about_callback( GtkWidget *widget, gpointer data ) -{ - - const gchar *authors[] = - { - "Christopher James Lahey <clahey@umich.edu>", - NULL - }; - - GtkWidget *about = - gnome_about_new ( _( "Minicard Test" ), VERSION, - _( "Copyright (C) 2000, Ximian, Inc." ), - authors, - _( "This should test the minicard canvas item" ), - NULL); - gtk_widget_show (about); -} -#endif - -int main( int argc, char *argv[] ) -{ - GtkWidget *app; - GtkWidget *canvas; - int i; - - /* bindtextdomain (PACKAGE, GNOMELOCALEDIR); - textdomain (PACKAGE);*/ - - gnome_init( "Minicard Test", VERSION, argc, argv); - app = gnome_app_new("Minicard Test", NULL); - - canvas = gnome_canvas_new(); - rect = gnome_canvas_item_new( gnome_canvas_root( GNOME_CANVAS( canvas ) ), - gnome_canvas_rect_get_type(), - "x1", (double) 0, - "y1", (double) 0, - "x2", (double) 100, - "y2", (double) 100, - "fill_color", "white", - NULL ); - for ( i = 0; i < 1; i++ ) - { - card = gnome_canvas_item_new( gnome_canvas_root( GNOME_CANVAS( canvas ) ), - e_minicard_get_type(), - "width", (double) 100, - NULL ); - } - gnome_canvas_set_scroll_region ( GNOME_CANVAS( canvas ), - 0, 0, - 100, 100 ); - - gnome_app_set_contents( GNOME_APP( app ), canvas ); - - /* Connect the signals */ - gtk_signal_connect( GTK_OBJECT( app ), "destroy", - GTK_SIGNAL_FUNC( destroy_callback ), - ( gpointer ) app ); - - gtk_signal_connect( GTK_OBJECT( canvas ), "size_allocate", - GTK_SIGNAL_FUNC( allocate_callback ), - ( gpointer ) app ); - - gtk_widget_show_all( app ); - - gtk_main(); - - /* Not reached. */ - return 0; -} diff --git a/addressbook/gui/widgets/test-reflow.c b/addressbook/gui/widgets/test-reflow.c deleted file mode 100644 index 14066c4cd0..0000000000 --- a/addressbook/gui/widgets/test-reflow.c +++ /dev/null @@ -1,201 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* test-reflow.c - * - * Copyright (C) 2000 Ximian, Inc. - * Author: Chris Lahey <clahey@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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. - */ - -#define TEST_VCARD \ -"BEGIN:VCARD -" \ -"FN:Nat -" \ -"N:Friedman;Nat;D;Mr. -" \ -"TITLE:Head Geek -" \ -"BDAY:1977-08-06 -" \ -"TEL;WORK:617 679 1984 -" \ -"TEL;CELL:123 456 7890 -" \ -"EMAIL;INTERNET:nat@nat.org -" \ -"EMAIL;INTERNET:nat@ximian.com -" \ -"ADR;WORK;POSTAL:P.O. Box 101;;;Any Town;CA;91921-1234; -" \ -"ADR;HOME;POSTAL;INTL:P.O. Box 202;;;Any Town 2;MI;12344-4321;USA -" \ -"END:VCARD -" \ -" -" - - -#include "config.h" - -#include <gtk/gtkmain.h> -#include <gtk/gtkvbox.h> -#include <libgnomeui/gnome-canvas-rect-ellipse.h> -#include <libgnomeui/gnome-init.h> -#include <gal/widgets/e-canvas.h> -#include <gal/widgets/e-reflow.h> -#include <gal/widgets/e-scroll-frame.h> - -#include "e-minicard.h" - -/* This is a horrible thing to do, but it is just a test. */ -GnomeCanvasItem *reflow; -GnomeCanvasItem *rect; -GtkAllocation last_alloc; - -static void destroy_callback(GtkWidget *app, gpointer data) -{ - exit(0); -} - -static void allocate_callback(GtkWidget *canvas, GtkAllocation *allocation, gpointer data) -{ - double width; - last_alloc = *allocation; - gnome_canvas_item_set( reflow, - "height", (double) allocation->height, - NULL ); - gnome_canvas_item_set( reflow, - "minimum_width", (double) allocation->width, - NULL ); - gtk_object_get(GTK_OBJECT(reflow), - "width", &width, - NULL); - width = MAX(width, allocation->width); - gnome_canvas_set_scroll_region(GNOME_CANVAS( canvas ), 0, 0, width - 1, allocation->height - 1); - gnome_canvas_item_set( rect, - "x2", (double) width, - "y2", (double) allocation->height, - NULL ); -} - -static void resize(GnomeCanvas *canvas, gpointer data) -{ - double width; - gtk_object_get(GTK_OBJECT(reflow), - "width", &width, - NULL); - width = MAX(width, last_alloc.width); - gnome_canvas_set_scroll_region(canvas , 0, 0, width - 1, last_alloc.height - 1); - gnome_canvas_item_set( rect, - "x2", (double) width, - "y2", (double) last_alloc.height, - NULL ); -} - -#if 0 -static void about_callback( GtkWidget *widget, gpointer data ) -{ - - const gchar *authors[] = - { - "Christopher James Lahey <clahey@umich.edu>", - NULL - }; - - GtkWidget *about = - gnome_about_new ( _( "Reflow Test" ), VERSION, - _( "Copyright (C) 2000, Ximian, Inc." ), - authors, - _( "This should test the reflow canvas item" ), - NULL); - gtk_widget_show (about); -} -#endif - -int main( int argc, char *argv[] ) -{ - GtkWidget *app; - GtkWidget *canvas; - GtkWidget *vbox; - GtkWidget *scrollframe; - int i; - - /* bindtextdomain (PACKAGE, GNOMELOCALEDIR); - textdomain (PACKAGE);*/ - - gnome_init( "Reflow Test", VERSION, argc, argv); - app = gnome_app_new("Reflow Test", NULL); - - vbox = gtk_vbox_new(FALSE, 0); - - canvas = e_canvas_new(); - rect = gnome_canvas_item_new( gnome_canvas_root( GNOME_CANVAS( canvas ) ), - gnome_canvas_rect_get_type(), - "x1", (double) 0, - "y1", (double) 0, - "x2", (double) 100, - "y2", (double) 100, - "fill_color", "white", - NULL ); - reflow = gnome_canvas_item_new( gnome_canvas_root( GNOME_CANVAS( canvas ) ), - e_reflow_get_type(), - "height", (double) 100, - "minimum_width", (double) 100, - NULL ); - gtk_signal_connect( GTK_OBJECT( canvas ), "reflow", - GTK_SIGNAL_FUNC( resize ), - ( gpointer ) app); - for ( i = 0; i < 200; i++ ) - { - GnomeCanvasItem *item; - ECard *card = e_card_new (TEST_VCARD); - item = gnome_canvas_item_new( GNOME_CANVAS_GROUP(reflow), - e_minicard_get_type(), - "card", card, - NULL); - e_reflow_add_item(E_REFLOW(reflow), item, NULL); - } - gnome_canvas_set_scroll_region ( GNOME_CANVAS( canvas ), - 0, 0, - 100, 100 ); - - scrollframe = e_scroll_frame_new (gtk_layout_get_hadjustment(GTK_LAYOUT(canvas)), - gtk_layout_get_vadjustment(GTK_LAYOUT(canvas))); - e_scroll_frame_set_policy (E_SCROLL_FRAME (scrollframe), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_NEVER); - - gtk_container_add (GTK_CONTAINER (scrollframe), canvas); - - gnome_app_set_contents( GNOME_APP( app ), scrollframe ); - - /* Connect the signals */ - gtk_signal_connect( GTK_OBJECT( app ), "destroy", - GTK_SIGNAL_FUNC( destroy_callback ), - ( gpointer ) app ); - - gtk_signal_connect( GTK_OBJECT( canvas ), "size_allocate", - GTK_SIGNAL_FUNC( allocate_callback ), - ( gpointer ) app ); - - gtk_widget_show_all( app ); - gdk_window_set_back_pixmap( GTK_LAYOUT(canvas)->bin_window, NULL, FALSE); - - gtk_main(); - - /* Not reached. */ - return 0; -} |