kio module sort of working with kde5 dolphin, but not konqueror

This commit is contained in:
Jean-Francois Dockes 2016-04-04 19:53:30 +02:00
parent 6938a4a4d4
commit 2de064796d
7 changed files with 212 additions and 197 deletions

View File

@ -55,12 +55,12 @@ Recipe:
--prefix=/usr (or wherever KDE lives), build and install
Recoll.
- In the Recoll source, go to kde/kioslave/recoll, then build and
- In the Recoll source, go to kde/kioslave/kio_recoll, then build and
install the kio slave:
mkdir builddir
cd builddir
cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DQT_QMAKE_EXECUTABLE=/usr/bin/qmake-qt4
cmake .. -DCMAKE_INSTALL_PREFIX=/usr
make
sudo make install
@ -78,17 +78,3 @@ You need to build/update the index with recollindex, the KIO slave
doesn't deal with indexing for now.
Misc build problems:
===================
KUBUNTU 8.10 (updated to 2008-27-11)
------------------------------------
cmake generates a bad dependancy on
/build/buildd/kde4libs-4.1.2/obj-i486-linux-gnu/lib/libkdecore.so
inside CMakeFiles/kio_recoll.dir/build.make
Found no way to fix this. You need to edit the line and replace the
/build/[...]/lib with /usr/lib. This manifests itself with the
following error message:
make[2]: *** No rule to make target `/build/buildd/kde4libs-4.1.2/obj-i486-linux-gnu/lib/libkdecore.so', needed by `lib/kio_recoll.so'. Stop.

View File

