PIM: locale-aware sorting and searching

Change the --enable-dbus-service-pim parameter into one which takes a
parameter that specifies how locale-aware sorting and searching is to
be implemented. The default implementation uses boost::locale. It is
expected to get replaced or augemented by OEMs which want to implement
more complex sorting or searching (like ignoring Tussenvoegsel in the
Netherlands).

The LocaleFactory instance takes the current locale from the
environment. Making it and its users aware of locale changes at
runtime might be needed at some point but is not part of the API at
the moment.

The Manager class uses the factory to handle sorting and searching
requests coming in via D-Bus. Right now, that is not functional yet
because the boost::locale implementation is just a stub. It only
compiles and links.

FullView::setSortOrder is now functional.

Clean up view code a bit:
- All views delay populating their content until the caller asks for
  it. For the FullView this will only happen once, so the caller must be
  able to handle an already populated view, which was missing
  in ViewResource. Still need a test for this.
- Use init(<smart pointer) consistently.
This commit is contained in:
Patrick Ohly 2012-10-09 09:18:42 +02:00
parent 8b5644ad0f
commit f13956bd4b
9 changed files with 451 additions and 43 deletions

View File

@ -61,6 +61,11 @@ dnl check for programs.
AC_PROG_CXX
AC_PROG_MAKE_SET
# Boost headers: boost/foreach.hpp is needed (1.33/Debian Etch
# doesn't have it, 1.34/Ubuntu 8.10 Hardy does). 1.35 is available
# as Debian Etch backport.
AX_BOOST_BASE(1.34)
# TODO: Fix code to pass with -pedantic -Wextra.
# -Wno-unknown-pragmas needed because icalstrdup.h
# currently uses the "#pragma }" trick. Should remove that.
@ -517,21 +522,48 @@ if test $enable_dbus_service = "yes"; then
AC_DEFINE(DBUS_SERVICE, 1, [define if dbus service is enabled])
AC_ARG_ENABLE(dbus-service-pim,
AS_HELP_STRING([--enable-dbus-service-pim],
[enable implementation of org._01.pim D-Bus APIs (depends on libfolks)]),
AS_HELP_STRING([--enable-dbus-service-pim[=<locale>]],
[Enable implementation of org._01.pim D-Bus APIs (depends on libfolks),
using src/dbus/server/pim/locale-factory-<locale>.cpp to implement sorting
and searching. The default is <locale>=boost, which uses boost::locale.]),
[ enable_dbus_pim="$enableval" ],
[ enable_dbus_pim="no" ])
case "$enable_dbus_pim" in
no) ;;
yes)
*)
if test "$enable_dbus_pim" = "yes"; then
enable_dbus_pim=boost
fi
if ! test -r "$srcdir/src/dbus/server/pim/locale-factory-$enable_dbus_pim.cpp"; then
AC_MSG_ERROR([invalid value '$enable_dbus_pim' for --enable-dbus-service-pim, $srcdir/src/dbus/server/pim/locale-factory-$enable_dbus_pim.cpp does not exist or is not readable])
fi
PKG_CHECK_MODULES(FOLKS, [folks])
AC_DEFINE(ENABLE_DBUS_PIM, 1, [org._01.pim D-Bus API enabled])
DBUS_PIM_PLUGIN=$enable_dbus_pim
AC_SUBST(DBUS_PIM_PLUGIN)
case "$enable_dbus_pim" in
boost)
AX_BOOST_LOCALE
# AX_BOOST_LOCALE incorrectly puts -L/... into LDFLAGS.
# That's broken because it then overrides the search path
# for *all* libraries in a link, not just for boost. Fix
# this by putting the LDFLAGS before the lib and leaving
# DBUS_PIM_PLUGIN_LDFLAGS empty (for now - might have to
# be revised if there ever are any boost flags which need
# to go to the start of the link line).
DBUS_PIM_PLUGIN_LIBS='$(BOOST_LDFLAGS) $(BOOST_LOCALE_LIB)'
DBUS_PIM_PLUGIN_LDFLAGS=
;;
esac
AC_SUBST(DBUS_PIM_PLUGIN_CFLAGS)
AC_SUBST(DBUS_PIM_PLUGIN_LIBS)
AC_SUBST(DBUS_PIM_PLUGIN_LDFLAGS)
;;
*) AC_MSG_ERROR([invalid value for --enable-dbus-service-pim: '$enable_dbus_pim']);;
esac
fi
AM_CONDITIONAL([NOTIFY_COMPATIBILITY], [test "$enable_notify_compat" = "yes"])
AM_CONDITIONAL([COND_DBUS_PIM], [test "$enable_dbus_pim" = "yes"])
AM_CONDITIONAL([COND_DBUS_PIM], [test "$enable_dbus_pim" != "no"])
AC_SUBST(DBUS_CFLAGS)
AC_SUBST(DBUS_LIBS)
@ -623,11 +655,6 @@ AC_SUBST(GUI_LIBS)
AC_SUBST(GUI_PROGRAMS)
AC_SUBST(GUI_DESKTOP_FILES)
# Boost headers: boost/foreach.hpp is needed (1.33/Debian Etch
# doesn't have it, 1.34/Ubuntu 8.10 Hardy does). 1.35 is available
# as Debian Etch backport.
AX_BOOST_BASE(1.34)
# C++ regular expression support is required often enough to make it
# mandatory.
PKG_CHECK_MODULES(PCRECPP, libpcrecpp)

