67
68
uds.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR );
68
69
uds.insert( KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1( "inode/directory" ) );
69
70
uds.insert( KIO::UDSEntry::UDS_ICON_OVERLAY_NAMES, QLatin1String( "nepomuk" ) );
70
uds.insert( KIO::UDSEntry::UDS_NAME, Nepomuk::resourceUriToUdsName( url ) );
71
uds.insert( KIO::UDSEntry::UDS_DISPLAY_TYPE, i18n( "Query folder" ) );
72
uds.insert( KIO::UDSEntry::UDS_NAME, Nepomuk::Query::Query::titleFromQueryUrl( url ) );
71
73
uds.insert( KIO::UDSEntry::UDS_DISPLAY_NAME, Nepomuk::Query::Query::titleFromQueryUrl( url ) );
72
uds.insert( KIO::UDSEntry::UDS_URL, url.url() );
74
if ( url.hasQueryItem( QLatin1String( "resource" ) ) ) {
75
Nepomuk::addGenericNepomukResourceData( Nepomuk::Resource( KUrl( url.queryItemValue( QLatin1String( "resource" ) ) ) ), uds );
77
Nepomuk::Query::Query query = Nepomuk::Query::Query::fromQueryUrl( url );
78
if ( query.isValid() )
79
uds.insert( KIO::UDSEntry::UDS_NEPOMUK_QUERY, query.toString() );
78
* Empty if the path only contains the query.
80
QString fileNameFromUrl( const KUrl& url ) {
81
if ( url.hasQueryItem( QLatin1String( "sparql" ) ) ||
82
url.hasQueryItem( QLatin1String( "query" ) ) ||
83
url.hasQueryItem( QLatin1String( "encodedquery" ) ) ||
84
url.directory() != QLatin1String( "/" ) ) {
85
return url.fileName();
92
83
bool isRootUrl( const KUrl& url ) {
93
84
const QString path = url.path(KUrl::RemoveTrailingSlash);
94
85
return( !url.hasQuery() &&
95
86
( path.isEmpty() || path == QLatin1String("/") ) );
89
// a query folder has a non-empty path with a single section and a query parameter
90
// Example: nepomuksearch:/My Query?query=foobar
91
bool isQueryFolder( const KUrl& url ) {
92
return( url.hasQuery() &&
93
url.directory() == QLatin1String("/") );
96
// Legacy query URLs look like: nepomuksearch:/?query=xyz&title=foobar
97
// i.e. an empty path and a query, new URLs have their title as path
98
bool isLegacyQueryUrl( const KUrl& url ) {
99
const QString path = url.path(KUrl::RemoveTrailingSlash);
100
return( url.hasQuery() &&
101
( path.isEmpty() || path == QLatin1String("/") ) );
104
KUrl convertLegacyQueryUrl( const KUrl& url ) {
105
KUrl newUrl(QLatin1String("nepomuksearch:/") + Nepomuk::Query::Query::titleFromQueryUrl(url));
106
Nepomuk::Query::Query query = Nepomuk::Query::Query::fromQueryUrl(url);
108
newUrl.addQueryItem(QLatin1String("encodedquery"), query.toString());
110
newUrl.addQueryItem(QLatin1String("sparql"), Nepomuk::Query::Query::sparqlFromQueryUrl(url));
114
Nepomuk::Query::Query rootQuery() {
115
KConfig config( "kio_nepomuksearchrc" );
116
QString queryStr = config.group( "General" ).readEntry( "Root query", QString() );
117
Nepomuk::Query::Query query;
118
if ( queryStr.isEmpty() )
119
query = Nepomuk::lastModifiedFilesQuery();
121
query = Nepomuk::Query::Query::fromString( queryStr );
122
query.setLimit( config.group( "General" ).readEntry( "Root query limit", 10 ) );
97
125
const int s_historyMax = 10;
164
// list the root folder
136
165
if ( isRootUrl( url ) ) {
169
// backwards compatibility with pre-4.6 query URLs
170
else if( isLegacyQueryUrl( url ) ) {
171
redirection( convertLegacyQueryUrl(url) );
175
// list the actual query folders
176
else if( isQueryFolder( url ) ) {
140
177
if ( !ensureNepomukRunning(false) ) {
141
178
// we defer the listing to later when Nepomuk is up and running
142
179
listEntry( KIO::UDSEntry(), true);
145
182
else if ( SearchFolder* folder = getQueryFolder( url ) ) {
183
updateQueryUrlHistory( url );
147
185
listEntry( KIO::UDSEntry(), true );
227
// the root url is always a folder
184
228
if ( isRootUrl( url ) ) {
185
229
mimeType( QString::fromLatin1( "inode/directory" ) );
188
else if ( url.directory() == QLatin1String( "/" ) ) {
233
// Query result URLs in the root folder do not include a query
234
// while all query folders do. The latter ones are what we check
236
else if ( url.directory() == QLatin1String( "/" ) &&
189
238
mimeType( QString::fromLatin1( "inode/directory" ) );
242
// results are forwarded
193
244
ForwardingSlaveBase::mimetype( url );
210
262
uds.insert( KIO::UDSEntry::UDS_ICON_NAME, QString::fromLatin1( "nepomuk" ) );
211
263
uds.insert( KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR );
212
264
uds.insert( KIO::UDSEntry::UDS_MIME_TYPE, QString::fromLatin1( "inode/directory" ) );
265
uds.insert( KIO::UDSEntry::UDS_NEPOMUK_QUERY, rootQuery().toString() );
214
267
statEntry( uds );
217
else if ( fileNameFromUrl( url ).isEmpty() ) {
272
else if( isQueryFolder( url ) ) {
218
273
kDebug() << "Stat search folder" << url;
219
274
statEntry( statSearchFolder( url ) );
278
// results are forwarded
223
280
kDebug() << "Stat forward" << url;
224
281
ForwardingSlaveBase::stat(url);
249
void Nepomuk::SearchProtocol::prepareUDSEntry( KIO::UDSEntry&, bool ) const
301
void Nepomuk::SearchProtocol::prepareUDSEntry( KIO::UDSEntry& uds, bool listing ) const
251
// we already handle UDS_URL in SearchFolder. No need to do anything more here.
303
// for performace reasons we do encode the result's resource URI in the UDS_NAME
304
// Otherwise we would have to re-query for each stat operation
305
// This is simple for "direct" query results (SearchFolder takes care of that)
306
// but a bit harder for items in results that are folders.
307
// In the latter case we get the parent folder's resource URI (which is encoded in
308
// the UDS_NAME) and append the filename.
310
// Also note that results listed via a SearchFolder will never go through this method
311
// since they are listed directly and not via a forward. Forwarding will only happen
312
// for search results that are folders and for non-listing operations.
314
kDebug() << requestedUrl() << processedUrl() << uds.stringValue(KIO::UDSEntry::UDS_NAME);
315
const QString name = uds.stringValue(KIO::UDSEntry::UDS_NAME);
316
if(name != QLatin1String(".") && name != QLatin1String("..")) {
317
// let the ForwardingSlaveBase create UDS_LOCAL_PATH and mimetype entries
318
// This call depends on the original UDS_NAME which we change below. Thus, it
319
// is important to let ForwardingSlaveBase do its thing before we start ours
320
ForwardingSlaveBase::prepareUDSEntry( uds, listing );
322
// encode the URL in the UDS_NAME to prevent a re-query in stat and friends
323
KUrl resourceUrl(processedUrl());
325
resourceUrl.addPath(name);
327
uds.insert(KIO::UDSEntry::UDS_NAME, Nepomuk::resourceUriToUdsName(resourceUrl));
328
if ( !uds.contains( KIO::UDSEntry::UDS_DISPLAY_NAME ) ) {
329
uds.insert(KIO::UDSEntry::UDS_DISPLAY_NAME, name);
332
// There is a trade-off between using UDS_TARGET_URL or not. The advantage is that we get proper
333
// file names in opening applications and non-KDE apps can handle the URLs properly. The downside
334
// is that we lose the context information, i.e. query results cannot be browsed in the opening
335
// application. We decide pro-filenames and pro-non-kde-apps here.
336
if( resourceUrl.isLocalFile() ) {
338
Query::FileQuery query;
339
query.addIncludeFolder( resourceUrl );
340
uds.insert( KIO::UDSEntry::UDS_NEPOMUK_QUERY, query.toString() );
343
uds.insert( KIO::UDSEntry::UDS_TARGET_URL, resourceUrl.url() );
264
367
Nepomuk::SearchFolder* Nepomuk::SearchProtocol::getQueryFolder( const KUrl& url )
266
// this is necessary to properly handle user queries which are encoded in the filename in
267
// statSearchFolder(). This is necessary for cases in which UDS_URL is ignored like in
268
// KUrlNavigator's popup menus
269
KUrl normalizedUrl = Nepomuk::udsNameToResourceUri( url.fileName() );
270
if ( normalizedUrl.protocol() != QLatin1String( "nepomuksearch" ) ) {
274
// here we strip off the entry's name since that is not part of the query URL
275
if ( url.hasQuery() ) {
276
normalizedUrl.setPath( QLatin1String( "/" ) );
278
else if ( url.directory() != QLatin1String( "/" ) ) {
279
normalizedUrl.setPath( QLatin1String( "/" ) + url.path().section( '/', 0, 0 ) );
282
SearchFolder* folder = new SearchFolder( normalizedUrl, this );
369
return new SearchFolder( url, this );
373
void Nepomuk::SearchProtocol::updateQueryUrlHistory( const KUrl& url )
376
// if the url is already in the history update its timestamp
377
// otherwise remove the last item if we reached the max and then
378
// add the url along with its timestamp
380
KSharedConfigPtr cfg = KSharedConfig::openConfig( "kio_nepomuksearchrc" );
381
KConfigGroup grp = cfg->group( "Last Queries" );
384
const int cnt = grp.readEntry( "count", 0 );
385
QList<QPair<KUrl, QDateTime> > entries;
386
for ( int i = 0; i < cnt; ++i ) {
387
KUrl u = grp.readEntry( QString::fromLatin1( "query_%1_url" ).arg( i ), QString() );
388
QDateTime t = grp.readEntry( QString::fromLatin1( "query_%1_timestamp" ).arg( i ), QDateTime() );
393
while ( entries.count() > pos &&
394
entries[pos].second < t ) {
397
entries.insert( pos, qMakePair( u, t ) );
400
if ( entries.count() >= s_historyMax ) {
401
entries.removeFirst();
403
entries.append( qMakePair( url, QDateTime::currentDateTime() ) );
407
grp = cfg->group( "Last Queries" );
409
for ( int i = 0; i < entries.count(); ++i ) {
410
KUrl u = entries[i].first;
411
QDateTime t = entries[i].second;
412
grp.writeEntry( QString::fromLatin1( "query_%1_url" ).arg( i ), u.url() );
413
grp.writeEntry( QString::fromLatin1( "query_%1_timestamp" ).arg( i ), t );
415
grp.writeEntry( QLatin1String( "count" ), entries.count() );
442
void Nepomuk::SearchProtocol::listUserQueries()
444
UserQueryUrlList userQueries;
445
Q_FOREACH( const KUrl& url, userQueries ) {
446
KIO::UDSEntry uds = statSearchFolder( url );
447
uds.insert( KIO::UDSEntry::UDS_DISPLAY_TYPE, i18n( "Saved Query" ) );
448
listEntry( uds, false );
451
void Nepomuk::SearchProtocol::listLastQueries()
453
KSharedConfigPtr cfg = KSharedConfig::openConfig( "kio_nepomuksearchrc" );
454
KConfigGroup grp = cfg->group( "Last Queries" );
457
const int cnt = grp.readEntry( "count", 0 );
458
QList<QPair<KUrl, QDateTime> > entries;
459
for ( int i = 0; i < cnt; ++i ) {
460
KUrl u = grp.readEntry( QString::fromLatin1( "query_%1_url" ).arg( i ), QString() );
461
QDateTime t = grp.readEntry( QString::fromLatin1( "query_%1_timestamp" ).arg( i ), QDateTime() );
462
if ( !u.isEmpty() && t.isValid() )
463
listEntry( statLastQuery( u, t ), false );
466
listEntry( KIO::UDSEntry(), true );
306
471
#include "kio_nepomuksearch.moc"