[QGIS Commit] r10380 - in trunk/qgis/src: app plugins ui
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Sat Mar 21 16:26:46 EDT 2009
Author: timlinux
Date: 2009-03-21 16:26:46 -0400 (Sat, 21 Mar 2009)
New Revision: 10380
Modified:
trunk/qgis/src/app/qgsserversourceselect.cpp
trunk/qgis/src/app/qgsserversourceselect.h
trunk/qgis/src/plugins/CMakeLists.txt
trunk/qgis/src/ui/qgsserversourceselectbase.ui
Log:
Added open WMS search interface from Mathias Walker
Mathias Walker <mwa at sourcepole.ch>, Sourcepole AG
Modified: trunk/qgis/src/app/qgsserversourceselect.cpp
===================================================================
--- trunk/qgis/src/app/qgsserversourceselect.cpp 2009-03-21 20:03:24 UTC (rev 10379)
+++ trunk/qgis/src/app/qgsserversourceselect.cpp 2009-03-21 20:26:46 UTC (rev 10380)
@@ -2,8 +2,11 @@
qgserversourceselect.cpp - selector for WMS servers, etc.
-------------------
begin : 3 April 2005
- copyright : (C) 2005 by Brendan Morley
- email : morb at ozemail dot com dot au
+ copyright :
+ original : (C) 2005 by Brendan Morley email : morb at ozemail dot com dot au
+ wms search : (C) 2009 Mathias Walker <mwa at sourcepole.ch>, Sourcepole AG
+
+
***************************************************************************/
/***************************************************************************
@@ -16,29 +19,31 @@
***************************************************************************/
/* $Id$ */
-#include "qgsserversourceselect.h"
-
+#include "../providers/wms/qgswmsprovider.h"
+#include "qgis.h" // GEO_EPSG_CRS_ID
+#include "qgscontexthelp.h"
+#include "qgscoordinatereferencesystem.h"
#include "qgsgenericprojectionselector.h"
-
+#include "qgshttptransaction.h"
+#include "qgslogger.h"
+#include "qgsmessageviewer.h"
#include "qgsnewhttpconnection.h"
#include "qgsnumericsortlistviewitem.h"
+#include "qgsproject.h"
#include "qgsproviderregistry.h"
-#include "qgscoordinatereferencesystem.h"
-#include "../providers/wms/qgswmsprovider.h"
-#include "qgscontexthelp.h"
+#include "qgsserversourceselect.h"
+#include <qgisinterface.h>
-#include "qgsproject.h"
-#include "qgsmessageviewer.h"
-
+#include <QButtonGroup>
+#include <QDomDocument>
+#include <QHeaderView>
+#include <QImageReader>
+#include <QMap>
#include <QMessageBox>
#include <QPicture>
#include <QSettings>
-#include <QButtonGroup>
-#include <QMap>
-#include <QImageReader>
-#include "qgslogger.h"
-#include "qgis.h" // GEO_EPSG_CRS_ID
+#include <QUrl>
@@ -108,6 +113,17 @@
// set up the default WMS Coordinate Reference System
labelCoordRefSys->setText( descriptionForEpsg( m_Epsg ) );
+
+
+ //
+ // For wms search tab
+ //
+ tableWidgetWMSList->setColumnWidth(0, 250);
+ tableWidgetWMSList->setColumnWidth(1, 150);
+ tableWidgetWMSList->setColumnWidth(2, 250);
+ tableWidgetWMSList->verticalHeader()->hide();
+
+ connect(tableWidgetWMSList, SIGNAL(itemSelectionChanged()), this, SLOT(wmsSelectionChanged()));
}
QgsServerSourceSelect::~QgsServerSourceSelect()
@@ -718,4 +734,166 @@
"need to set the proxy settings in the QGIS options dialog." ) + "</p>" );
}
+bool QgsServerSourceSelect::retrieveSearchResults(const QString& searchTerm, QByteArray& httpResponse)
+{
+ // TODO: test proxy
+ // read proxy settings: code from QgsWmsProvider::retrieveUrl()
+ QSettings settings;
+ QString proxyHost, proxyUser, proxyPassword;
+ int proxyPort;
+ QNetworkProxy::ProxyType proxyType = QNetworkProxy::NoProxy;
+
+ bool proxyEnabled = settings.value( "proxy/proxyEnabled", "0" ).toBool();
+ if(proxyEnabled)
+ {
+ proxyHost = settings.value( "proxy/proxyHost", "" ).toString();
+ proxyPort = settings.value( "proxy/proxyPort", "" ).toString().toInt();
+ proxyUser = settings.value( "proxy/proxyUser", "" ).toString();
+ proxyPassword = settings.value( "proxy/proxyPassword", "" ).toString();
+ QString proxyTypeString = settings.value( "proxy/proxyType", "" ).toString();
+ if(proxyTypeString == "DefaultProxy")
+ {
+ proxyType = QNetworkProxy::DefaultProxy;
+ }
+ else if(proxyTypeString == "Socks5Proxy")
+ {
+ proxyType = QNetworkProxy::Socks5Proxy;
+ }
+ else if(proxyTypeString == "HttpProxy")
+ {
+ proxyType = QNetworkProxy::HttpProxy;
+ }
+#if QT_VERSION >= 0x040400
+ else if(proxyTypeString == "HttpCachingProxy")
+ {
+ proxyType = QNetworkProxy::HttpCachingProxy;
+ }
+ else if(proxyTypeString == "FtpCachingProxy")
+ {
+ proxyType = QNetworkProxy::FtpCachingProxy;
+ }
+#endif
+ }
+
+ QUrl url(QString("http://geopole.org/wms/search?search=%1&type=rss").arg(searchTerm));
+ QgsHttpTransaction http(url.toEncoded(),
+ proxyHost, proxyPort, proxyUser, proxyPassword, proxyType );
+
+ bool httpOk = http.getSynchronously( httpResponse );
+ if ( !httpOk )
+ {
+ // TODO: error handling
+ return false;
+ }
+
+ // TODO: check doctype?
+
+ return true;
+}
+
+void QgsServerSourceSelect::addWMSListRow(const QDomElement& item, int row)
+{
+ QDomElement title = item.firstChildElement("title");
+ addWMSListItem(title, row, 0);
+ QDomElement link = item.firstChildElement("link");
+ addWMSListItem(link, row, 1);
+ QDomElement description = item.firstChildElement("description");
+ addWMSListItem(description, row, 2);
+}
+
+void QgsServerSourceSelect::addWMSListItem(const QDomElement& el, int row, int column)
+{
+ if (!el.isNull())
+ {
+ QTableWidgetItem* tableItem = new QTableWidgetItem(el.text());
+ // TODO: add linebreaks to long tooltips?
+ tableItem->setToolTip(el.text());
+ tableWidgetWMSList->setItem(row, column, tableItem);
+ }
+}
+
+void QgsServerSourceSelect::on_btnClose_clicked()
+{
+ accept();
+}
+
+void QgsServerSourceSelect::on_btnSearch_clicked()
+{
+ // clear results
+ tableWidgetWMSList->clearContents();
+ tableWidgetWMSList->setRowCount(0);
+
+ // disable Add WMS button
+ btnAddWMS->setEnabled(false);
+
+ // retrieve search results
+ QByteArray httpResponse;
+ bool success = retrieveSearchResults(leSearchTerm->text(), httpResponse);
+ if (!success)
+ {
+ // TODO: error handling
+ return;
+ }
+
+ // parse results
+ QDomDocument doc("RSS");
+ if (!doc.setContent(httpResponse))
+ {
+ // TODO: error handling
+ return;
+ }
+
+ QDomNodeList list = doc.elementsByTagName("item");
+ tableWidgetWMSList->setRowCount(list.size());
+ for (int i=0;i<list.size();i++)
+ {
+ if (list.item(i).isElement())
+ {
+ QDomElement item = list.item(i).toElement();
+ addWMSListRow(item, i);
+ }
+ }
+}
+
+void QgsServerSourceSelect::on_btnAddWMS_clicked()
+{
+ // TODO: deactivate button if dialog is open?
+ // TODO: remove from config on close?
+
+ int selectedRow = tableWidgetWMSList->currentRow();
+ if (selectedRow == -1)
+ {
+ return;
+ }
+
+ QString wmsTitle = tableWidgetWMSList->item(selectedRow, 0)->text();
+ QString wmsUrl = tableWidgetWMSList->item(selectedRow, 1)->text();
+
+ QSettings settings;
+ if (settings.contains(QString("Qgis/connections-wms/%1/url").arg(wmsTitle)))
+ {
+ QString msg = tr("The %1 connection already exists. Do you want to overwrite it?").arg(wmsTitle);
+ QMessageBox::StandardButton result = QMessageBox::information( this, tr( "Confirm Overwrite" ), msg, QMessageBox::Ok | QMessageBox::Cancel );
+ if ( result != QMessageBox::Ok )
+ {
+ return;
+ }
+ }
+
+ // add selected WMS to config and mark as current
+ settings.setValue(QString("Qgis/connections-wms/%1/url").arg(wmsTitle), wmsUrl);
+ settings.setValue( "/Qgis/connections-wms/selected", wmsTitle);
+ populateConnectionList();
+ tabWidget->setCurrentIndex( 0 );
+}
+
+void QgsServerSourceSelect::wmsSelectionChanged()
+{
+ btnAddWMS->setEnabled(tableWidgetWMSList->currentRow() != -1);
+}
+
+
+
+//
+//
// ENDS
Modified: trunk/qgis/src/app/qgsserversourceselect.h
===================================================================
--- trunk/qgis/src/app/qgsserversourceselect.h 2009-03-21 20:03:24 UTC (rev 10379)
+++ trunk/qgis/src/app/qgsserversourceselect.h 2009-03-21 20:26:46 UTC (rev 10380)
@@ -2,8 +2,8 @@
qgserversourceselect.h - selector for WMS servers, etc.
-------------------
begin : 3 April 2005
- copyright : (C) 2005 by Brendan Morley
- email : morb at ozemail dot com dot au
+ original : (C) 2005 by Brendan Morley email : morb at ozemail dot com dot au
+ wms search : (C) 2009 Mathias Walker <mwa at sourcepole.ch>, Sourcepole AG
***************************************************************************/
/***************************************************************************
@@ -27,6 +27,8 @@
class QgsWmsProvider;
class QButtonGroup;
class QgsNumericSortTreeWidgetItem;
+class QDomDocument;
+class QDomElement;
/*!
* \brief Dialog to create connections and add layers from WMS, etc.
@@ -180,7 +182,18 @@
//! The WMS provider that retrieves information for this dialog
QgsWmsProvider * mWmsProvider;
+
+ bool retrieveSearchResults(const QString& searchTerm, QByteArray& httpResponse);
+ void addWMSListRow(const QDomElement& item, int row);
+ void addWMSListItem(const QDomElement& el, int row, int column);
+
static const int context_id = 710979116;
+
+ private slots:
+ void on_btnClose_clicked();
+ void on_btnSearch_clicked();
+ void on_btnAddWMS_clicked();
+ void wmsSelectionChanged();
};
Modified: trunk/qgis/src/plugins/CMakeLists.txt
===================================================================
--- trunk/qgis/src/plugins/CMakeLists.txt 2009-03-21 20:03:24 UTC (rev 10379)
+++ trunk/qgis/src/plugins/CMakeLists.txt 2009-03-21 20:26:46 UTC (rev 10380)
@@ -1,4 +1,9 @@
-SUBDIRS (copyright_label delimited_text interpolation north_arrow scale_bar)
+SUBDIRS (copyright_label
+ delimited_text
+ interpolation
+ north_arrow
+ scale_bar
+ )
IF (POSTGRES_FOUND)
SUBDIRS (spit)
Modified: trunk/qgis/src/ui/qgsserversourceselectbase.ui
===================================================================
--- trunk/qgis/src/ui/qgsserversourceselectbase.ui 2009-03-21 20:03:24 UTC (rev 10379)
+++ trunk/qgis/src/ui/qgsserversourceselectbase.ui 2009-03-21 20:26:46 UTC (rev 10380)
@@ -6,7 +6,7 @@
<x>0</x>
<y>0</y>
<width>600</width>
- <height>505</height>
+ <height>481</height>
</rect>
</property>
<property name="windowTitle" >
@@ -22,108 +22,205 @@
<bool>true</bool>
</property>
<layout class="QGridLayout" >
- <property name="margin" >
- <number>9</number>
- </property>
- <property name="spacing" >
- <number>6</number>
- </property>
<item row="0" column="0" colspan="4" >
- <widget class="QGroupBox" name="GroupBox1" >
+ <widget class="QTabWidget" name="tabWidget" >
+ <property name="currentIndex" >
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab" >
+ <attribute name="title" >
+ <string>Servers</string>
+ </attribute>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" colspan="6" >
+ <widget class="QComboBox" name="cmbConnections" />
+ </item>
+ <item row="1" column="0" >
+ <widget class="QPushButton" name="btnConnect" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>C&onnect</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QPushButton" name="btnNew" >
+ <property name="text" >
+ <string>&New</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" >
+ <widget class="QPushButton" name="btnEdit" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Edit</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3" >
+ <widget class="QPushButton" name="btnDelete" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Delete</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="4" >
+ <widget class="QPushButton" name="btnAddDefault" >
+ <property name="statusTip" >
+ <string>Adds a few example WMS servers</string>
+ </property>
+ <property name="whatsThis" >
+ <string comment="Adds several example WMS servers to the list" />
+ </property>
+ <property name="text" >
+ <string>Add default servers</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="5" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>131</width>
+ <height>30</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="0" colspan="6" >
+ <widget class="QTreeWidget" name="lstLayers" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="selectionMode" >
+ <enum>QAbstractItemView::MultiSelection</enum>
+ </property>
+ <property name="allColumnsShowFocus" >
+ <bool>true</bool>
+ </property>
+ <column>
+ <property name="text" >
+ <string>ID</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Name</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Title</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Abstract</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_2" >
+ <attribute name="title" >
+ <string>Server Search</string>
+ </attribute>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLineEdit" name="leSearchTerm" />
+ </item>
+ <item row="0" column="1" >
+ <widget class="QPushButton" name="btnSearch" >
+ <property name="text" >
+ <string>Search</string>
+ </property>
+ <property name="default" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2" >
+ <widget class="QTableWidget" name="tableWidgetWMSList" >
+ <property name="selectionMode" >
+ <enum>QAbstractItemView::SingleSelection</enum>
+ </property>
+ <property name="selectionBehavior" >
+ <enum>QAbstractItemView::SelectRows</enum>
+ </property>
+ <property name="cornerButtonEnabled" >
+ <bool>false</bool>
+ </property>
+ <column>
+ <property name="text" >
+ <string>Title</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>URL</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Description</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2" >
+ <widget class="QPushButton" name="btnAddWMS" >
+ <property name="text" >
+ <string>Add selected row to WMS list</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="4" >
+ <widget class="QGroupBox" name="btnGrpImageEncoding" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize" >
+ <size>
+ <width>16</width>
+ <height>64</height>
+ </size>
+ </property>
<property name="title" >
- <string>Server Connections</string>
+ <string>Image encoding</string>
</property>
- <layout class="QGridLayout" >
- <property name="margin" >
- <number>9</number>
- </property>
- <property name="spacing" >
- <number>6</number>
- </property>
- <item row="1" column="4" >
- <widget class="QPushButton" name="btnAddDefault" >
- <property name="statusTip" >
- <string>Adds a few example WMS servers</string>
- </property>
- <property name="whatsThis" >
- <string comment="Adds several example WMS servers to the list" />
- </property>
- <property name="text" >
- <string>Add default servers</string>
- </property>
- </widget>
- </item>
- <item row="1" column="5" >
- <spacer>
- <property name="orientation" >
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType" >
- <enum>QSizePolicy::Expanding</enum>
- </property>
- <property name="sizeHint" >
- <size>
- <width>131</width>
- <height>30</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="0" column="0" colspan="6" >
- <widget class="QComboBox" name="cmbConnections" />
- </item>
- <item row="1" column="0" >
- <widget class="QPushButton" name="btnConnect" >
- <property name="enabled" >
- <bool>false</bool>
- </property>
- <property name="text" >
- <string>C&onnect</string>
- </property>
- </widget>
- </item>
- <item row="1" column="2" >
- <widget class="QPushButton" name="btnEdit" >
- <property name="enabled" >
- <bool>false</bool>
- </property>
- <property name="text" >
- <string>Edit</string>
- </property>
- </widget>
- </item>
- <item row="1" column="3" >
- <widget class="QPushButton" name="btnDelete" >
- <property name="enabled" >
- <bool>false</bool>
- </property>
- <property name="text" >
- <string>Delete</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1" >
- <widget class="QPushButton" name="btnNew" >
- <property name="text" >
- <string>&New</string>
- </property>
- </widget>
- </item>
- </layout>
</widget>
</item>
- <item row="3" column="0" colspan="4" >
+ <item row="2" column="0" colspan="4" >
<widget class="QGroupBox" name="gbCRS" >
<property name="title" >
<string>Coordinate Reference System</string>
</property>
<layout class="QHBoxLayout" >
- <property name="margin" >
- <number>9</number>
- </property>
- <property name="spacing" >
- <number>6</number>
- </property>
<item>
<widget class="QLabel" name="labelCoordRefSys" >
<property name="text" >
@@ -160,118 +257,23 @@
</layout>
</widget>
</item>
- <item row="5" column="0" colspan="4" >
- <widget class="QLabel" name="labelStatus" >
- <property name="sizePolicy" >
- <sizepolicy>
- <hsizetype>13</hsizetype>
- <vsizetype>5</vsizetype>
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text" >
- <string>Ready</string>
- </property>
- <property name="wordWrap" >
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item row="4" column="2" >
- <widget class="QPushButton" name="btnAdd" >
+ <item row="3" column="0" >
+ <widget class="QPushButton" name="btnHelp" >
<property name="enabled" >
- <bool>false</bool>
+ <bool>true</bool>
</property>
<property name="text" >
- <string>&Add</string>
+ <string>Help</string>
</property>
<property name="shortcut" >
- <string>Alt+A</string>
+ <string>F1</string>
</property>
<property name="autoDefault" >
<bool>true</bool>
</property>
- <property name="default" >
- <bool>true</bool>
- </property>
</widget>
</item>
- <item row="2" column="0" colspan="4" >
- <widget class="QGroupBox" name="groupBox2" >
- <property name="title" >
- <string>Layers</string>
- </property>
- <layout class="QVBoxLayout" >
- <property name="margin" >
- <number>9</number>
- </property>
- <property name="spacing" >
- <number>6</number>
- </property>
- <item>
- <widget class="QTreeWidget" name="lstLayers" >
- <property name="sizePolicy" >
- <sizepolicy>
- <hsizetype>7</hsizetype>
- <vsizetype>7</vsizetype>
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="selectionMode" >
- <enum>QAbstractItemView::MultiSelection</enum>
- </property>
- <property name="allColumnsShowFocus" >
- <bool>true</bool>
- </property>
- <column>
- <property name="text" >
- <string>ID</string>
- </property>
- </column>
- <column>
- <property name="text" >
- <string>Name</string>
- </property>
- </column>
- <column>
- <property name="text" >
- <string>Title</string>
- </property>
- </column>
- <column>
- <property name="text" >
- <string>Abstract</string>
- </property>
- </column>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item row="1" column="0" colspan="4" >
- <widget class="QGroupBox" name="btnGrpImageEncoding" >
- <property name="sizePolicy" >
- <sizepolicy>
- <hsizetype>5</hsizetype>
- <vsizetype>5</vsizetype>
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize" >
- <size>
- <width>16</width>
- <height>64</height>
- </size>
- </property>
- <property name="title" >
- <string>Image encoding</string>
- </property>
- </widget>
- </item>
- <item row="4" column="1" >
+ <item row="3" column="1" >
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
@@ -287,23 +289,26 @@
</property>
</spacer>
</item>
- <item row="4" column="0" >
- <widget class="QPushButton" name="btnHelp" >
+ <item row="3" column="2" >
+ <widget class="QPushButton" name="btnAdd" >
<property name="enabled" >
- <bool>true</bool>
+ <bool>false</bool>
</property>
<property name="text" >
- <string>Help</string>
+ <string>&Add</string>
</property>
<property name="shortcut" >
- <string>F1</string>
+ <string>Alt+A</string>
</property>
<property name="autoDefault" >
<bool>true</bool>
</property>
+ <property name="default" >
+ <bool>true</bool>
+ </property>
</widget>
</item>
- <item row="4" column="3" >
+ <item row="3" column="3" >
<widget class="QPushButton" name="btnCancel" >
<property name="text" >
<string>C&lose</string>
@@ -316,6 +321,22 @@
</property>
</widget>
</item>
+ <item row="4" column="0" colspan="4" >
+ <widget class="QLabel" name="labelStatus" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Ignored" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Ready</string>
+ </property>
+ <property name="wordWrap" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11" />
More information about the QGIS-commit
mailing list