summaryrefslogtreecommitdiffstats
path: root/kicker/kicker/plugins/beaglesearch.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kicker/kicker/plugins/beaglesearch.cpp')
-rw-r--r--kicker/kicker/plugins/beaglesearch.cpp362
1 files changed, 362 insertions, 0 deletions
diff --git a/kicker/kicker/plugins/beaglesearch.cpp b/kicker/kicker/plugins/beaglesearch.cpp
new file mode 100644
index 000000000..9f86c8fbd
--- /dev/null
+++ b/kicker/kicker/plugins/beaglesearch.cpp
@@ -0,0 +1,362 @@
+/*****************************************************************
+
+ Copyright (c) 2006 Debajyoti Bera <dbera.web@gmail.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+******************************************************************/
+
+#include "beaglesearch.h"
+
+#include <tqdatetime.h>
+#include <tqmutex.h>
+#include <tqstringlist.h>
+#include <tqapplication.h>
+#include <time.h>
+
+void beagle_init ()
+{
+ g_type_init ();
+}
+
+// ---------------- Hit ---------------------------
+
+Hit::Hit (BeagleHit *_hit) : processed (false)
+{
+ hit = beagle_hit_ref (_hit);
+}
+
+Hit::~Hit ()
+{
+ beagle_hit_unref (hit);
+ if (! processed)
+ return;
+ TQDictIterator<TQStringList> it (property_map);
+ for( ; it.current(); ++it )
+ ((TQStringList *)it.current())->clear ();
+
+}
+
+void Hit::processProperties ()
+{
+ processed = true;
+ GSList *prop_list = beagle_hit_get_all_properties (hit);
+ GSList *it;
+ property_map.setAutoDelete (true);
+ for (it = prop_list; it; it = it->next) {
+ BeagleProperty *property = (BeagleProperty *) it->data;
+ TQString key = TQString::fromUtf8 (beagle_property_get_key (property));
+ if (! property_map [key])
+ property_map.insert (key, new TQStringList ());
+ property_map [key]->append (TQString::fromUtf8 (beagle_property_get_value (property)));
+ }
+ g_slist_free (prop_list);
+}
+
+const TQString Hit::operator[] (TQString prop_name)
+{
+ if (! processed)
+ processProperties ();
+
+ TQStringList *prop_list = property_map [prop_name];
+ if (! prop_list)
+ return TQString::null;
+ if (prop_list->count () != 1)
+ return TQString::null;
+ return (TQString)prop_list->first ();
+}
+
+// ---------------- BeagleSearch ------------------
+
+BeagleSearchResult::BeagleSearchResult(int client_id)
+ : client_id (client_id), total (0)
+{
+ hitlist = new TQPtrList<Hit>;
+ hitlist->setAutoDelete (true);
+}
+
+
+BeagleSearchResult::~BeagleSearchResult()
+{
+ // everything is set to autodelete
+}
+
+void BeagleSearchResult::addHit(BeagleHit *_hit)
+{
+ Hit *hit = new Hit (_hit);
+ hitlist->prepend (hit);
+}
+
+const TQPtrList<Hit> *BeagleSearchResult::getHits () const
+{
+ return hitlist;
+}
+
+
+static int total_hits;
+
+static void print_feed_item_hit (BeagleHit *hit)
+{
+ const char *text;
+
+ if (beagle_hit_get_one_property (hit, "dc:title", &text))
+ g_print ("Blog: %s\n", text);
+}
+
+static void print_file_hit (BeagleHit *hit)
+{
+ g_print ("File: %s, (%s)\n", beagle_hit_get_uri (hit), beagle_hit_get_mime_type (hit));
+}
+
+static void print_other_hit (BeagleHit *hit)
+{
+ const char *text;
+
+ g_print ("%s (%s)", beagle_hit_get_uri (hit),
+ beagle_hit_get_source (hit));
+ if (beagle_hit_get_one_property (hit, "dc:title", &text))
+ g_print ("title = %s\n", text);
+}
+
+static void print_hit (BeagleHit *hit)
+{
+ if (strcmp (beagle_hit_get_type (hit), "FeedItem") == 0) {
+ print_feed_item_hit (hit);
+ }
+ else if (strcmp (beagle_hit_get_type (hit), "File") == 0) {
+ print_file_hit (hit);
+ } else {
+ print_other_hit (hit);
+ }
+}
+
+// ---------------- BeagleSearchClient ------------------
+
+void BeagleSearchClient::run ()
+{
+ kdDebug () << "Starting query ..." << endl;
+
+ TQTime query_timer;
+ query_timer.start ();
+
+ g_signal_connect (query, "hits-added",
+ G_CALLBACK (hitsAddedSlot),
+ this);
+ g_signal_connect (query, "finished",
+ G_CALLBACK (finishedSlot),
+ this);
+ beagle_client_send_request_async (client,
+ BEAGLE_REQUEST (query),
+ NULL);
+ g_main_loop_run (main_loop);
+ kdDebug () << "Finished query ..." << endl;
+
+ TQCustomEvent *ev;
+ if (collate_results) {
+ result->query_msec = query_timer.elapsed ();
+
+ ev = new TQCustomEvent (RESULTFOUND, result);
+ TQApplication::postEvent (object, ev);
+ }
+
+ ev = new TQCustomEvent (KILLME, this);
+ TQApplication::postEvent (object, ev);
+
+}
+
+void BeagleSearchClient::stopClient ()
+{
+ if (finished ())
+ return; // duh!
+ kdDebug () << "Query thread " << id << " not yet finished ..." << endl;
+ // get ready for suicide
+ client_mutex->lock ();
+ kill_me = true;
+ g_signal_handlers_disconnect_by_func (
+ query,
+ (void *)hitsAddedSlot,
+ this);
+ g_signal_handlers_disconnect_by_func (
+ query,
+ (void *)finishedSlot,
+ this);
+ g_main_loop_quit (main_loop);
+ client_mutex->unlock ();
+}
+
+void BeagleSearchClient::hitsAddedSlot (BeagleQuery *query,
+ BeagleHitsAddedResponse *response,
+ BeagleSearchClient *bsclient)
+{
+ GSList *hits, *l;
+ gint i;
+ gint nr_hits;
+
+ // check if we are supposed to be killed
+ bsclient->client_mutex->lock ();
+ if (bsclient->kill_me) {
+ kdDebug () << "Suicide time before processing" << endl;
+ bsclient->client_mutex->unlock ();
+ return;
+ }
+ bsclient->client_mutex->unlock ();
+
+ hits = beagle_hits_added_response_get_hits (response);
+
+ nr_hits = g_slist_length (hits);
+ total_hits += nr_hits;
+ g_print ("Found hits (%d) at %ld:\n", nr_hits, time (NULL));
+
+ BeagleSearchResult *search_result;
+ if (! bsclient->collate_results)
+ search_result = new BeagleSearchResult (bsclient->id);
+ else
+ search_result = bsclient->result;
+ search_result->total += nr_hits;
+
+ for (l = hits, i = 1; l; l = l->next, ++i) {
+ //g_print ("[%d] ", i);
+ //print_hit (BEAGLE_HIT (l->data));
+ //g_print ("\n");
+
+ search_result->addHit(BEAGLE_HIT (l->data));//hit);
+ }
+ g_print ("[%ld] hits adding finished \n", time (NULL));
+
+ // check if we are supposed to be killed
+ bsclient->client_mutex->lock ();
+ if (bsclient->kill_me) {
+ kdDebug () << "Suicide time before sending ..." << endl;
+ bsclient->client_mutex->unlock ();
+ if (! bsclient->collate_results)
+ delete search_result;
+ return;
+ }
+ bsclient->client_mutex->unlock ();
+
+ // time to send back results, if user asked so
+ if (bsclient->collate_results)
+ return;
+ TQCustomEvent *ev = new TQCustomEvent (RESULTFOUND, search_result);
+ g_print ("[%ld] event notified \n", time (NULL));
+ TQApplication::postEvent (bsclient->object, ev);
+}
+
+void BeagleSearchClient::finishedSlot (BeagleQuery *query,
+ BeagleFinishedResponse *response,
+ BeagleSearchClient *bsclient)
+{
+ // check if we are supposed to be killed
+ bsclient->client_mutex->lock ();
+ bool should_kill = bsclient->kill_me;
+ TQObject* receiver = bsclient->object;
+ bsclient->client_mutex->unlock ();
+
+ if (should_kill)
+ return;
+
+ g_main_loop_quit (bsclient->main_loop);
+
+ if (bsclient->collate_results)
+ return; // if we are collating, everything will be send from a central place
+ if (receiver) {
+ TQCustomEvent *ev = new TQCustomEvent (SEARCHOVER, bsclient);
+ g_print ("[%ld] query finish notified \n", time (NULL));
+ TQApplication::postEvent (receiver, ev);
+ }
+}
+
+// ----------------- BeagleUtil -------------------
+
+BeagleQuery *
+BeagleUtil::createQueryFromString (TQString query_str,
+ TQStringList &sources_menu,
+ TQStringList &types_menu,
+ int max_hits_per_source)
+{
+ BeagleQuery *beagle_query = beagle_query_new ();
+ beagle_query_set_max_hits (beagle_query, max_hits_per_source); // this is per source!
+
+ kdDebug () << "Creating query from \"" << query_str << "\"" << endl;
+ for ( TQStringList::Iterator it = sources_menu.begin(); it != sources_menu.end(); ++it )
+ beagle_query_add_source (beagle_query, g_strdup ((*it).utf8 ()));
+
+ for ( TQStringList::Iterator it = types_menu.begin(); it != types_menu.end(); ++it )
+ beagle_query_add_hit_type (beagle_query, g_strdup ((*it).utf8 ()));
+
+ TQStringList query_terms;
+ TQString start_date, end_date;
+ TQStringList words = TQStringList::split (' ', query_str, false);
+ for ( TQStringList::Iterator it = words.begin(); it != words.end(); ++it ) {
+ TQStringList key_value_pair = TQStringList::split ('=', *it, false);
+ if (key_value_pair.count () == 1)
+ query_terms += *it;
+ else if (key_value_pair.count () == 2) {
+ TQString key = key_value_pair [0].lower ();
+ TQString value = key_value_pair [1];
+ if (key == "mime")
+ beagle_query_add_mime_type (beagle_query, g_strdup (value.utf8 ()));
+ else if (key == "type")
+ beagle_query_add_hit_type (beagle_query, g_strdup (value.utf8 ()));
+ else if (key == "source")
+ beagle_query_add_source (beagle_query, g_strdup (value.utf8 ()));
+ else if (key == "start")
+ start_date = value;
+ else if (key == "end")
+ end_date = value;
+ else
+ query_terms += *it;
+ } else
+ query_terms += *it;
+ }
+
+ beagle_query_add_text (beagle_query, g_strdup (query_terms.join (" ").utf8 ()));
+ kdDebug () << "Adding query text:" << query_terms.join (" ").utf8 () << endl;
+
+ if (start_date.isNull () && end_date.isNull ())
+ return beagle_query;
+
+ //kdDebug () << "Handling dates ..." << endl;
+ BeagleQueryPartDate * date_part = beagle_query_part_date_new ();
+ if (! start_date.isNull ())
+ beagle_query_part_date_set_start_date (date_part, timestringToBeagleTimestamp (start_date));
+ if (! end_date.isNull ())
+ beagle_query_part_date_set_end_date (date_part, timestringToBeagleTimestamp (end_date));
+ beagle_query_add_part (beagle_query, BEAGLE_QUERY_PART (date_part));
+
+ return beagle_query;
+}
+
+// timestring format allowed YYYYmmDD
+BeagleTimestamp *
+BeagleUtil::timestringToBeagleTimestamp(TQString timestring)
+{
+ //kdDebug () << "datetime string:" << timestring << endl;
+ // FIXME: error check timestring format
+ if (timestring.isNull () || timestring.stripWhiteSpace () == "" || timestring.length() != 8 )
+ return beagle_timestamp_new_from_unix_time (TQDateTime::currentDateTime ().toTime_t ());
+ //TQDateTime dt = TQDateTime::fromString (timestring, Qt::ISODate);
+ struct tm tm_time;
+ time_t timet_time;
+ time (&timet_time);
+ localtime_r (&timet_time, &tm_time);
+ strptime (timestring.ascii(), "%Y%m%d", &tm_time);
+ tm_time.tm_sec = tm_time.tm_min = tm_time.tm_hour = 0;
+ //kdDebug() << asctime (&tm_time) << endl;
+ timet_time = mktime (&tm_time);
+ return beagle_timestamp_new_from_unix_time (timet_time);
+}
+