119
m4-repo/ax_boost_locale.m4 Normal file
View File

@ -0,0 +1,119 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_boost_locale.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_BOOST_LOCALE
#
# DESCRIPTION
#
# Test for System library from the Boost C++ libraries. The macro requires
# a preceding call to AX_BOOST_BASE. Further documentation is available at
# <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
# AC_SUBST(BOOST_LOCALE_LIB)
#
# And sets:
#
# HAVE_BOOST_LOCALE
#
# LICENSE
#
# Copyright (c) 2012 Xiyue Deng <manphiz@gmail.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 1
AC_DEFUN([AX_BOOST_LOCALE],
[
AC_ARG_WITH([boost-locale],
AS_HELP_STRING([--with-boost-locale@<:@=special-lib@:>@],
[use the Locale library from boost - it is possible to specify a certain library for the linker
e.g. --with-boost-locale=boost_locale-gcc-mt ]),
[
if test "$withval" = "no"; then
want_boost="no"
elif test "$withval" = "yes"; then
want_boost="yes"
ax_boost_user_locale_lib=""
else
want_boost="yes"
ax_boost_user_locale_lib="$withval"
fi
],
[want_boost="yes"]
)
if test "x$want_boost" = "xyes"; then
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_CANONICAL_BUILD])
CPPFLAGS_SAVED="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
export LDFLAGS
AC_CACHE_CHECK(whether the Boost::Locale library is available,
ax_cv_boost_locale,
[AC_LANG_PUSH([C++])
CXXFLAGS_SAVE=$CXXFLAGS
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/locale.hpp>]],
[[boost::locale::generator gen;
std::locale::global(gen(""));]])],
ax_cv_boost_locale=yes, ax_cv_boost_locale=no)
CXXFLAGS=$CXXFLAGS_SAVE
AC_LANG_POP([C++])
])
if test "x$ax_cv_boost_locale" = "xyes"; then
AC_SUBST(BOOST_CPPFLAGS)
AC_DEFINE(HAVE_BOOST_LOCALE,,[define if the Boost::Locale library is available])
BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
LDFLAGS_SAVE=$LDFLAGS
if test "x$ax_boost_user_locale_lib" = "x"; then
for libextension in `ls $BOOSTLIBDIR/libboost_locale*.so* $BOOSTLIBDIR/libboost_locale*.dylib* $BOOSTLIBDIR/libboost_locale*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_locale.*\)\.so.*$;\1;' -e 's;^lib\(boost_locale.*\)\.dylib.*$;\1;' -e 's;^lib\(boost_locale.*\)\.a.*$;\1;'` ; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_LOCALE_LIB="-l$ax_lib"; AC_SUBST(BOOST_LOCALE_LIB) link_locale="yes"; break],
[link_locale="no"])
done
if test "x$link_locale" != "xyes"; then
for libextension in `ls $BOOSTLIBDIR/boost_locale*.dll* $BOOSTLIBDIR/boost_locale*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_locale.*\)\.dll.*$;\1;' -e 's;^\(boost_locale.*\)\.a.*$;\1;'` ; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_LOCALE_LIB="-l$ax_lib"; AC_SUBST(BOOST_LOCALE_LIB) link_locale="yes"; break],
[link_locale="no"])
done
fi
else
for ax_lib in $ax_boost_user_locale_lib boost_locale-$ax_boost_user_locale_lib; do
AC_CHECK_LIB($ax_lib, exit,
[BOOST_LOCALE_LIB="-l$ax_lib"; AC_SUBST(BOOST_LOCALE_LIB) link_locale="yes"; break],
[link_locale="no"])
done
fi
if test "x$ax_lib" = "x"; then
AC_MSG_ERROR(Could not find a version of the library!)
fi
if test "x$link_locale" = "xno"; then
AC_MSG_ERROR(Could not link against $ax_lib !)
fi
fi
CPPFLAGS="$CPPFLAGS_SAVED"
LDFLAGS="$LDFLAGS_SAVED"
fi
])

