From 0b649ae8d660bc6df7bfebbb7f4975b88aa015c9 Mon Sep 17 00:00:00 2001 From: dockes Date: Wed, 3 Dec 2008 17:04:20 +0000 Subject: [PATCH] cleaned up virtual tree and url handling. Drag to desktop now works with appropriate name. recollf protocol --- src/kde/kioslave/recoll/CMakeLists.txt | 2 +- src/kde/kioslave/recoll/data/help.html | 2 +- src/kde/kioslave/recoll/dirif.cpp | 166 ++++++++++---------- src/kde/kioslave/recoll/htmlif.cpp | 66 ++++---- src/kde/kioslave/recoll/kio_recoll.cpp | 203 +++++++++++++++++-------- src/kde/kioslave/recoll/kio_recoll.h | 68 +++++++-- src/kde/kioslave/recoll/notes.txt | Bin 4199 -> 6177 bytes 7 files changed, 320 insertions(+), 187 deletions(-) diff --git a/src/kde/kioslave/recoll/CMakeLists.txt b/src/kde/kioslave/recoll/CMakeLists.txt index ce9698dc..cdba9852 100644 --- a/src/kde/kioslave/recoll/CMakeLists.txt +++ b/src/kde/kioslave/recoll/CMakeLists.txt @@ -95,7 +95,7 @@ target_link_libraries(kio_recoll xapian ${EXTRA_LIBS} ${KDE4_KIO_LIBS}) install(TARGETS kio_recoll DESTINATION ${PLUGIN_INSTALL_DIR}) IF ("${KDE_VERSION_MAJOR}.${KDE_VERSION_MINOR}" GREATER 4.0) - install(FILES recoll.protocol DESTINATION ${SERVICES_INSTALL_DIR}) + install(FILES recoll.protocol recollf.protocol DESTINATION ${SERVICES_INSTALL_DIR}) ELSE ("${KDE_VERSION_MAJOR}.${KDE_VERSION_MINOR}" GREATER 4.0) install(FILES recollnolist.protocol DESTINATION ${SERVICES_INSTALL_DIR} RENAME recoll.protocol) diff --git a/src/kde/kioslave/recoll/data/help.html b/src/kde/kioslave/recoll/data/help.html index 9cf799a8..d6619ade 100644 --- a/src/kde/kioslave/recoll/data/help.html +++ b/src/kde/kioslave/recoll/data/help.html @@ -4,7 +4,7 @@ Recoll Kio Slave - Recoll search + Recoll search

Recoll kio slave