@ -1,16 +1,42 @@
cmake_minimum_required(VERSION 2.6)
project(kio_recoll)
find_package(KDE4 REQUIRED)
cmake_minimum_required(VERSION 2.8.12)
add_definitions(${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
add_definitions(-DKDE_DEFAULT_DEBUG_AREA=7130
-DRECOLL_DATADIR=\\"${CMAKE_INSTALL_PREFIX}/share/recoll\\"
-DLIBDIR=\\"${CMAKE_INSTALL_PREFIX}/lib\\"
include(FeatureSummary)
set(QT_MIN_VERSION 5.2.0)
set(KF5_MIN_VERSION 5.0.0)
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
Network
Widgets)
find_package(ECM REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
include(KDEInstallDirs)
include(KDECMakeSettings)
include(KDECompilerSettings NO_POLICY_SCOPE)
# CoreAddons?
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
KIO)
add_definitions(-DQT_NO_URL_CAST_FROM_STRING)
include_directories(
${CMAKE_SOURCE_DIR}
${CMAKE_BINARY_DIR}
)
## Recoll stuff
add_definitions(
-DRECOLL_DATADIR="${CMAKE_INSTALL_PREFIX}/share/recoll"
-DLIBDIR="${CMAKE_INSTALL_PREFIX}/lib"
-DHAVE_CONFIG_H
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}")
set(rcltop ${CMAKE_CURRENT_SOURCE_DIR}/../../../)
@ -22,7 +48,7 @@ execute_process(COMMAND ${rcltop}/configure --disable-static --disable-qtgui --d
link_directories(${rcltop}/.libs ${CMAKE_INSTALL_PREFIX}/lib)
include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES}
include_directories (${CMAKE_SOURCE_DIR}
${rcltop}/aspell
${rcltop}/bincimapmime
${rcltop}/common
@ -35,16 +61,9 @@ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES}
${rcltop}/qtgui
)
set(kio_recoll_SRCS kio_recoll.cpp htmlif.cpp dirif.cpp ${rcltop}/qtgui/guiutils.cpp)
set(kio_recoll_SRCS kio_recoll.cpp htmlif.cpp dirif.cpp
${rcltop}/qtgui/guiutils.cpp)
CHECK_LIBRARY_EXISTS(dl dlopen "" DLOPEN_IN_LIBDL)
IF(DLOPEN_IN_LIBDL)
LIST(APPEND EXTRA_LIBS dl)
ENDIF(DLOPEN_IN_LIBDL)
CHECK_LIBRARY_EXISTS(pthread pthread_sigmask "" PTHREAD_IN_LIBPTHREAD)
IF(PTHREAD_IN_LIBPTHREAD)
LIST(APPEND EXTRA_LIBS pthread)
ENDIF(PTHREAD_IN_LIBPTHREAD)
# Had the idea to add e.g. /usr/lib/recoll to the rpath so that the dyn lib
# will be found at run time. But this does not seem to work with debian
@ -52,24 +71,30 @@ ENDIF(PTHREAD_IN_LIBPTHREAD)
# paths but I did not find it). Link with the .a instead.
#SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib/recoll")
kde4_add_plugin(kio_recoll ${kio_recoll_SRCS})
add_library(kio_recoll MODULE ${kio_recoll_SRCS})
add_custom_target(rcllib
COMMAND make PicStatic
COMMAND make -j 6 PicStatic
WORKING_DIRECTORY ${rcltop}
)
add_dependencies(kio_recoll rcllib)
target_link_libraries(kio_recoll recoll xapian z ${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 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)
ENDIF ("${KDE_VERSION_MAJOR}.${KDE_VERSION_MINOR}" GREATER 4.0)
target_link_libraries(kio_recoll
recoll
xapian
KF5::KIOCore
z
pthread
)
install(FILES recoll.protocol DESTINATION ${SERVICES_INSTALL_DIR})
install(FILES data/welcome.html data/help.html
DESTINATION ${DATA_INSTALL_DIR}/kio_recoll)
# Tried but could not use PLUGIN_INSTALL_DIR (/usr/lib64/plugins), or
# /usr/lib64/qt5/plugins/kf5/kio/recoll.so: the module is not found by
# dolphin). Actually that's because of the protocol file. recoll has
# exec=kio_recoll, file has exec=kf5/kio/file
set_target_properties(kio_recoll PROPERTIES OUTPUT_NAME "kio_recoll")
install(TARGETS kio_recoll DESTINATION ${LIB_INSTALL_DIR}/qt5/plugins)

View File

@ -26,19 +26,15 @@
#include "autoconfig.h"
#include <kdeversion.h>
#if KDE_IS_VERSION(4,1,0)
// Couldn't get listDir() to work with kde 4.0, konqueror keeps
// crashing because of kdirmodel, couldn't find a workaround (not
// saying it's impossible)...
#include <sys/stat.h>
#include <kurl.h>
#include <kio/global.h>
#include <kstandarddirs.h>
#include <kdebug.h>
#include <QDebug>
#include <QUrl>
#include <QStandardPaths>
#include "kio_recoll.h"
#include "pathut.h"
@ -52,18 +48,24 @@ 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, QString *q)
bool RecollProtocol::isRecollResult(const QUrl &url, int *num, QString *q)
{
*num = -1;
kDebug() << "url" << url;
qDebug() << "RecollProtocol::isRecollResult: url: " << url;
// Basic checks
if (!url.host().isEmpty() || url.path().isEmpty() ||
(url.protocol().compare("recoll") && url.protocol().compare("recollf")))
(url.scheme().compare("recoll") && url.scheme().compare("recollf"))) {
qDebug() << "RecollProtocol::isRecollResult: no: url.host " <<
url.host() << " path " << url.path() << " scheme " << url.scheme();
return false;
}
QString path = url.path();
if (!path.startsWith("/"))
return false;
qDebug() << "RecollProtocol::isRecollResult: path: " << path;
// if (!path.startsWith("/")) {
// return false;
// }
// Look for the last '/' and check if it is followed by
// resultBaseName (riiiight...)
@ -71,18 +73,18 @@ bool RecollProtocol::isRecollResult(const KUrl &url, int *num, QString *q)
if (slashpos == -1 || slashpos == 0 || slashpos == path.length() -1)
return false;
slashpos++;
//kDebug() << "Comparing " << path.mid(slashpos, resultBaseName.length()) <<
//qDebug() << "Comparing " << path.mid(slashpos, resultBaseName.length()) <<
// "and " << resultBaseName;
if (path.mid(slashpos, resultBaseName.length()).compare(resultBaseName))
return false;
// Extract the result number
QString snum = path.mid(slashpos + resultBaseName.length());
sscanf(snum.toAscii(), "%d", num);
sscanf(snum.toUtf8(), "%d", num);
if (*num == -1)
return false;
//kDebug() << "URL analysis ok, num:" << *num;
//qDebug() << "URL analysis ok, num:" << *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
@ -95,8 +97,8 @@ static const UDSEntry resultToUDSEntry(const Rcl::Doc& doc, int num)
{
UDSEntry entry;
KUrl url(doc.url.c_str());
// kDebug() << doc.url.c_str();
QUrl url(doc.url.c_str());
// qDebug() << doc.url.c_str();
entry.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, url.fileName());
char cnum[30];sprintf(cnum, "%04d", num);
@ -105,7 +107,7 @@ static const UDSEntry resultToUDSEntry(const Rcl::Doc& doc, int num)
if (!doc.mimetype.compare("application/x-fsdirectory") ||
!doc.mimetype.compare("inode/directory")) {
entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, "inode/directory");
entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
} else {
entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, doc.mimetype.c_str());
entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFREG);
@ -113,7 +115,7 @@ static const UDSEntry resultToUDSEntry(const Rcl::Doc& doc, int num)
entry.insert(KIO::UDSEntry::UDS_LOCAL_PATH, url.path());
// For local files, supply the usual file stat information
struct stat info;
if (lstat(url.path().toAscii(), &info) >= 0) {
if (lstat(url.path().toUtf8(), &info) >= 0) {
entry.insert( KIO::UDSEntry::UDS_SIZE, info.st_size);
entry.insert( KIO::UDSEntry::UDS_ACCESS, info.st_mode);
entry.insert( KIO::UDSEntry::UDS_MODIFICATION_TIME, info.st_mtime);
@ -153,7 +155,8 @@ static void createGoHomeEntry(KIO::UDSEntry& entry)
static void createGoHelpEntry(KIO::UDSEntry& entry)
{
QString location =
KStandardDirs::locate("data", "kio_recoll/help.html");
QStandardPaths::locate(QStandardPaths::GenericDataLocation,
"kio_recoll/help.html");
entry.clear();
entry.insert(KIO::UDSEntry::UDS_NAME, "help");
entry.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, "Recoll help (click me first)");
@ -165,45 +168,52 @@ static void createGoHelpEntry(KIO::UDSEntry& entry)
entry.insert(KIO::UDSEntry::UDS_ICON_NAME, "help");
}
void RecollProtocol::stat(const KUrl & url)
void RecollProtocol::stat(const QUrl& url)
{
kDebug() << url << endl ;
qDebug() << "RecollProtocol::stat:" << url;
UrlIngester ingest(this, url);
KIO::UDSEntry entry;
entry.insert(KIO::UDSEntry::UDS_TARGET_URL, url.url());
entry.insert(KIO::UDSEntry::UDS_URL, url.url());
UrlIngester::RootEntryType rettp;
QueryDesc qd;
int num;
if (ingest.isRootEntry(&rettp)) {
qDebug() << "RecollProtocol::stat: root entry";
switch(rettp) {
case UrlIngester::UIRET_ROOT:
qDebug() << "RecollProtocol::stat: root";
createRootEntry(entry);
break;
case UrlIngester::UIRET_HELP:
qDebug() << "RecollProtocol::stat: root help";
createGoHelpEntry(entry);
break;
case UrlIngester::UIRET_SEARCH:
qDebug() << "RecollProtocol::stat: root search";
createGoHomeEntry(entry);
break;
default:
error(ERR_DOES_NOT_EXIST, "");
qDebug() << "RecollProtocol::stat: ??";
error(ERR_DOES_NOT_EXIST, QString());
break;
}
} else if (ingest.isResult(&qd, &num)) {
qDebug() << "RecollProtocol::stat: isresult";
if (syncSearch(qd)) {
Rcl::Doc doc;
if (num >= 0 && !m_source.isNull() &&
m_source->getDoc(num, doc)) {
if (num >= 0 && m_source && m_source->getDoc(num, doc)) {
entry = resultToUDSEntry(doc, num);
} else {
error(ERR_DOES_NOT_EXIST, "");
error(ERR_DOES_NOT_EXIST, QString());
}
} else {
// hopefully syncSearch() set the error?
}
} else if (ingest.isQuery(&qd)) {
qDebug() << "RecollProtocol::stat: isquery";
// ie "recoll:/some string" or "recoll:/some string/"
//
// We have a problem here. We'd like to let the user enter
@ -214,23 +224,31 @@ void RecollProtocol::stat(const KUrl & url)
//
// Another approach would be to use different protocol names
// to avoid any possibility of mixups
if (m_alwaysdir || ingest.alwaysDir() || ingest.endSlashQuery()) {
kDebug() << "Directory type";
if (true || m_alwaysdir || ingest.alwaysDir() || ingest.endSlashQuery()) {
qDebug() << "RecollProtocol::stat: Directory type:";
// Need to check no / in there
#if 0
entry.insert(KIO::UDSEntry::UDS_NAME, "dockes bla"/*qd.query*/);
entry.insert(KIO::UDSEntry::UDS_URL, "recoll:other query");
entry.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, qd.query);
entry.insert(KIO::UDSEntry::UDS_ACCESS, 0777);
entry.insert(KIO::UDSEntry::UDS_SIZE, 20480);
entry.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, time(0));
entry.insert(KIO::UDSEntry::UDS_CREATION_TIME, time(0));
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);
entry.insert( KIO::UDSEntry::UDS_MODIFICATION_TIME, time(0));
entry.insert( KIO::UDSEntry::UDS_CREATION_TIME, time(0));
#endif
}
} else {
qDebug() << "RecollProtocol::stat: none of the above ??";
}
statEntry(entry);
finished();
}
void RecollProtocol::listDir(const KUrl& url)
void RecollProtocol::listDir(const QUrl& url)
{
kDebug() << url << endl;
qDebug() << "RecollProtocol::listDir: url: " << url;
UrlIngester ingest(this, url);
UrlIngester::RootEntryType rettp;
@ -240,7 +258,7 @@ void RecollProtocol::listDir(const KUrl& url)
switch(rettp) {
case UrlIngester::UIRET_ROOT:
{
kDebug() << "list /" << endl;
qDebug() << "RecollProtocol::listDir:list /";
UDSEntryList entries;
KIO::UDSEntry entry;
createRootEntry(entry);
@ -254,7 +272,7 @@ void RecollProtocol::listDir(const KUrl& url)
}
return;
default:
error(ERR_CANNOT_ENTER_DIRECTORY, "");
error(ERR_CANNOT_ENTER_DIRECTORY, QString());
return;
}
} else if (ingest.isQuery(&qd)) {
@ -262,8 +280,8 @@ void RecollProtocol::listDir(const KUrl& url)
// 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");
qDebug() << "RecollProtocol::listDir: Ends With /";
error(ERR_SLAVE_DEFINED, u8s2qs("Autocompletion search aborted"));
return;
}
if (!syncSearch(qd)) {
@ -272,8 +290,8 @@ void RecollProtocol::listDir(const KUrl& url)
}
// Fallthrough to actually listing the directory
} else {
kDebug() << "Cant grok input url";
error(ERR_CANNOT_ENTER_DIRECTORY, "");
qDebug() << "RecollProtocol::listDir: Cant grok input url";
error(ERR_CANNOT_ENTER_DIRECTORY, QString());
return;
}
@ -291,28 +309,18 @@ void RecollProtocol::listDir(const KUrl& url)
int pagelen = m_source->getSeqSlice(pagebase, pagesize, page);
UDSEntry entry;
if (pagelen < 0) {
error(ERR_SLAVE_DEFINED, "Internal error");
listEntry(entry, true);
error(ERR_SLAVE_DEFINED, u8s2qs("Internal error"));
break;
}
UDSEntryList entries;
for (int i = 0; i < pagelen; i++) {
listEntry(resultToUDSEntry(page[i].doc, i), false);
entries.push_back(resultToUDSEntry(page[i].doc, i));
}
listEntries(entries);
if (pagelen != pagesize) {
listEntry(entry, true);
break;
}
pagebase += pagelen;
}
finished();
}
#else // <--- KDE 4.1+
#include <kurl.h>
#include "kio_recoll.h"
bool RecollProtocol::isRecollResult(const KUrl &, int *, QString *)
{
return false;
}
#endif