View File

@ -87,6 +87,14 @@ void IndividualData::init(const boost::shared_ptr<IndividualCompare> &compare,
compare->createCriteria(individual, m_criteria);
}
void IndividualView::start()
{
if (!m_started) {
m_started = true;
doStart();
}
}
void IndividualView::readContacts(int start, int count, std::vector<FolksIndividualCXX> &contacts)
{
contacts.clear();
@ -138,7 +146,12 @@ FullView::FullView(const FolksIndividualAggregatorCXX &folks) :
{
}
void FullView::init()
void FullView::init(const boost::shared_ptr<FullView> &self)
{
m_self = self;
}
void FullView::doStart()
{
// Populate view from current set of data. Usually FullView
// gets instantiated when the aggregator is idle, in which
@ -162,9 +175,14 @@ void FullView::init()
}
individuals.sort(IndividualDataCompare(m_compare));
// Copy the sorted data into the view. No slots are called,
// because nothing can be connected at the moment.
// Copy the sorted data into the view in one go.
m_entries.insert(m_entries.begin(), individuals.begin(), individuals.end());
// Avoid loop if no-one is listening.
if (!m_addedSignal.empty()) {
for (size_t index = 0; index < m_entries.size(); index++) {
m_addedSignal(index, m_entries[index].m_individual);
}
}
// Connect to changes. Aggregator might live longer than we do, so
// bind to weak pointer and check our existence at runtime.
@ -181,13 +199,14 @@ void FullView::init()
GParamSpec *pspec)>("notify::is-quiescent",
boost::bind(&FullView::quiesenceChanged,
m_self));
}
boost::shared_ptr<FullView> FullView::create(const FolksIndividualAggregatorCXX &folks)
{
boost::shared_ptr<FullView> view(new FullView(folks));
view->m_self = view;
view->init();
view->init(view);
return view;
}
@ -353,22 +372,74 @@ void FullView::waitForIdle()
void FullView::setCompare(const boost::shared_ptr<IndividualCompare> &compare)
{
// TODO
if (!compare) {
// Fall back to debug ordering.
m_compare.reset(new CompareFormattedName());
} else {
m_compare = compare;
}
// Reorder a copy of the current data.
Entries_t entries(m_entries);
BOOST_FOREACH (IndividualData &data, entries) {
data.init(m_compare, data.m_individual);
}
std::sort(entries.begin(), entries.end(), IndividualDataCompare(m_compare));
// Now update real array.
for (size_t index = 0; index < entries.size(); index++) {
IndividualData &previous = m_entries[index],
&current = entries[index];
if (previous.m_individual != current.m_individual) {
// Contact at the index changed. Don't try to find out
// where it came from now. The effect is that temporarily
// the same contact might be shown at two different
// indices.
m_modifiedSignal(index, current.m_individual);
}
// Ensure that m_entries is up-to-date, whatever the change
// may have been.
std::swap(previous, current);
}
// Current status is stable again, send out all modifications.
m_quiesenceSignal();
}
FilteredView::FilteredView(const boost::shared_ptr<IndividualView> &parent,
const boost::shared_ptr<IndividualFilter> &filter) :
m_parent(parent),
m_filter(filter)
{
}
void FilteredView::init(const boost::shared_ptr<FilteredView> &self)
{
m_self = self;
m_parent->m_quiesenceSignal.connect(QuiesenceSignal_t::slot_type(boost::bind(boost::cref(m_quiesenceSignal))).track(m_self));
}
boost::shared_ptr<FilteredView> FilteredView::create(const boost::shared_ptr<IndividualView> &parent,
const boost::shared_ptr<IndividualFilter> &filter)
{
boost::shared_ptr<FilteredView> view(new FilteredView);
view->m_self = view;
view->m_parent = parent;
parent->m_quiesenceSignal.connect(QuiesenceSignal_t::slot_type(boost::bind(boost::cref(view->m_quiesenceSignal))).track(view->m_self));
// TODO
boost::shared_ptr<FilteredView> view(new FilteredView(parent, filter));
view->init(view);
return view;
}
void FilteredView::start()
void FilteredView::doStart()
{
// TODO
// Add initial content. Our processing of the new contact must not
// cause changes to the parent view, otherwise the result will not
// be inconsistent.
for (int index = 0; index < m_parent->size(); index++) {
addIndividual(index, m_parent->getContact(index));
}
// Start listening to signals.
m_parent->m_addedSignal.connect(ChangeSignal_t::slot_type(boost::bind(&FilteredView::addIndividual, this, _1, _2)).track(m_self));
m_parent->m_modifiedSignal.connect(ChangeSignal_t::slot_type(boost::bind(&FilteredView::modifyIndividual, this, _1, _2)).track(m_self));
m_parent->m_removedSignal.connect(ChangeSignal_t::slot_type(boost::bind(&FilteredView::removeIndividual, this, _1, _2)).track(m_self));
}
void FilteredView::addIndividual(int parentIndex, FolksIndividual *individual)
{
@ -378,7 +449,7 @@ void FilteredView::removeIndividual(int parentIndex, FolksIndividual *individual
{
// TODO
}
void FilteredView::changeIndividual(int parentIndex, FolksIndividual *individual)
void FilteredView::modifyIndividual(int parentIndex, FolksIndividual *individual)
{
// TODO
}
@ -500,7 +571,7 @@ void IndividualAggregator::start()
}
}
boost::shared_ptr<IndividualView> IndividualAggregator::getMainView()
boost::shared_ptr<FullView> IndividualAggregator::getMainView()
{
if (!m_view) {
start();

View File

@ -151,6 +151,8 @@ class IndividualAggregator;
*/
class IndividualView
{
Bool m_started;
public:
typedef boost::signals2::signal<void (int, FolksIndividual *)> ChangeSignal_t;
typedef boost::signals2::signal<void (void)> QuiesenceSignal_t;
@ -182,6 +184,12 @@ class IndividualView
*/
ChangeSignal_t m_modifiedSignal;
/**
* Start filling the view. Gives the user a chance to connect
* to the signals first. May be called multiple times.
*/
void start();
/** current number of entries */
virtual int size() const = 0;
@ -190,6 +198,12 @@ class IndividualView
/** returns access to one individual or an empty pointer if outside of the current range */
virtual FolksIndividualCXX getContact(int index) = 0;
protected:
/**
* Start filling the view. Will only be called once by start().
*/
virtual void doStart() = 0;
};
/**
@ -215,7 +229,7 @@ class FullView : public IndividualView
boost::shared_ptr<IndividualCompare> m_compare;
FullView(const FolksIndividualAggregatorCXX &folks);
void init();
void init(const boost::shared_ptr<FullView> &self);
/**
* Run via m_waitForIdle if (and only if) something
@ -281,10 +295,13 @@ class FullView : public IndividualView
* Set new sort method. Reorders current set of entries on the
* fly. Default is lexicographical comparison of the single-string
* full name.
*
* @param compare the new ordering or NULL for the builtin default (last/first with ASCII lexicographic comparison)
*/
void setCompare(const boost::shared_ptr<IndividualCompare> &compare);
// from IndividualView
virtual void doStart();
virtual int size() const { return (int)m_entries.size(); }
virtual FolksIndividualCXX getContact(int index) { return (index >= 0 && (unsigned)index < m_entries.size()) ? m_entries[index].m_individual : FolksIndividualCXX(); }
};
@ -297,8 +314,8 @@ class FullView : public IndividualView
class FilteredView : public IndividualView
{
boost::weak_ptr<FilteredView> m_self;
boost::shared_ptr<IndividualFilter> m_filter;
boost::shared_ptr<IndividualView> m_parent;
boost::shared_ptr<IndividualFilter> m_filter;
/**
* Maps local indices to indices in parent view. Could be be
@ -307,6 +324,10 @@ class FilteredView : public IndividualView
*/
std::vector<int> m_local2parent;
FilteredView(const boost::shared_ptr<IndividualView> &parent,
const boost::shared_ptr<IndividualFilter> &filter);
void init(const boost::shared_ptr<FilteredView> &self);
public:
/**
* Creates an idle IndividualAggregator. Configure it and
@ -315,12 +336,6 @@ class FilteredView : public IndividualView
static boost::shared_ptr<FilteredView> create(const boost::shared_ptr<IndividualView> &parent,
const boost::shared_ptr<IndividualFilter> &filter);
/**
* Populates view from current content of parent, then
* updates it based on incoming signals.
*/
void start();
/**
* Add a FolksIndividual if it matches the filter. Tracking of
* changes to individuals is done in parent view.
@ -335,9 +350,10 @@ class FilteredView : public IndividualView
/**
* Check whether a changed individual still belongs into the view.
*/
void changeIndividual(int parentIndex, FolksIndividual *individual);
void modifyIndividual(int parentIndex, FolksIndividual *individual);
// from IndividualView
virtual void doStart();
virtual int size() const { return (int)m_local2parent.size(); }
virtual FolksIndividualCXX getContact(int index) { return (index >= 0 && (unsigned)index < m_local2parent.size()) ? m_parent->getContact(m_local2parent[index]) : FolksIndividualCXX(); }
};
@ -414,7 +430,7 @@ class IndividualAggregator
*
* @return never empty, start() will be called if necessary
*/
boost::shared_ptr<IndividualView> getMainView();
boost::shared_ptr<FullView> getMainView();
};