Use this module to perform Recoll searches from any program with diff --git a/src/kde/kioslave/recoll/dirif.cpp b/src/kde/kioslave/recoll/dirif.cpp index 987f3f34..ed6c8ed7 100644 --- a/src/kde/kioslave/recoll/dirif.cpp +++ b/src/kde/kioslave/recoll/dirif.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: dirif.cpp,v 1.8 2008-12-03 10:02:20 dockes Exp $ (C) 2008 J.F.Dockes"; +static char rcsid[] = "@(#$Id: dirif.cpp,v 1.9 2008-12-03 17:04:20 dockes Exp $ (C) 2008 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -53,14 +53,14 @@ static const QString resultBaseName("recollResult"); // is the search string). If it is, extract return the result document // number. Possibly restart the search if the search string does not // match the current one -bool RecollProtocol::isRecollResult(const KUrl &url, int *num) +bool RecollProtocol::isRecollResult(const KUrl &url, int *num, QString *q) { *num = -1; - kDebug() << "url" << url << "m_srchStr" << m_srchStr; + kDebug() << "url" << url; // Basic checks if (!url.host().isEmpty() || url.path().isEmpty() || - url.protocol().compare("recoll")) + (url.protocol().compare("recoll") && url.protocol().compare("recollf"))) return false; QString path = url.path(); if (!path.startsWith("/")) @@ -87,13 +87,7 @@ bool RecollProtocol::isRecollResult(const KUrl &url, int *num) // We do have something that ressembles a recoll result locator. Check if // this matches the current search, else have to run the requested one - QString searchstring = path.mid(1, slashpos-2); - kDebug() << "Comparing search strings" << m_srchStr << "and" << searchstring; - if (searchstring.compare(m_srchStr)) { - if (!doSearch(searchstring)) - return false; - } - + *q = path.mid(1, slashpos-2); return true; } @@ -106,7 +100,7 @@ static const UDSEntry resultToUDSEntry(const Rcl::Doc& doc, int num) kDebug() << doc.url.c_str(); entry.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, url.fileName()); - char cnum[30];sprintf(cnum, "%d", num); + char cnum[30];sprintf(cnum, "%04d", num); entry.insert(KIO::UDSEntry::UDS_NAME, resultBaseName + cnum); if (!doc.mimetype.compare("application/x-fsdirectory")) { @@ -150,7 +144,7 @@ static void createGoHomeEntry(KIO::UDSEntry& entry) entry.insert(KIO::UDSEntry::UDS_NAME, "search"); entry.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, "Recoll search (click me)"); entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFREG); - entry.insert(KIO::UDSEntry::UDS_TARGET_URL, "recoll:///welcome"); + entry.insert(KIO::UDSEntry::UDS_TARGET_URL, "recoll:///search.html"); entry.insert(KIO::UDSEntry::UDS_ACCESS, 0500); entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, "text/html"); entry.insert(KIO::UDSEntry::UDS_ICON_NAME, "recoll"); @@ -175,28 +169,40 @@ static void createGoHelpEntry(KIO::UDSEntry& entry) void RecollProtocol::stat(const KUrl & url) { kDebug() << url << endl ; - int num = -1; - QString path = url.path(); - QString host = url.host(); + + UrlIngester ingest(this, url); + KIO::UDSEntry entry; - if (!host.isEmpty()) { - // Do nothing probably coming from the html form, if we return a - // directory here, we crash konqueror - kDebug() << "HOST NOT EMPTY:" << host; - } else if (!path.compare("/")) { - createRootEntry(entry); - } else if (!path.compare("/help")) { - createGoHelpEntry(entry); - } else if (!path.compare("/search")) { - createGoHomeEntry(entry); - // } else if (!path.compare("/welcome")) { - } else if (isRecollResult(url, &num)) { - // Let's stat said result. - Rcl::Doc doc; - if (num >= 0 && !m_source.isNull() && m_source->getDoc(num, doc)) { - entry = resultToUDSEntry(doc, num); + UrlIngester::RootEntryType rettp; + QueryDesc qd; + int num; + if (ingest.isRootEntry(&rettp)) { + switch(rettp) { + case UrlIngester::UIRET_ROOT: + createRootEntry(entry); + break; + case UrlIngester::UIRET_HELP: + createGoHelpEntry(entry); + break; + case UrlIngester::UIRET_SEARCH: + createGoHomeEntry(entry); + break; + default: + error(ERR_DOES_NOT_EXIST, ""); + break; } - } else { + } else if (ingest.isResult(&qd, &num)) { + if (syncSearch(qd)) { + Rcl::Doc doc; + if (num >= 0 && !m_source.isNull() && m_source->getDoc(num, doc)) { + entry = resultToUDSEntry(doc, num); + } else { + error(ERR_DOES_NOT_EXIST, ""); + } + } else { + // hopefully syncSearch() set the error? + } + } else if (ingest.isQuery(&qd)) { // ie "recoll:/some string" or "recoll:/some string/" // // We have a problem here. We'd like to let the user enter @@ -207,13 +213,11 @@ void RecollProtocol::stat(const KUrl & url) // // Another approach would be to use different protocol names // to avoid any possibility of mixups - if (path.endsWith("/")) { - QString q, opt; - URLToQuery(url, q, opt); - entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); - entry.insert( KIO::UDSEntry::UDS_ACCESS, 0700); - entry.insert( KIO::UDSEntry::UDS_MIME_TYPE, "inode/directory"); - entry.insert(KIO::UDSEntry::UDS_NAME, q); + if (m_alwaysdir || ingest.alwaysDir() || ingest.endSlashQuery()) { + entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); + entry.insert(KIO::UDSEntry::UDS_ACCESS, 0700); + entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, "inode/directory"); + entry.insert(KIO::UDSEntry::UDS_NAME, qd.query); } } @@ -226,50 +230,48 @@ void RecollProtocol::listDir(const KUrl& url) { kDebug() << url << endl; - // It seems that when the request is from konqueror - // autocompletion it comes with a / at the end, which offers - // an opportunity to not perform it. - if (url.path() != "/" && url.path().endsWith("/")) { - kDebug() << "EndsWith /" << endl; - error(ERR_SLAVE_DEFINED, "Autocompletion search aborted"); - return; - } + UrlIngester ingest(this, url); + UrlIngester::RootEntryType rettp; + QueryDesc qd; - if (!m_initok || !maybeOpenDb(m_reason)) { - string reason = "RecollProtocol::listDir: Init error:" + m_reason; - error(KIO::ERR_SLAVE_DEFINED, reason.c_str()); - return; - } - - if (url.path().isEmpty() || url.path() == "/") { - kDebug() << "list /" << endl; - - UDSEntryList entries; - KIO::UDSEntry entry; - - // entry for '/' - createRootEntry(entry); - entries.append(entry); - - createGoHomeEntry(entry); - entries.append(entry); - createGoHelpEntry(entry); - entries.append(entry); - - listEntries(entries); - finished(); - return; - } - - - QString query, opt; - URLToQuery(url, query, opt); - kDebug() << "Query: " << query; - if (!query.isEmpty()) { - if (!doSearch(query, opt)) + if (ingest.isRootEntry(&rettp)) { + switch(rettp) { + case UrlIngester::UIRET_ROOT: + { + kDebug() << "list /" << endl; + UDSEntryList entries; + KIO::UDSEntry entry; + createRootEntry(entry); + entries.append(entry); + createGoHomeEntry(entry); + entries.append(entry); + createGoHelpEntry(entry); + entries.append(entry); + listEntries(entries); + finished(); + } return; + default: + error(ERR_CANNOT_ENTER_DIRECTORY, ""); + finished(); + return; + } + } else if (ingest.isQuery(&qd)) { + // At this point, it seems that when the request is from + // konqueror autocompletion it comes with a / at the end, + // which offers an opportunity to not perform it. + if (ingest.endSlashQuery()) { + kDebug() << "Ends With /" << endl; + error(ERR_SLAVE_DEFINED, "Autocompletion search aborted"); + return; + } + if (!syncSearch(qd)) { + return; + } + // Fallthrough to actually listing the directory } else { - finished(); + kDebug() << "Cant grok input url"; + error(ERR_CANNOT_ENTER_DIRECTORY, ""); return; } @@ -290,7 +292,9 @@ void RecollProtocol::listDir(const KUrl& url) listEntries(entries); finished(); } + #else // <--- KDE 4.1+ + #include #include "kio_recoll.h" bool RecollProtocol::isRecollResult(const KUrl &, int *) diff --git a/src/kde/kioslave/recoll/htmlif.cpp b/src/kde/kioslave/recoll/htmlif.cpp index 6f3f9d5f..2305f65a 100644 --- a/src/kde/kioslave/recoll/htmlif.cpp +++ b/src/kde/kioslave/recoll/htmlif.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: htmlif.cpp,v 1.5 2008-12-02 13:14:01 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: htmlif.cpp,v 1.6 2008-12-03 17:04:20 dockes Exp $ (C) 2005 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -53,10 +53,24 @@ bool RecollKioPager::append(const string& data) return true; } +string RecollProtocol::makeQueryUrl(int page, bool isdet) +{ + char buf[100]; + sprintf(buf, "recoll://search/query?q=%s&qtp=%s&p=%d", + (const char*)m_query.query.toUtf8(), + (const char*)m_query.opt.toUtf8(), + page); + string ret(buf); + if (isdet) + ret += "&det=1"; + return ret; +} + string RecollKioPager::detailsLink() { - string chunk = ""; - chunk += tr("(show query)") + ""; + string chunk = string("makeQueryUrl(m_parent->m_pager.pageNumber(), true) + "\">" + + "(show query)" + ""; return chunk; } @@ -73,16 +87,7 @@ const string& RecollKioPager::parFormat() string RecollKioPager::pageTop() { - return "

New Search

"; -} - -string RecollProtocol::makeQueryUrl(int page) -{ - char buf[100]; - sprintf(buf, "recoll://search/query?q=%s&qtp=%s&p=%d", - (const char*)m_srchStr.toUtf8(), (const char*)m_opt.toUtf8(), - page); - return string(buf); + return "

New Search

"; } string RecollKioPager::nextUrl() @@ -107,7 +112,7 @@ string RecollKioPager::prevUrl() static string welcomedata; -void RecollProtocol::welcomePage() +void RecollProtocol::searchPage() { kDebug(); mimeType("text/html"); @@ -171,32 +176,35 @@ void RecollProtocol::queryDetails() data(array); } -void RecollProtocol::htmlDoSearch(const QString& q, const QString &opt, int page) +void RecollProtocol::htmlDoSearch(const QueryDesc& qd) { - kDebug() << "q" << q << "opt" << opt << "page" << page; - if (m_source.isNull()) - kDebug() << "Null source"; - // Check if same search or need to start new - if (q.compare(m_srchStr) || opt.compare(m_opt)) { - if (!doSearch(q, opt)) - return; + kDebug() << "q" << qd.query << "opt" << qd.opt << "page" << qd.page << + "isdet" << qd.isDetReq; + + mimeType("text/html"); + + bool samesearch; + if (!syncSearch(qd, &samesearch)) + return; + if (!samesearch) { m_pager.setDocSource(m_source); - // goto page 0 m_pager.resultPageNext(); } + if (qd.isDetReq) { + queryDetails(); + return; + } // Check / adjust page number - if (page > m_pager.pageNumber()) { - int npages = page - m_pager.pageNumber(); + if (qd.page > m_pager.pageNumber()) { + int npages = qd.page - m_pager.pageNumber(); for (int i = 0; i < npages; i++) m_pager.resultPageNext(); - } else if (page < m_pager.pageNumber()) { - int npages = m_pager.pageNumber() - page; + } else if (qd.page < m_pager.pageNumber()) { + int npages = m_pager.pageNumber() - qd.page; for (int i = 0; i < npages; i++) m_pager.resultPageBack(); } // Display - mimeType("text/html"); m_pager.displayPage(); - kDebug() << "done"; } diff --git a/src/kde/kioslave/recoll/kio_recoll.cpp b/src/kde/kioslave/recoll/kio_recoll.cpp index f3d4ef42..60228237 100644 --- a/src/kde/kioslave/recoll/kio_recoll.cpp +++ b/src/kde/kioslave/recoll/kio_recoll.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: kio_recoll.cpp,v 1.20 2008-12-01 18:42:52 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: kio_recoll.cpp,v 1.21 2008-12-03 17:04:20 dockes Exp $ (C) 2005 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -58,7 +58,8 @@ RclConfig *RclConfig::getMainConfig() } RecollProtocol::RecollProtocol(const QByteArray &pool, const QByteArray &app) - : SlaveBase("recoll", pool, app), m_initok(false), m_rcldb(0), m_opt("l") + : SlaveBase("recoll", pool, app), m_initok(false), m_rcldb(0), + m_alwaysdir(false) { kDebug() << endl; if (o_rclconfig == 0) { @@ -81,6 +82,17 @@ RecollProtocol::RecollProtocol(const QByteArray &pool, const QByteArray &app) m_reason = "Could not build database object. (out of memory ?)"; return; } + + // Decide if we allow switching between html and file manager + // presentation by using an end slash or not. Can also be done dynamically + // by switching proto names. + const char *cp = getenv("RECOLL_KIO_ALWAYS_DIR"); + if (cp) { + m_alwaysdir = stringToBool(cp); + } else { + o_rclconfig->getConfParam("kio_always_dir", &m_alwaysdir); + } + m_pager.setParent(this); m_initok = true; return; @@ -113,46 +125,99 @@ bool RecollProtocol::maybeOpenDb(string &reason) void RecollProtocol::mimetype(const KUrl &url) { kDebug() << url << endl; + ///////////////////////////////REMOVEME REMOVEME REMOVEME when sure !///// + abort(); + //////////////////////////////////////////////////////////////////////// mimeType("text/html"); finished(); } -bool RecollProtocol::URLToQuery(const KUrl &url, QString& q, QString& opt, - int *page) +UrlIngester::UrlIngester(RecollProtocol *p, const KUrl& url) + : m_parent(p), m_slashend(false), m_alwaysdir(false), + m_retType(UIRET_NONE), m_resnum(0), m_type(UIMT_NONE) { - // "recoll:/some query/" or "recoll:/some query" + kDebug() << "Url" << url; + m_alwaysdir = !url.protocol().compare("recollf"); + QString path = url.path(); if (url.host().isEmpty()) { - q = url.path(); - opt = "l"; - if (page) - *page = 0; - } else { - // Decode the forms' arguments - q = url.queryItem("q"); - opt = url.queryItem("qtp"); - if (opt.isEmpty()) { - opt = "l"; - } - if (page) { - QString p = url.queryItem("p"); - if (p.isEmpty()) { - *page = 0; - } else { - sscanf(p.toAscii(), "%d", page); - } + if (path.isEmpty() || !path.compare("/")) { + m_type = UIMT_ROOTENTRY; + m_retType = UIRET_ROOT; + return; + } else if (!path.compare("/help.html")) { + m_type = UIMT_ROOTENTRY; + m_retType = UIRET_HELP; + return; + } else if (!path.compare("/search.html")) { + m_type = UIMT_ROOTENTRY; + m_retType = UIRET_SEARCH; + return; + } else if (m_parent->isRecollResult(url, &m_resnum, &m_query.query)) { + m_type = UIMT_QUERYRESULT; + m_query.opt = "l"; + m_query.page = 0; + } else { + // Have to think this is some search string + m_type = UIMT_QUERY; + m_query.query = url.path(); + m_query.opt = "l"; + m_query.page = 0; } + } else { + if (url.host().compare("search")) { + return; + } + m_type = UIMT_QUERY; + // Decode the forms' arguments + m_query.query = url.queryItem("q"); + + m_query.opt = url.queryItem("qtp"); + if (m_query.opt.isEmpty()) { + m_query.opt = "l"; + } + QString p = url.queryItem("p"); + if (p.isEmpty()) { + m_query.page = 0; + } else { + sscanf(p.toAscii(), "%d", &m_query.page); + } + p = url.queryItem("det"); + m_query.isDetReq = !p.isEmpty(); } - if (q.startsWith("/")) - q.remove(0,1); - if (q.endsWith("/")) - q.chop(1); - return true; + if (m_query.query.startsWith("/")) + m_query.query.remove(0,1); + if (m_query.query.endsWith("/")) { + m_slashend = true; + m_query.query.chop(1); + } else { + m_slashend = false; + } + return; +} + +bool RecollProtocol::syncSearch(const QueryDesc &qd, bool *same) +{ + kDebug(); + if (!m_initok || !maybeOpenDb(m_reason)) { + string reason = "RecollProtocol::listDir: Init error:" + m_reason; + error(KIO::ERR_SLAVE_DEFINED, reason.c_str()); + return false; + } + if (qd.sameQuery(m_query)) { + if (same) + *same = true; + return true; + } + if (same) + *same = false; + // doSearch() calls error() if appropriate. + return doSearch(qd); } // This is used by the html interface, but also by the directory one // when doing file copies for exemple. This is the central dispatcher // for requests, it has to know a little about both models. -void RecollProtocol::get(const KUrl & url) +void RecollProtocol::get(const KUrl& url) { kDebug() << url << endl; @@ -162,56 +227,65 @@ void RecollProtocol::get(const KUrl & url) return; } - QString host = url.host(); - QString path = url.path(); - - int docnum = -1; - if (host.isEmpty() && - (path.isEmpty() || !path.compare("/")||!path.compare("/welcome"))) { - // recoll:/ : print the html form page - welcomePage(); - goto out; - } else if (host.isEmpty() && isRecollResult(url, &docnum)) { + UrlIngester ingest(this, url); + UrlIngester::RootEntryType rettp; + QueryDesc qd; + int resnum; + if (ingest.isRootEntry(&rettp)) { + switch(rettp) { + case UrlIngester::UIRET_HELP: + { + QString location = + KStandardDirs::locate("data", "kio_recoll/help.html"); + redirection(location); + } + goto out; + default: + searchPage(); + goto out; + } + } else if (ingest.isResult(&qd, &resnum)) { // Matched an url generated by konqueror out of a directory listing: // ie: recoll:/some search string/recollResultxx // Redirect to the result document URL + if (!syncSearch(qd)) { + return; + } Rcl::Doc doc; - if (docnum >= 0 && !m_source.isNull() && m_source->getDoc(docnum, doc)) { + if (resnum >= 0 && !m_source.isNull() && m_source->getDoc(resnum, doc)) { mimeType(doc.mimetype.c_str()); redirection(KUrl::fromLocalFile((const char *)(doc.url.c_str()+7))); goto out; } - } else if (host.isEmpty() || - (!host.compare("search") && !path.compare("/query"))) { - // Either "recoll://search/query?query args" - // Or "recoll:[/]some search string" - // HTML style query, maybe initial or request for other page - QString query, opt; - int page; - URLToQuery(url, query, opt, &page); - if (!query.isEmpty()) { - htmlDoSearch(query, opt, page); + } else if (ingest.isQuery(&qd)) { +#if 0 +// Do we need this ? + if (host.isEmpty()) { + char cpage[20];sprintf(cpage, "%d", page); + QString nurl = QString::fromAscii("recoll://search/query?q=") + + query + "&qtp=" + opt + "&p=" + cpage; + redirection(KUrl(nurl)); goto out; } - } else if (!host.compare("command")) { - if (path.indexOf("/QueryDetails") == 0) { - queryDetails(); - goto out; - } +#endif + // htmlDoSearch does the search syncing (needs to know about changes). + htmlDoSearch(qd); + goto out; } - error(KIO::ERR_SLAVE_DEFINED, "Unrecognized URL"); + + error(KIO::ERR_SLAVE_DEFINED, "Unrecognized URL or internal error"); out: finished(); } -// Execute Recoll search, and set the docsource etc. -bool RecollProtocol::doSearch(const QString& q, const QString &qopt) +// Execute Recoll search, and set the docsource +bool RecollProtocol::doSearch(const QueryDesc& qd) { - kDebug() << "query" << q << "opt" << qopt; - m_srchStr = q; - m_opt = qopt; - char opt = qopt.isEmpty() ? 'l' : qopt.toUtf8().at(0); - string qs = (const char *)q.toUtf8(); + kDebug() << "query" << qd.query << "opt" << qd.opt; + m_query = qd; + + char opt = qd.opt.isEmpty() ? 'l' : qd.opt.toUtf8().at(0); + string qs = (const char *)qd.query.toUtf8(); Rcl::SearchData *sd = 0; if (opt != 'l') { Rcl::SearchDataClause *clp = 0; @@ -238,7 +312,6 @@ bool RecollProtocol::doSearch(const QString& q, const QString &qopt) if (!sd) { m_reason = "Internal Error: cant build search"; error(KIO::ERR_SLAVE_DEFINED, m_reason.c_str()); - finished(); return false; } @@ -248,7 +321,6 @@ bool RecollProtocol::doSearch(const QString& q, const QString &qopt) if (!query->setQuery(sdata)) { m_reason = "Query execute failed. Invalid query or syntax error?"; error(KIO::ERR_SLAVE_DEFINED, m_reason.c_str()); - finished(); return false; } @@ -256,7 +328,6 @@ bool RecollProtocol::doSearch(const QString& q, const QString &qopt) new DocSequenceDb(RefCntr(query), "Query results", sdata); if (src == 0) { error(KIO::ERR_SLAVE_DEFINED, "Can't build result sequence"); - finished(); return false; } m_source = RefCntr(src); diff --git a/src/kde/kioslave/recoll/kio_recoll.h b/src/kde/kioslave/recoll/kio_recoll.h index e490497d..19f300ff 100644 --- a/src/kde/kioslave/recoll/kio_recoll.h +++ b/src/kde/kioslave/recoll/kio_recoll.h @@ -1,5 +1,5 @@ #ifndef _RECOLL_H -/* @(#$Id: kio_recoll.h,v 1.11 2008-12-01 18:42:52 dockes Exp $ (C) 2005 J.F.Dockes */ +/* @(#$Id: kio_recoll.h,v 1.12 2008-12-03 17:04:20 dockes Exp $ (C) 2005 J.F.Dockes */ #define _RECOLL_H /* * This program is free software; you can redistribute it and/or modify @@ -54,6 +54,54 @@ private: RecollProtocol *m_parent; }; +class QueryDesc { +public: + QueryDesc() : opt("l"), page(0), isDetReq(false) {} + QString query; + QString opt; + int page; + bool isDetReq; + bool sameQuery(const QueryDesc& o) const { + return !opt.compare(o.opt) && !query.compare(o.query); + } +}; + +// Our virtual tree is a bit complicated. We need a class to analyse an URL +// and tell what we should do with it +class UrlIngester { +public: + UrlIngester(RecollProtocol *p, const KUrl& url); + enum RootEntryType {UIRET_NONE, UIRET_ROOT, UIRET_HELP, UIRET_SEARCH}; + bool isRootEntry(RootEntryType *tp) { + if (m_type != UIMT_ROOTENTRY) return false; + *tp = m_retType; + return true; + } + bool isQuery(QueryDesc *q) { + if (m_type != UIMT_QUERY) return false; + *q = m_query; + return true; + } + bool isResult(QueryDesc *q, int *num) { + if (m_type != UIMT_QUERYRESULT) return false; + *q = m_query; + *num = m_resnum; + return true; + } + bool endSlashQuery() {return m_slashend;} + bool alwaysDir() {return m_alwaysdir;} +private: + RecollProtocol *m_parent; + QueryDesc m_query; + bool m_slashend; + bool m_alwaysdir; + RootEntryType m_retType; + int m_resnum; + enum MyType {UIMT_NONE, UIMT_ROOTENTRY, UIMT_QUERY, UIMT_QUERYRESULT}; + MyType m_type; +}; + + /** * A KIO slave to execute and display Recoll searches. * @@ -95,23 +143,25 @@ class RecollProtocol : public KIO::SlaveBase { static RclConfig *o_rclconfig; friend class RecollKioPager; + friend class UrlIngester; private: bool maybeOpenDb(string& reason); bool URLToQuery(const KUrl &url, QString& q, QString& opt, int *page=0); - bool doSearch(const QString& q, const QString& opt = "l"); + bool doSearch(const QueryDesc& qd); - void welcomePage(); + void searchPage(); void queryDetails(); - string makeQueryUrl(int page); - void htmlDoSearch(const QString& q, const QString& opt, int page); + string makeQueryUrl(int page, bool isdet = false); + bool syncSearch(const QueryDesc& qd, bool *same = 0); + void htmlDoSearch(const QueryDesc& qd); - bool isRecollResult(const KUrl &url, int *num); + bool isRecollResult(const KUrl &url, int *num, QString* q); bool m_initok; Rcl::Db *m_rcldb; string m_reason; - + bool m_alwaysdir; // Search state: because of how the KIO slaves are used / reused, // we can't be sure that the next request will be for the same // search, and we need to check and restart one if the data @@ -121,8 +171,8 @@ class RecollProtocol : public KIO::SlaveBase { // cache of recent searches kept open. RecollKioPager m_pager; RefCntr m_source; - QString m_srchStr; - QString m_opt; + // Note: page here is not used, current page always comes from m_pager. + QueryDesc m_query; }; extern "C" {int kdemain(int, char**);} diff --git a/src/kde/kioslave/recoll/notes.txt b/src/kde/kioslave/recoll/notes.txt index 676d3400918cf762e3f23c1624b722a597d37147..00e81e8c8b2129630bc8c99c9ede40058852d2dc 100644 GIT binary patch delta 2083 zcmaJ?!EPf(5JlPrDTA~Zj$8^Ku){j`f&>S%*&J992x(bJ0C9@iGc}%8db(%3dor;Q znvcjAaO8%>2k<%k14xKhJ!2;%()wgqcUQgl>Q(tK`t?bF<_gClJC;wD{aCT3(CL_0 z+HPpgv13Fgo^xl+Y8hDhyrK|2jwhsSarZ16&X$uowSg&COpV$w*|uJ@r_#GR1*=#a z(#y9>I?1v(e*fn||AY3iRfeKxUJZZ}sswBVK-mt-{!7KCSxB~hWB@tD2%nd&XS1cS zwLlYfPSG`F_>v8=1rrVn`ic86r;WY@Tftm{uIoT@j-NVE&B}&Mvc*b8+PaozC$yQyeQ$CR|_wTF1ETwmHkDXt>YT0j3UL8-u zy-JgmuGEI9Ru(S(ZR@wj-Dmv*)CA_61t6k ze^kp!0(T?yT|E{HA(0xHP>*CO%d)S(`i88F9B!F9%Z}*OpuK^V7scDq19e~q{0(da z_8v;PdO@FyCoz&0<<45TN;`YxU|XnCps2IRGSl#EY!2r;YYyi5h%TI!p241QbK$zA zUZKkpirPq(3sHRC=^h1~MQP-tAlRs@G={y?#_X+_8y9%#*`X6j;TufAj6|$tKco#J ziqIFRoU(<1gJ)$>gs+ewVBBD9G|ej0W2>mht&Jq7@bb zy?6chgWui-fzhI*(5Z2%F>!Qq{pZ6E-oZIC4Q%Bb0A2t4@JWw&vI1b%bRvTe2fc7} z!qTzGb9=&+kdd8;mUpf-1r*UyCzY_AHZn&F8SpV!1JAXe9b!kO1HlBs2z0Wz8|)9{ z;zz}>XUD@oR&O4?-DlZngMA=^SoHrJ_BcBO??OnZ0^{R0ZMfyP)Eh*EEu&{8@S;Tn z-o^_ptipT$8>(r-a_D|P#~$EdBPNCNit`Jp2GUbxmF*xcl(t@IcMd0K*`?D3eV6`t zUXEkDT8ZyQ9%vVcXFn%xE}rwc-OLU@O}|D{av_0VQl|c1s$}KY=Ng{gdl@)>iMg4f z4EFN3r|5>=yq{)i4hO-}AAT~Y?BL)awJlxi_xI+a>#cW(cPP-)rzzDA`Tg=ToaZtv zZJ6DCJqVCAKOJsN(k}YA!as8KEhj}D3oyWtb&^!VTwz%77gMY4I!$-6M(+Or^Nzs| delta 89 zcmZ2z@LXYI>u=`CY@91(6pB)dOLIz!xfB!+V4 qS12yeEJ@A)u}U&hfhrXyvvC>lC}fo6<|w4)7v(D0Z$8YW%MAd2I2~vJ