View File

@ -22,11 +22,7 @@
#include <sys/stat.h>
#include <string>
using namespace std;
#include <kdebug.h>
#include <kstandarddirs.h>
#include <QStandardPaths>
#include "rclconfig.h"
#include "rcldb.h"
@ -44,6 +40,7 @@ using namespace std;
#include "wipedir.h"
#include "hldata.h"
using namespace std;
using namespace KIO;
bool RecollKioPager::append(const string& data)
@ -110,7 +107,7 @@ string RecollKioPager::pageTop()
return pt;
// Would be nice to have but doesnt work because the query may be executed
// by another kio instance which has no idea of the current page o
#if 0 && KDE_IS_VERSION(4,1,0)
#if 0
" &nbsp;&nbsp;&nbsp;<a href=\"recoll:///" +
url_encode(string(m_parent->m_query.query.toUtf8())) +
"/\">Directory view</a> (you may need to reload the page)"
@ -143,8 +140,9 @@ void RecollProtocol::searchPage()
{
mimeType("text/html");
if (welcomedata.empty()) {
QString location =
KStandardDirs::locate("data", "kio_recoll/welcome.html");
QString location =
QStandardPaths::locate(QStandardPaths::GenericDataLocation,
"kio_recoll/welcome.html");
string reason;
if (location.isEmpty() ||
!file_to_string((const char *)location.toUtf8(),
@ -239,7 +237,8 @@ void RecollProtocol::showPreview(const Rcl::Doc& idoc)
Rcl::Doc fdoc;
string ipath = idoc.ipath;
if (!interner.internfile(fdoc, ipath)) {
error(KIO::ERR_SLAVE_DEFINED, "Cannot convert file to internal format");
error(KIO::ERR_SLAVE_DEFINED,
u8s2qs("Cannot convert file to internal format"));
return;
}
if (!interner.get_html().empty()) {
@ -254,7 +253,7 @@ void RecollProtocol::showPreview(const Rcl::Doc& idoc)
ptr.set_inputhtml(!fdoc.mimetype.compare("text/html"));
list<string> otextlist;
HighlightData hdata;
if (!m_source.isNull())
if (m_source)
m_source->getTerms(hdata);
ptr.plaintorich(fdoc.text, otextlist, hdata);
@ -270,7 +269,7 @@ void RecollProtocol::showPreview(const Rcl::Doc& idoc)
void RecollProtocol::htmlDoSearch(const QueryDesc& qd)
{
kDebug() << "q" << qd.query << "option" << qd.opt << "page" << qd.page <<
qDebug() << "q" << qd.query << "option" << qd.opt << "page" << qd.page <<
"isdet" << qd.isDetReq << endl;
mimeType("text/html");

View File

@ -21,16 +21,12 @@
#include <errno.h>
#include <string>
using namespace std;
#include <qglobal.h>
#include <qfile.h>
#include <qtextstream.h>
#include <qstring.h>
#include <kdebug.h>
#include <kcomponentdata.h>
#include <kstandarddirs.h>
#include <QCoreApplication>
#include <QObject>
#include <QString>
#include <QUrlQuery>
#include <QStandardPaths>
#include "rclconfig.h"
#include "rcldb.h"
@ -47,6 +43,7 @@ using namespace std;
#include "guiutils.h"
using namespace KIO;
using namespace std;
RclConfig *RecollProtocol::o_rclconfig;
@ -54,7 +51,10 @@ RecollProtocol::RecollProtocol(const QByteArray &pool, const QByteArray &app)
: SlaveBase("recoll", pool, app), m_initok(false), m_rcldb(0),
m_alwaysdir(false)
{
kDebug() << endl;
qDebug() << "RecollProtocol::RecollProtocol()";
int fd = ::creat("/tmp/recolldebug", 0666);
::write(fd, "Hello\n", strlen("Hello\n"));
::close(fd);
if (o_rclconfig == 0) {
o_rclconfig = recollinit(0, 0, m_reason);
if (!o_rclconfig || !o_rclconfig->ok()) {
@ -102,7 +102,7 @@ RecollProtocol::RecollProtocol(const QByteArray &pool, const QByteArray &app)
// Doesn't seem needed in the kio context.
RecollProtocol::~RecollProtocol()
{
kDebug();
qDebug() << "RecollProtocol::~RecollProtocol()";
delete m_rcldb;
}
@ -120,19 +120,19 @@ bool RecollProtocol::maybeOpenDb(string &reason)
}
// This is never called afaik
void RecollProtocol::mimetype(const KUrl &url)
void RecollProtocol::mimetype(const QUrl &url)
{
kDebug() << url << endl;
qDebug() << "RecollProtocol::mimetype: url: " << url;
mimeType("text/html");
finished();
}
UrlIngester::UrlIngester(RecollProtocol *p, const KUrl& url)
UrlIngester::UrlIngester(RecollProtocol *p, const QUrl& url)
: m_parent(p), m_slashend(false), m_alwaysdir(false),
m_retType(UIRET_NONE), m_resnum(0), m_type(UIMT_NONE)
{
kDebug() << "Url" << url;
m_alwaysdir = !url.protocol().compare("recollf");
qDebug() << "UrlIngester::UrlIngester: Url: " << url;
m_alwaysdir = !url.scheme().compare("recollf");
QString path = url.path();
if (url.host().isEmpty()) {
if (path.isEmpty() || !path.compare("/")) {
@ -146,8 +146,9 @@ UrlIngester::UrlIngester(RecollProtocol *p, const KUrl& url)
} else if (!path.compare("/search.html")) {
m_type = UIMT_ROOTENTRY;
m_retType = UIRET_SEARCH;
QUrlQuery q(url);
// Retrieve the query value for preloading the form
m_query.query = url.queryItem("q");
m_query.query = q.queryItemValue("q");
return;
} else if (m_parent->isRecollResult(url, &m_resnum, &m_query.query)) {
m_type = UIMT_QUERYRESULT;
@ -163,30 +164,33 @@ UrlIngester::UrlIngester(RecollProtocol *p, const KUrl& url)
} else {
// Non empty host, url must be something like :
// //search/query?q=query&param=value...
kDebug() << "host" << url.host() << "path" << url.path();
qDebug() << "UrlIngester::UrlIngester: host " <<
url.host() << " path " << url.path();
if (url.host().compare("search") || url.path().compare("/query")) {
return;
}
m_type = UIMT_QUERY;
// Decode the forms' arguments
m_query.query = url.queryItem("q");
// Retrieve the query value for preloading the form
QUrlQuery q(url);
m_query.query = q.queryItemValue("q");
m_query.opt = url.queryItem("qtp");
m_query.opt = q.queryItemValue("qtp");
if (m_query.opt.isEmpty()) {
m_query.opt = "l";
}
QString p = url.queryItem("p");
QString p = q.queryItemValue("p");
if (p.isEmpty()) {
m_query.page = 0;
} else {
sscanf(p.toAscii(), "%d", &m_query.page);
sscanf(p.toUtf8(), "%d", &m_query.page);
}
p = url.queryItem("det");
p = q.queryItemValue("det");
m_query.isDetReq = !p.isEmpty();
p = url.queryItem("cmd");
p = q.queryItemValue("cmd");
if (!p.isEmpty() && !p.compare("pv")) {
p = url.queryItem("dn");
p = q.queryItemValue("dn");
if (!p.isEmpty()) {
// Preview and no docnum ??
m_resnum = atoi((const char *)p.toUtf8());
@ -199,7 +203,7 @@ UrlIngester::UrlIngester(RecollProtocol *p, const KUrl& url)
if (m_query.query.startsWith("/"))
m_query.query.remove(0,1);
if (m_query.query.endsWith("/")) {
kDebug() << "Ends with /";
qDebug() << "UrlIngester::UrlIngester: query Ends with /";
m_slashend = true;
m_query.query.chop(1);
} else {
@ -210,10 +214,10 @@ UrlIngester::UrlIngester(RecollProtocol *p, const KUrl& url)
bool RecollProtocol::syncSearch(const QueryDesc &qd)
{
kDebug();
qDebug() << "RecollProtocol::syncSearch";
if (!m_initok || !maybeOpenDb(m_reason)) {
string reason = "RecollProtocol::listDir: Init error:" + m_reason;
error(KIO::ERR_SLAVE_DEFINED, reason.c_str());
error(KIO::ERR_SLAVE_DEFINED, u8s2qs(reason));
return false;
}
if (qd.sameQuery(m_query)) {
@ -226,13 +230,13 @@ bool RecollProtocol::syncSearch(const QueryDesc &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 QUrl& url)
{
kDebug() << url << endl;
qDebug() << "RecollProtocol::get: " << url;
if (!m_initok || !maybeOpenDb(m_reason)) {
string reason = "Recoll: init error: " + m_reason;
error(KIO::ERR_SLAVE_DEFINED, reason.c_str());
error(KIO::ERR_SLAVE_DEFINED, u8s2qs(reason));
return;
}
@ -245,8 +249,9 @@ void RecollProtocol::get(const KUrl& url)
case UrlIngester::UIRET_HELP:
{
QString location =
KStandardDirs::locate("data", "kio_recoll/help.html");
redirection(location);
QStandardPaths::locate(QStandardPaths::GenericDataLocation,
"kio_recoll/help.html");
redirection(QUrl::fromLocalFile(location));
}
goto out;
default:
@ -268,9 +273,9 @@ void RecollProtocol::get(const KUrl& url)
return;
}
Rcl::Doc doc;
if (resnum >= 0 && !m_source.isNull() && m_source->getDoc(resnum, doc)) {
if (resnum >= 0 && m_source && m_source->getDoc(resnum, doc)) {
mimeType(doc.mimetype.c_str());
redirection(KUrl::fromLocalFile((const char *)(doc.url.c_str()+7)));
redirection(QUrl::fromLocalFile((const char *)(doc.url.c_str()+7)));
goto out;
}
} else if (ingest.isPreview(&qd, &resnum)) {
@ -278,7 +283,7 @@ void RecollProtocol::get(const KUrl& url)
return;
}
Rcl::Doc doc;
if (resnum >= 0 && !m_source.isNull() && m_source->getDoc(resnum, doc)) {
if (resnum >= 0 && m_source && m_source->getDoc(resnum, doc)) {
showPreview(doc);
goto out;
}
@ -289,7 +294,7 @@ void RecollProtocol::get(const KUrl& url)
char cpage[20];sprintf(cpage, "%d", page);
QString nurl = QString::fromAscii("recoll://search/query?q=") +
query + "&qtp=" + opt + "&p=" + cpage;
redirection(KUrl(nurl));
redirection(QUrl(nurl));
goto out;
}
#endif
@ -298,7 +303,7 @@ void RecollProtocol::get(const KUrl& url)
goto out;
}
error(KIO::ERR_SLAVE_DEFINED, "Unrecognized URL or internal error");
error(KIO::ERR_SLAVE_DEFINED, u8s2qs("Unrecognized URL or internal error"));
out:
finished();
}
@ -306,7 +311,7 @@ void RecollProtocol::get(const KUrl& url)
// Execute Recoll search, and set the docsource
bool RecollProtocol::doSearch(const QueryDesc& qd)
{
kDebug() << "query" << qd.query << "opt" << qd.opt;
qDebug() << "RecollProtocol::doSearch:query" << qd.query << "opt" << qd.opt;
m_query = qd;
char opt = qd.opt.isEmpty() ? 'l' : qd.opt.toUtf8().at(0);
@ -328,7 +333,7 @@ bool RecollProtocol::doSearch(const QueryDesc& qd)
}
if (!sd) {
m_reason = "Internal Error: cant build search";
error(KIO::ERR_SLAVE_DEFINED, m_reason.c_str());
error(KIO::ERR_SLAVE_DEFINED, u8s2qs(m_reason));
return false;
}
@ -337,14 +342,14 @@ bool RecollProtocol::doSearch(const QueryDesc& qd)
query->setCollapseDuplicates(prefs.collapseDuplicates);
if (!query->setQuery(sdata)) {
m_reason = "Query execute failed. Invalid query or syntax error?";
error(KIO::ERR_SLAVE_DEFINED, m_reason.c_str());
error(KIO::ERR_SLAVE_DEFINED, u8s2qs(m_reason));
return false;
}
DocSequenceDb *src =
new DocSequenceDb(STD_SHARED_PTR<Rcl::Query>(query), "Query results", sdata);
if (src == 0) {
error(KIO::ERR_SLAVE_DEFINED, "Can't build result sequence");
error(KIO::ERR_SLAVE_DEFINED, u8s2qs("Can't build result sequence"));
return false;
}
m_source = STD_SHARED_PTR<DocSequence>(src);
@ -354,28 +359,19 @@ bool RecollProtocol::doSearch(const QueryDesc& qd)
return true;
}
// Note: KDE_EXPORT is actually needed on Unix when building with
// cmake. Says something like __attribute__(visibility(defautl))
// (cmake apparently sets all symbols to not exported)
extern "C" {KDE_EXPORT int kdemain(int argc, char **argv);}
int kdemain(int argc, char **argv)
{
#ifdef KDE_VERSION_3
KInstance instance("kio_recoll");
#else
KComponentData instance("kio_recoll");
#endif
kDebug() << "*** starting kio_recoll " << endl;
QCoreApplication::setApplicationName("kio_recoll");
qDebug() << "*** starting kio_recoll ";
if (argc != 4) {
kDebug() << "Usage: kio_recoll proto dom-socket1 dom-socket2\n" << endl;
qDebug() << "Usage: kio_recoll proto dom-socket1 dom-socket2\n";
exit(-1);
}
RecollProtocol slave(argv[2], argv[3]);
slave.dispatchLoop();
kDebug() << "kio_recoll Done" << endl;
qDebug() << "kio_recoll Done";
return 0;
}

View File

@ -18,20 +18,16 @@
*/
#include <string>
using std::string;
#include <qglobal.h>
#include <qstring.h>
#include <QString>
#include <QUrl>
#include <kurl.h>
#include <kio/global.h>
#include <kio/slavebase.h>
#include <kdeversion.h>
#include "rclconfig.h"
#include "rcldb.h"
#include "reslistpager.h"
#include "docseq.h"
#include "reslistpager.h"
#include MEMORY_INCLUDE
class RecollProtocol;
@ -42,14 +38,14 @@ public:
RecollKioPager() : m_parent(0) {}
void setParent(RecollProtocol *proto) {m_parent = proto;}
virtual bool append(const string& data);
virtual bool append(const string& data, int, const Rcl::Doc&)
virtual bool append(const std::string& data);
virtual bool append(const std::string& data, int, const Rcl::Doc&)
{return append(data);}
virtual string detailsLink();
virtual const string &parFormat();
virtual string nextUrl();
virtual string prevUrl();
virtual string pageTop();
virtual std::string detailsLink();
virtual const std::string &parFormat();
virtual std::string nextUrl();
virtual std::string prevUrl();
virtual std::string pageTop();
private:
RecollProtocol *m_parent;
@ -71,7 +67,7 @@ public:
// and tell what we should do with it
class UrlIngester {
public:
UrlIngester(RecollProtocol *p, const KUrl& url);
UrlIngester(RecollProtocol *p, const QUrl& url);
enum RootEntryType {UIRET_NONE, UIRET_ROOT, UIRET_HELP, UIRET_SEARCH};
bool isRootEntry(RootEntryType *tp) {
if (m_type != UIMT_ROOTENTRY) return false;
@ -110,7 +106,6 @@ private:
MyType m_type;
};
/**
* A KIO slave to execute and display Recoll searches.
*
@ -140,14 +135,12 @@ class RecollProtocol : public KIO::SlaveBase {
public:
RecollProtocol(const QByteArray &pool, const QByteArray &app );
virtual ~RecollProtocol();
virtual void mimetype(const KUrl& url);
virtual void get(const KUrl& url);
virtual void mimetype(const QUrl& url);
virtual void get(const QUrl& url);
// The directory mode is not available with KDE 4.0, I could find
// no way to avoid crashing kdirmodel
#if KDE_IS_VERSION(4,1,0)
virtual void stat(const KUrl & url);
virtual void listDir(const KUrl& url);
#endif
virtual void stat(const QUrl & url);
virtual void listDir(const QUrl& url);
static RclConfig *o_rclconfig;
@ -155,23 +148,24 @@ class RecollProtocol : public KIO::SlaveBase {
friend class UrlIngester;
private:
bool maybeOpenDb(string& reason);
bool URLToQuery(const KUrl &url, QString& q, QString& opt, int *page=0);
bool maybeOpenDb(std::string& reason);
bool URLToQuery(const QUrl &url, QString& q, QString& opt, int *page=0);
bool doSearch(const QueryDesc& qd);
void searchPage();
void queryDetails();
string makeQueryUrl(int page, bool isdet = false);
std::string makeQueryUrl(int page, bool isdet = false);
bool syncSearch(const QueryDesc& qd);
void htmlDoSearch(const QueryDesc& qd);
void showPreview(const Rcl::Doc& doc);
bool isRecollResult(const KUrl &url, int *num, QString* q);
bool isRecollResult(const QUrl &url, int *num, QString* q);
bool m_initok;
Rcl::Db *m_rcldb;
string m_reason;
std::string m_reason;
bool m_alwaysdir;
string m_stemlang; // english by default else env[RECOLL_KIO_STEMLANG]
// english by default else env[RECOLL_KIO_STEMLANG]
std::string m_stemlang;
// 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
@ -186,6 +180,13 @@ class RecollProtocol : public KIO::SlaveBase {
QueryDesc m_query;
};
extern "C" {int kdemain(int, char**);}
extern "C" { __attribute__ ((visibility("default"))) int
kdemain(int argc, char **argv);}
inline QString u8s2qs(const string& s)
{
return QString::fromUtf8(s.c_str());
}
#endif // _RECOLL_H

View File

@ -1,11 +1,11 @@
[Protocol]
exec=kio_recoll
protocol=recoll
Icon=recoll
input=none
output=filesystem
listing=Name,Type, URL
reading=true
defaultMimeType=text/html
Icon=recoll
Class=:local
URIMode=rawuri
defaultMimeType=text/html