View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2012 Intel Corporation
*
* This library 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.1 of the License, or (at your option) version 3.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
/**
* The boost::locale based implementation of locale-factory.h.
*/
#include "locale-factory.h"
#include "folks.h"
#include <boost/locale.hpp>
SE_BEGIN_CXX
class LocaleFactoryBoost : public LocaleFactory
{
std::locale m_locale;
public:
LocaleFactoryBoost() :
m_locale(boost::locale::generator()(""))
{}
virtual boost::shared_ptr<IndividualCompare> createCompare(const std::string &order)
{
SE_THROW("not implemented");
}
virtual boost::shared_ptr<IndividualFilter> createFilter(const StringMap &filter)
{
SE_THROW("not implemented");
}
};
boost::shared_ptr<LocaleFactory> LocaleFactory::createFactory()
{
return boost::shared_ptr<LocaleFactory>(new LocaleFactoryBoost());
}
SE_END_CXX

View File

@ -0,0 +1,82 @@
/*
* Copyright (C) 2012 Intel Corporation
*
* This library 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.1 of the License, or (at your option) version 3.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
/**
* Abstract definition of sorting and searching plugin. Used
* by folks.cpp, must be provided by exactly one implementation
* which is chosen at compile time.
*/
#ifndef INCL_SYNCEVO_DBUS_SERVER_PIM_LOCALE_FACTORY
#define INCL_SYNCEVO_DBUS_SERVER_PIM_LOCALE_FACTORY
#include <boost/shared_ptr.hpp>
#include <syncevo/util.h>
#include <syncevo/declarations.h>
SE_BEGIN_CXX
class IndividualCompare;
class IndividualFilter;
/**
* Factory for everything related to the current locale: sorting and
* searching.
*/
class LocaleFactory
{
public:
/**
* Exactly one factory can be created, chosen at compile time.
*/
static boost::shared_ptr<LocaleFactory> createFactory();
/**
* Creates a compare instance or throws an error when that is not
* possible.
*
* @param order factory-specific string which chooses one of
* the orderings supported by the factory
* @return a valid instance, must not be NULL
*/
virtual boost::shared_ptr<IndividualCompare> createCompare(const std::string &order) = 0;
/**
* An array of search terms which all must match. Each search term
* itself is again an array of strings, with the first one choosing
* the search criteria and the rest providing parameters for that
* search term.
*/
typedef std::vector< std::vector<std::string> > Filter_t;
/**
* Creates a filter instance or throws an error when that is not
* possible.
*
* @param order factory-specific string which chooses one of
* the search criteria supported by the factory
* @return a valid instance, must not be NULL
*/
virtual boost::shared_ptr<IndividualFilter> createFilter(const Filter_t &filter) = 0;
};
SE_END_CXX
#endif // INCL_SYNCEVO_DBUS_SERVER_PIM_LOCALE_FACTORY

