55
56
#define XAPIAN_VALUE_SCREENSHOT_URLS 185
56
57
#define XAPIAN_VALUE_DESCRIPTION 188
57
58
#define XAPIAN_VALUE_VERSION_INFO 198
59
#define XAPIAN_VALUE_EXENAME 294
58
60
#define XAPIAN_VALUE_CURRENCY 201
60
62
#include "unity-package-search.h"
64
extern gchar* unity_applications_lens_utils_preprocess_string (const gchar* input);
63
#include "columbus.hh"
67
65
struct _UnityPackageSearcher
71
69
Xapian::Enquire *enquire;
72
70
Xapian::QueryParser *query_parser;
72
Columbus::Matcher *matcher;
73
vector<string> col_mapping;
77
static void buildMatcher(UnityPackageSearcher *searcher) {
78
Columbus::Matcher *m = searcher->matcher;
79
Xapian::Database *db = searcher->db;
81
Columbus::Word appnameField("appname");
82
Columbus::Word summaryField("summary");
83
Columbus::Word pkgnameField("pkgname");
84
Columbus::Word exenameField("exename");
86
for(Xapian::PostingIterator post = db->postlist_begin(""); post != db->postlist_end(""); post++) {
87
Xapian::Document xdoc = db->get_document(*post);
89
if(searcher->db_merged) {
90
searcher->col_mapping.push_back(xdoc.get_value(XAPIAN_VALUE_APPNAME));
91
id = searcher->col_mapping.size()-1;
93
id = xdoc.get_docid();
95
Columbus::Document cdoc(id);
98
val = xdoc.get_value(XAPIAN_VALUE_APPNAME);
100
cdoc.addText(appnameField, val.c_str());
101
val = xdoc.get_value(XAPIAN_VALUE_SUMMARY);
103
cdoc.addText(summaryField, val.c_str());
104
val = xdoc.get_value(XAPIAN_VALUE_PKGNAME);
106
cdoc.addText(pkgnameField, val.c_str());
107
val = xdoc.get_value(XAPIAN_VALUE_EXENAME);
109
cdoc.addText(exenameField, val.c_str());
113
m->getErrorValues().addStandardErrors();
114
m->getErrorValues().setSubstringMode();
115
m->getIndexWeights().setWeight(summaryField, 0.5);
121
extern gchar* unity_applications_lens_utils_preprocess_string (const gchar* input);
76
124
/* A Xapian::Sorter that respects the collation rules for the current locale */
77
125
class LocaleKeyMaker : public Xapian::KeyMaker
264
312
dum2 = strstr (dum1, " "); // const
265
313
dum2 == NULL ? : *dum2 = '\0'; // const
266
314
dum2 = g_path_get_basename (dum1); // alloc
315
doc.add_value(XAPIAN_VALUE_EXENAME, dum2);
267
316
indexer->index_text (dum2, 2);
269
318
dum1 = g_strdelimit (dum2, "-", '_'); // in place switch, dum1 own mem
299
348
UnityPackageSearcher *searcher;
300
349
Xapian::WritableDatabase *db;
302
searcher = g_new0 (UnityPackageSearcher, 1);
351
searcher = new UnityPackageSearcher;
303
352
db = new Xapian::WritableDatabase ();
304
353
searcher->db = db;
305
354
searcher->db->add_database (Xapian::InMemory::open ());
307
356
init_searcher (searcher);
309
358
/* Index the menu recursively */
359
searcher->db_merged = false;
310
360
Xapian::TermGenerator *indexer = new Xapian::TermGenerator ();
311
361
index_menu_item (db, indexer, gmenu_tree_get_root_directory (menu));
365
searcher->matcher = new Columbus::Matcher();
366
buildMatcher(searcher);
425
482
g_slice_free (UnityPackageInfo, pkginfo);
428
UnityPackageSearchResult*
429
unity_package_searcher_search (UnityPackageSearcher *searcher,
430
const gchar *search_string,
432
UnityPackageSearchType search_type,
433
UnityPackageSort sort)
485
Xapian::Document get_doc_from_col_match(UnityPackageSearcher *searcher, DocumentID id) {
486
if(searcher->db_merged) {
487
string name = searcher->col_mapping[id];
488
string query = "AA\"";
491
Xapian::QueryParser p;
493
Xapian::Enquire e(*searcher->db);
494
Xapian::MSet matches;
495
p.set_database(*searcher->db);
496
q = p.parse_query(query);
498
matches = e.get_mset(0, 1);
499
return matches.begin().get_document();
501
return searcher->db->get_document(id);
505
static UnityPackageSearchResult*
506
xapian_search (UnityPackageSearcher *searcher,
507
const gchar *search_string,
509
UnityPackageSearchType search_type,
510
UnityPackageSort sort)
435
512
UnityPackageSearchResult* result;
437
g_return_val_if_fail (searcher != NULL, NULL);
438
g_return_val_if_fail (search_string != NULL, NULL);
440
513
string _search_string (search_string);
441
514
Xapian::Query query;
444
518
switch (search_type)
488
561
// Retrieve the results, note that we build the result->results
489
562
// list in reverse order and then reverse it before we return it
490
563
result->num_hits = matches.get_matches_estimated ();
491
565
for (Xapian::MSetIterator i = matches.begin(); i != matches.end(); ++i)
495
Xapian::Document doc = i.get_document();
496
UnityPackageInfo *pkginfo = _pkginfo_from_document (doc);
497
pkginfo->relevancy = i.get_percent ();
498
result->results = g_slist_prepend (result->results, pkginfo);
500
catch (Xapian::Error e)
502
g_warning ("Unable to read document from result set: %s", e.get_msg().c_str());
569
Xapian::Document doc = i.get_document();
570
UnityPackageInfo *pkginfo = _pkginfo_from_document (doc);
571
pkginfo->relevancy = i.get_percent();
572
result->results = g_slist_prepend (result->results, pkginfo);
574
catch (Xapian::Error &e)
576
g_warning ("Unable to read document from result set: %s",
577
e.get_msg().c_str());
506
581
result->results = g_slist_reverse (result->results);
508
catch(const Xapian::Error e)
583
catch(const Xapian::Error &e)
510
585
g_warning ("Error running query '%s': %s", search_string, e.get_msg().c_str());
591
static UnityPackageSearchResult*
592
libcolumbus_search(UnityPackageSearcher *searcher, const char *str) {
593
Columbus::MatchResults results;
594
UnityPackageSearchResult* result;
596
result = g_slice_new0 (UnityPackageSearchResult);
597
searcher->matcher->match(str, results);
598
for (size_t i = 0; i < results.size(); ++i)
602
Xapian::Document doc = get_doc_from_col_match(searcher, results.getDocumentID(i));
603
UnityPackageInfo *pkginfo = _pkginfo_from_document (doc);
604
pkginfo->relevancy = results.getRelevancy(i);
605
result->results = g_slist_prepend (result->results, pkginfo);
607
catch (Xapian::Error &e)
609
g_warning ("Unable to read document from result set: %s",
610
e.get_msg().c_str());
614
result->results = g_slist_reverse (result->results);
618
UnityPackageSearchResult*
619
unity_package_searcher_search (UnityPackageSearcher *searcher,
620
const gchar *search_string,
622
UnityPackageSearchType search_type,
623
UnityPackageSort sort)
626
g_return_val_if_fail (searcher != NULL, NULL);
627
g_return_val_if_fail (search_string != NULL, NULL);
629
bool has_category = strstr(search_string, "category:") != NULL;
630
const char *col_query_str = strstr(search_string, "AND");
631
if(has_category || !col_query_str) {
632
return xapian_search(searcher, search_string, max_hits, search_type, sort);
635
return libcolumbus_search(searcher, col_query_str);
517
641
* Get applications matching given xapian filter query and additionally filter results out
518
642
* using AppFilterCallback, until n_apps matching apps are found.