[Xfce4-commits] <xfce4-notifyd:master> Port xfce4-notifyd to libxfce4ui and GtkBuilder
Brian J. Tarricone
noreply at xfce.org
Mon Apr 12 02:54:01 CEST 2010
Updating branch refs/heads/master
to f1169d86075b1ce972b173ed999ca6bcdad3f97f (commit)
from 5b9e6a3f628b1f534eb3c56e97a3949fab931f23 (commit)
commit f1169d86075b1ce972b173ed999ca6bcdad3f97f
Author: Romain Bouvier <skunnyk at archlinux.fr>
Date: Sun Apr 11 17:30:08 2010 +0200
Port xfce4-notifyd to libxfce4ui and GtkBuilder
Makefile.am | 18 ++--
configure.ac.in | 5 +-
xfce4-notifyd-config/main.c | 41 ++++----
xfce4-notifyd-config/xfce4-notifyd-config.glade | 136 ++++++++++++++---------
xfce4-notifyd/main.c | 2 +-
xfce4-notifyd/xfce-notify-daemon.c | 9 +-
xfce4-notifyd/xfce-notify-window.c | 17 +++-
7 files changed, 137 insertions(+), 91 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 7310806..c396e21 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -30,13 +30,13 @@ xfce4_notifyd_xfce4_notifyd_SOURCES = \
xfce4_notifyd_config_xfce4_notifyd_config_SOURCES = \
xfce4-notifyd-config/main.c \
- xfce4-notifyd-config/xfce4-notifyd-config.glade.h
+ xfce4-notifyd-config/xfce4-notifyd-config.ui.h
common_cflags = \
-DLOCALEDIR=\"$(localedir)\" \
$(GTK_CFLAGS) \
$(LIBXFCE4UTIL_CFLAGS) \
- $(LIBXFCEGUI4_CFLAGS) \
+ $(LIBXFCE4UI_CFLAGS) \
$(DBUS_GLIB_CFLAGS) \
$(XFCONF_CFLAGS)
@@ -47,13 +47,12 @@ xfce4_notifyd_xfce4_notifyd_CFLAGS = \
xfce4_notifyd_config_xfce4_notifyd_config_CFLAGS = \
-DG_LOG_DOMAIN=\"xfce4-notifyd-config\" \
- $(common_cflags) \
- $(LIBGLADE_CFLAGS)
+ $(common_cflags)
common_ldadd = \
$(GTK_LIBS) \
$(LIBXFCE4UTIL_LIBS) \
- $(LIBXFCEGUI4_LIBS) \
+ $(LIBXFCE4UI_LIBS) \
$(DBUS_GLIB_LIBS) \
$(XFCONF_LIBS)
@@ -62,8 +61,7 @@ xfce4_notifyd_xfce4_notifyd_LDADD = \
$(LIBSEXY_LIBS)
xfce4_notifyd_config_xfce4_notifyd_config_LDADD = \
- $(common_ldadd) \
- $(LIBGLADE_LIBS)
+ $(common_ldadd)
servicedir = $(datadir)/dbus-1/services
@@ -116,7 +114,7 @@ built_xfce4_notifyd += \
xfce4-notifyd/xfce-notify-enum-types.h
built_xfce4_notifyd_config = \
- xfce4-notifyd-config/xfce4-notifyd-config.glade.h
+ xfce4-notifyd-config/xfce4-notifyd-config.ui.h
clean_xfce4_notifyd += \
xfce4-notifyd/stamp-xfce-notify-enum-types.h \
@@ -201,8 +199,8 @@ xfce4-notifyd/xfce-notify-enum-types.c: xfce4-notifyd/xfce-notify-window.h Makef
&& cp xfce4-notifyd/xgen-xnetc xfce4-notifyd/xfce-notify-enum-types.c \
&& rm -f xfce4-notifyd/xgen-xnetc
-xfce4-notifyd-config/xfce4-notifyd-config.glade.h: $(srcdir)/xfce4-notifyd-config/xfce4-notifyd-config.glade
- $(EXO_CSOURCE) --static --name=xfce4_notifyd_config_glade $< >$@
+xfce4-notifyd-config/xfce4-notifyd-config.ui.h: $(srcdir)/xfce4-notifyd-config/xfce4-notifyd-config.glade
+ $(EXO_CSOURCE) --static --name=xfce4_notifyd_config_ui $< >$@
endif
diff --git a/configure.ac.in b/configure.ac.in
index 6058490..0306eec 100644
--- a/configure.ac.in
+++ b/configure.ac.in
@@ -49,12 +49,11 @@ XDT_I18N([@LINGUAS@])
dnl required
XDT_CHECK_PACKAGE([LIBXFCE4UTIL], [libxfce4util-1.0], [4.4.0])
-XDT_CHECK_PACKAGE([LIBXFCEGUI4], [libxfcegui4-1.0], [4.5.2svn-r26504])
+XDT_CHECK_PACKAGE([LIBXFCE4UI], [libxfce4ui-1], [4.7.0])
XDT_CHECK_PACKAGE([XFCONF], [libxfconf-0], [0.1.0svn-r26876])
-XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.10.0])
+XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.14.0])
XDT_CHECK_PACKAGE([DBUS], [dbus-1], [1.0.0])
XDT_CHECK_PACKAGE([DBUS_GLIB], [dbus-glib-1], [0.72])
-XDT_CHECK_PACKAGE([LIBGLADE], [libglade-2.0], [2.6.0])
XDT_CHECK_OPTIONAL_PACKAGE([LIBSEXY], [libsexy], [0.1.6], [libsexy],
[libsexy support (for clickable URLs) (default=yes)],
diff --git a/xfce4-notifyd-config/main.c b/xfce4-notifyd-config/main.c
index 2977b73..753ff1b 100644
--- a/xfce4-notifyd-config/main.c
+++ b/xfce4-notifyd-config/main.c
@@ -30,14 +30,13 @@
#endif
#include <gtk/gtk.h>
-#include <glade/glade.h>
#include <dbus/dbus-glib.h>
#include <xfconf/xfconf.h>
-#include <libxfcegui4/libxfcegui4.h>
+#include <libxfce4ui/libxfce4ui.h>
-#include "xfce4-notifyd-config.glade.h"
+#include "xfce4-notifyd-config.ui.h"
/* unfortunately, currently we have to kill the daemon to
* change themes. this is only annoying because existing notifications
@@ -209,7 +208,7 @@ xfce4_notifyd_config_setup_treeview(GtkWidget *treeview,
}
static GtkWidget *
-xfce4_notifyd_config_setup_dialog(GladeXML *gxml)
+xfce4_notifyd_config_setup_dialog(GtkBuilder *builder)
{
XfconfChannel *channel;
GtkWidget *dlg, *btn, *sbtn, *slider, *chk, *treeview, *combo;
@@ -218,11 +217,11 @@ xfce4_notifyd_config_setup_dialog(GladeXML *gxml)
GError *error = NULL;
gchar *current_theme;
- glade_xml_signal_autoconnect(gxml);
+ gtk_builder_connect_signals(builder, NULL);
- dlg = glade_xml_get_widget(gxml, "notifyd_settings_dlg");
+ dlg = GTK_WIDGET(gtk_builder_get_object(builder, "notifyd_settings_dlg"));
+ btn = GTK_WIDGET(gtk_builder_get_object(builder, "close_btn"));
- btn = glade_xml_get_widget(gxml, "close_btn");
g_signal_connect_swapped(G_OBJECT(btn), "clicked",
G_CALLBACK(gtk_dialog_response), dlg);
@@ -238,22 +237,22 @@ xfce4_notifyd_config_setup_dialog(GladeXML *gxml)
channel = xfconf_channel_new("xfce4-notifyd");
- sbtn = glade_xml_get_widget(gxml, "expire_timeout_sbtn");
+ sbtn = GTK_WIDGET(gtk_builder_get_object(builder, "expire_timeout_sbtn"));
xfconf_g_property_bind(channel, "/expire-timeout", G_TYPE_INT,
G_OBJECT(sbtn), "value");
- slider = glade_xml_get_widget(gxml, "opacity_slider");
+ slider = GTK_WIDGET(gtk_builder_get_object(builder, "opacity_slider"));
g_signal_connect(G_OBJECT(slider), "format-value",
G_CALLBACK(xfce4_notifyd_slider_format_value), NULL);
adj = gtk_range_get_adjustment(GTK_RANGE(slider));
xfconf_g_property_bind(channel, "/initial-opacity", G_TYPE_DOUBLE,
G_OBJECT(adj), "value");
- chk = glade_xml_get_widget(gxml, "fade_transparency_chk");
+ chk = GTK_WIDGET(gtk_builder_get_object(builder, "fade_transparency_chk"));
xfconf_g_property_bind(channel, "/fade-transparency", G_TYPE_BOOLEAN,
G_OBJECT(chk), "active");
- treeview = glade_xml_get_widget(gxml, "themes_treeview");
+ treeview = GTK_WIDGET(gtk_builder_get_object(builder, "themes_treeview"));
current_theme = xfconf_channel_get_string(channel, "/theme", "Default");
xfce4_notifyd_config_setup_treeview(treeview, current_theme);
g_free(current_theme);
@@ -266,7 +265,7 @@ xfce4_notifyd_config_setup_dialog(GladeXML *gxml)
G_CALLBACK(xfce4_notifyd_config_theme_changed),
treeview);
- combo = glade_xml_get_widget(gxml, "position_combo");
+ combo = GTK_WIDGET(gtk_builder_get_object(builder, "position_combo"));
xfconf_g_property_bind(channel, "/notify-location", G_TYPE_UINT,
G_OBJECT(combo), "active");
if(gtk_combo_box_get_active(GTK_COMBO_BOX(combo)) == -1)
@@ -280,7 +279,7 @@ main(int argc,
char **argv)
{
GtkWidget *settings_dialog = NULL;
- GladeXML *gxml;
+ GtkBuilder *builder;
gboolean opt_version = FALSE;
GdkNativeWindow opt_socket_id = 0;
GOptionEntry option_entries[] = {
@@ -313,15 +312,15 @@ main(int argc,
return EXIT_SUCCESS;
}
- gxml = glade_xml_new_from_buffer(xfce4_notifyd_config_glade,
- xfce4_notifyd_config_glade_length,
- NULL, NULL);
- if(G_UNLIKELY(!gxml)) {
+ builder = gtk_builder_new();
+ gtk_builder_add_from_string(builder, xfce4_notifyd_config_ui, xfce4_notifyd_config_ui_length, NULL);
+ if(G_UNLIKELY(!builder)) {
g_error("Unable to read embedded UI definition file");
return EXIT_FAILURE;
}
- settings_dialog = xfce4_notifyd_config_setup_dialog(gxml);
+ settings_dialog = xfce4_notifyd_config_setup_dialog(builder);
+
if(opt_socket_id) {
GtkWidget *plug, *plug_child;
@@ -331,17 +330,17 @@ main(int argc,
g_signal_connect(G_OBJECT(plug), "delete-event",
G_CALLBACK(gtk_main_quit), NULL);
- plug_child = glade_xml_get_widget(gxml, "plug-child");
+ plug_child = GTK_WIDGET(gtk_builder_get_object(builder, "plug-child"));
gtk_widget_reparent(plug_child, plug);
gtk_widget_show(plug_child);
gdk_notify_startup_complete();
- g_object_unref(G_OBJECT(gxml));
+ g_object_unref(G_OBJECT(builder));
gtk_widget_destroy(settings_dialog);
gtk_main();
} else {
- g_object_unref(G_OBJECT(gxml));
+ g_object_unref(G_OBJECT(builder));
gtk_dialog_run(GTK_DIALOG(settings_dialog));
}
diff --git a/xfce4-notifyd-config/xfce4-notifyd-config.glade b/xfce4-notifyd-config/xfce4-notifyd-config.glade
index 57ef321..2d30655 100644
--- a/xfce4-notifyd-config/xfce4-notifyd-config.glade
+++ b/xfce4-notifyd-config/xfce4-notifyd-config.glade
@@ -1,9 +1,42 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<?xml version="1.0"?>
<!--Generated with glade3 3.4.5 on Mon Nov 24 01:01:23 2008 -->
-<glade-interface>
- <requires lib="xfce4"/>
- <widget class="XfceTitledDialog" id="notifyd_settings_dlg">
+<interface>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">480</property>
+ <property name="lower">1</property>
+ <property name="page_increment">10</property>
+ <property name="step_increment">1</property>
+ <property name="page_size">0</property>
+ <property name="value">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment2">
+ <property name="upper">1.01</property>
+ <property name="lower">0</property>
+ <property name="page_increment">0.10000000000000001</property>
+ <property name="step_increment">0.01</property>
+ <property name="page_size">0.01</property>
+ <property name="value">0.90000000000000002</property>
+ </object>
+ <object class="GtkListStore" id="model1">
+ <columns>
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Top left</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Bottom left</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Top right</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Bottom right</col>
+ </row>
+ </data>
+ </object>
+ <object class="XfceTitledDialog" id="notifyd_settings_dlg">
<property name="title" translatable="yes">Notifications</property>
<property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
<property name="icon_name">xfce4-notifyd</property>
@@ -11,95 +44,98 @@
<property name="has_separator">False</property>
<property name="subtitle" translatable="yes">Customize how notifications appear on your screen</property>
<child internal-child="vbox">
- <widget class="GtkVBox" id="dialog-vbox1">
+ <object class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="spacing">2</property>
<child>
- <widget class="GtkHBox" id="plug-child">
+ <object class="GtkHBox" id="plug-child">
<property name="visible">True</property>
<property name="border_width">6</property>
<property name="spacing">12</property>
<child>
- <widget class="GtkScrolledWindow" id="scrolledwindow1">
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<child>
- <widget class="GtkTreeView" id="themes_treeview">
+ <object class="GtkTreeView" id="themes_treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
- <widget class="GtkVBox" id="vbox1">
+ <object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
- <widget class="GtkHBox" id="hbox4">
+ <object class="GtkHBox" id="hbox4">
<property name="visible">True</property>
<property name="spacing">12</property>
<child>
- <widget class="GtkLabel" id="label3">
+ <object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="label" translatable="yes">Default _position:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">position_combo</property>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
- <widget class="GtkComboBox" id="position_combo">
+ <object class="GtkComboBox" id="position_combo">
<property name="visible">True</property>
- <property name="items" translatable="yes">Top left
-Bottom left
-Top right
-Bottom right</property>
- </widget>
+ <property name="model">model1</property>
+ <child>
+ <object class="GtkCellRendererText" id="renderer1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
- <widget class="GtkHBox" id="hbox2">
+ <object class="GtkHBox" id="hbox2">
<property name="visible">True</property>
<property name="spacing">12</property>
<child>
- <widget class="GtkLabel" id="label1">
+ <object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">_Disappear after:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">expire_timeout_sbtn</property>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
- <widget class="GtkSpinButton" id="expire_timeout_sbtn">
+ <object class="GtkSpinButton" id="expire_timeout_sbtn">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="adjustment">10 1 480 1 10 0</property>
+ <property name="adjustment">adjustment1</property>
<property name="numeric">True</property>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
@@ -107,17 +143,17 @@ Bottom right</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label4">
+ <object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="label" translatable="yes">seconds</property>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
@@ -125,34 +161,34 @@ Bottom right</property>
</packing>
</child>
<child>
- <widget class="GtkHBox" id="hbox3">
+ <object class="GtkHBox" id="hbox3">
<property name="visible">True</property>
<property name="spacing">12</property>
<child>
- <widget class="GtkLabel" id="label2">
+ <object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="label" translatable="yes">_Opacity:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">opacity_slider</property>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
- <widget class="GtkHScale" id="opacity_slider">
+ <object class="GtkHScale" id="opacity_slider">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="adjustment">0.90000000000000002 0 1.01 0.01 0.10000000000000001 0.01</property>
+ <property name="adjustment">adjustment2</property>
<property name="digits">2</property>
<property name="value_pos">GTK_POS_RIGHT</property>
- </widget>
+ </object>
<packing>
<property name="position">1</property>
</packing>
</child>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
@@ -160,52 +196,50 @@ Bottom right</property>
</packing>
</child>
<child>
- <widget class="GtkCheckButton" id="fade_transparency_chk">
+ <object class="GtkCheckButton" id="fade_transparency_chk">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">_Fade to transparent</property>
<property name="use_underline">True</property>
- <property name="response_id">0</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
- </widget>
+ </object>
<packing>
<property name="position">1</property>
</packing>
</child>
- </widget>
+ </object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
- <widget class="GtkHButtonBox" id="dialog-action_area1">
+ <object class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
- <widget class="GtkButton" id="close_btn">
+ <object class="GtkButton" id="close_btn">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label">gtk-close</property>
<property name="use_stock">True</property>
- <property name="response_id">-1</property>
- </widget>
+ </object>
</child>
- </widget>
+ </object>
<packing>
<property name="expand">False</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
- </widget>
+ </object>
</child>
- </widget>
-</glade-interface>
+ </object>
+</interface>
diff --git a/xfce4-notifyd/main.c b/xfce4-notifyd/main.c
index 4a49518..a755b10 100644
--- a/xfce4-notifyd/main.c
+++ b/xfce4-notifyd/main.c
@@ -29,7 +29,7 @@
#include <xfconf/xfconf.h>
#include <libxfce4util/libxfce4util.h>
-#include <libxfcegui4/libxfcegui4.h>
+#include <libxfce4ui/libxfce4ui.h>
#include "xfce-notify-daemon.h"
diff --git a/xfce4-notifyd/xfce-notify-daemon.c b/xfce4-notifyd/xfce-notify-daemon.c
index 47970b5..6f5d69e 100644
--- a/xfce4-notifyd/xfce-notify-daemon.c
+++ b/xfce4-notifyd/xfce-notify-daemon.c
@@ -30,7 +30,7 @@
#endif
#include <libxfce4util/libxfce4util.h>
-#include <libxfcegui4/libxfcegui4.h>
+#include <libxfce4ui/libxfce4ui.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
@@ -800,7 +800,12 @@ notify_notify(XfceNotifyDaemon *xndaemon,
xfce_rc_set_group(rcfile, "Desktop Entry");
icon_file = xfce_rc_read_entry(rcfile, "Icon", NULL);
if(icon_file) {
- pix = xfce_themed_icon_load(icon_file, 32);
+ pix = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
+ icon_file,
+ 32,
+ GTK_ICON_LOOKUP_FORCE_SIZE,
+ NULL);
+
if(pix) {
xfce_notify_window_set_icon_pixbuf(window, pix);
g_object_unref(G_OBJECT(pix));
diff --git a/xfce4-notifyd/xfce-notify-window.c b/xfce4-notifyd/xfce-notify-window.c
index f25b1d3..d33d3b9 100644
--- a/xfce4-notifyd/xfce-notify-window.c
+++ b/xfce4-notifyd/xfce-notify-window.c
@@ -28,7 +28,7 @@
#include <math.h>
-#include <libxfcegui4/libxfcegui4.h>
+#include <libxfce4ui/libxfce4ui.h>
#ifdef HAVE_LIBSEXY
#include <libsexy/sexy.h>
@@ -748,7 +748,13 @@ xfce_notify_window_url_clicked(SexyUrlLabel *label,
if(opener) {
url_quoted = g_shell_quote(url);
cmd = g_strdup_printf("%s %s", opener, url_quoted);
- xfce_exec(cmd, FALSE, FALSE, NULL);
+ GError *error = NULL;
+ if(!g_spawn_command_line_async("cmd", &error)) {
+ xfce_dialog_show_error(NULL,
+ error,
+ _("%s could not be launched"), url);
+ g_error_free(error);
+ }
g_free(url_quoted);
g_free(cmd);
g_free(opener);
@@ -1085,7 +1091,12 @@ xfce_notify_window_set_icon_name(XfceNotifyWindow *window,
GdkPixbuf *pix;
gtk_icon_size_lookup(GTK_ICON_SIZE_DIALOG, &w, &h);
- pix = xfce_themed_icon_load(icon_name, w);
+ pix = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
+ icon_name,
+ w,
+ GTK_ICON_LOOKUP_FORCE_SIZE,
+ NULL);
+
if(pix) {
gtk_image_set_from_pixbuf(GTK_IMAGE(window->icon), pix);
gtk_widget_show(window->icon_box);
More information about the Xfce4-commits
mailing list