View File

@ -60,7 +60,8 @@ Manager::Manager(const boost::shared_ptr<Server> &server) :
DBusObjectHelper(server->getConnection(),
MANAGER_PATH,
MANAGER_IFACE),
m_server(server)
m_server(server),
m_locale(LocaleFactory::createFactory())
{
// Prevent automatic shut down during idle times, because we need
// to keep our unified address book available.
@ -78,7 +79,7 @@ Manager::~Manager()
void Manager::init()
{
// TODO: restore sort order
m_sortOrder = "first/last";
m_sortOrder = ""; // use default sorting in FullView
initFolks();
initSorting();
@ -110,8 +111,15 @@ void Manager::initFolks()
void Manager::initSorting()
{
// TODO: mirror m_sortOrder in m_folks main view
// Mirror m_sortOrder in m_folks main view.
// Empty string passes NULL pointer to setCompare(),
// which chooses the builtin sorting in folks.cpp,
// independent of the locale plugin.
boost::shared_ptr<IndividualCompare> compare;
if (!m_sortOrder.empty()) {
compare = m_locale->createCompare(m_sortOrder);
}
m_folks->getMainView()->setCompare(compare);
}
boost::shared_ptr<Manager> Manager::create(const boost::shared_ptr<Server> &server)
@ -388,6 +396,14 @@ class ViewResource : public Resource, public GDBusCXX::DBusObjectHelper
add(this, &ViewResource::refineSearch, "RefineSearch");
activate();
// The view might have been started already, for example when
// reconnecting a ViewResource to the persistent full view.
// Therefore tell the agent about the current content before
// starting, then connect to signals, and finally start.
int size = m_view->size();
if (size) {
sendChange(m_contactsAdded, 0, size);
}
m_view->m_quiesenceSignal.connect(IndividualView::QuiesenceSignal_t::slot_type(&ViewResource::flushChanges,
this).track(self));
m_view->m_modifiedSignal.connect(IndividualView::ChangeSignal_t::slot_type(&ViewResource::handleChange,
@ -405,7 +421,7 @@ class ViewResource : public Resource, public GDBusCXX::DBusObjectHelper
boost::cref(m_contactsRemoved),
_1,
1).track(self));
m_view->start();
}
public:
@ -478,8 +494,11 @@ GDBusCXX::DBusObject_t Manager::search(const GDBusCXX::Caller_t &ID,
boost::shared_ptr<Client> client = m_server->addClient(ID, watch);
boost::shared_ptr<IndividualView> view;
// TODO: parse filter
view = m_folks->getMainView();
if (!filter.empty()) {
boost::shared_ptr<IndividualFilter> individualFilter = m_locale->createFilter(filter);
view = FilteredView::create(view, individualFilter);
}
boost::shared_ptr<ViewResource> viewResource(ViewResource::create(view,
client,

View File

@ -26,6 +26,7 @@
#define INCL_SYNCEVO_DBUS_SERVER_PIM_MANAGER
#include "folks.h"
#include "locale-factory.h"
#include "../server.h"
#include <syncevo/declarations.h>
@ -39,6 +40,7 @@ class Manager : public GDBusCXX::DBusObjectHelper
boost::weak_ptr<Manager> m_self;
boost::shared_ptr<Server> m_server;
boost::shared_ptr<IndividualAggregator> m_folks;
boost::shared_ptr<LocaleFactory> m_locale;
std::string m_sortOrder;
/**
* Contains the EDS UUIDs of all address books contributing to the current

View File

@ -43,8 +43,11 @@ src_dbus_server_libsyncevodbusserver_la_SOURCES = \
$(src_dbus_server_server_cpp_files) \
src/dbus/server/main.cpp
nodist_src_dbus_server_libsyncevodbusserver_la_SOURCES =
dist_pkgdata_DATA += src/dbus/server/bluetooth_products.ini
src_dbus_server_libsyncevodbusserver_la_LDFLAGS =
src_dbus_server_libsyncevodbusserver_la_LIBADD = $(LIBNOTIFY_LIBS) $(MLITE_LIBS) $(DBUS_LIBS)
src_dbus_server_libsyncevodbusserver_la_CPPFLAGS = -DHAVE_CONFIG_H -DSYNCEVOLUTION_LOCALEDIR=\"${SYNCEVOLUTION_LOCALEDIR}\" -I$(top_srcdir)/src -I$(top_srcdir)/test -I$(top_srcdir) -I$(gdbus_dir) $(BACKEND_CPPFLAGS)
src_dbus_server_libsyncevodbusserver_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS) $(CORE_CXXFLAGS) $(SYNTHESIS_CFLAGS) $(GLIB_CFLAGS) $(DBUS_CFLAGS) $(LIBNOTIFY_CFLAGS) $(MLITE_CFLAGS) $(SYNCEVO_WFLAGS)
@ -54,10 +57,23 @@ src_dbus_server_server_cpp_files += \
src/dbus/server/pim/individual-traits.cpp \
src/dbus/server/pim/folks.cpp \
src/dbus/server/pim/manager.cpp
src_dbus_server_libsyncevodbusserver_la_LIBADD += $(FOLKS_LIBS)
src_dbus_server_libsyncevodbusserver_la_CXXFLAGS += $(FOLKS_CFLAGS)
src_dbus_server_server_h_files += \
src/dbus/server/pim/locale-factory.h
nodist_src_dbus_server_libsyncevodbusserver_la_SOURCES += \
src/dbus/server/pim/locale-factory-@DBUS_PIM_PLUGIN@.cpp
src_dbus_server_libsyncevodbusserver_la_LDFLAGS += $(DBUS_PIM_PLUGIN_LDFLAGS)
src_dbus_server_libsyncevodbusserver_la_LIBADD += $(FOLKS_LIBS) $(DBUS_PIM_PLUGIN_LIBS)
src_dbus_server_libsyncevodbusserver_la_CXXFLAGS += $(FOLKS_CFLAGS) $(DBUS_PIM_PLUGIN_CFLAGS)
endif
# Need to list all plugins here and not include the active one in the regular
# source list above, because "make dist" would only include the configured one.
EXTRA_DIST += \
src/dbus/server/pim/locale-factory-boost.cpp
# Session helper: syncevo-dbus-helper
noinst_LTLIBRARIES += src/dbus/server/libsyncevodbushelper.la