Provide default view properties for system-places

For the "Recently Accessed"-places and "Search For"-places like
documents, images, audio-files and videos proper default properties
are created now (e.g. previews and images-sizes are shown when
searching for "images" etc).
This commit is contained in:
Peter Penz 2012-05-16 23:11:56 +02:00
parent 2fd31c8a95
commit 3e2cf9721b
6 changed files with 248 additions and 182 deletions

View file

@ -23,6 +23,8 @@
#include "placesitemmodel.h"
#include "dolphin_generalsettings.h"
#include <KBookmark>
#include <KBookmarkGroup>
#include <KBookmarkManager>
@ -44,8 +46,17 @@
#include <Solid/StorageAccess>
#include <Solid/StorageDrive>
#include <views/dolphinview.h>
#include <views/viewproperties.h>
#ifdef HAVE_NEPOMUK
#include <Nepomuk/ResourceManager>
#include <Nepomuk/Query/ComparisonTerm>
#include <Nepomuk/Query/LiteralTerm>
#include <Nepomuk/Query/Query>
#include <Nepomuk/Query/ResourceTypeTerm>
#include <Nepomuk/Vocabulary/NFO>
#include <Nepomuk/Vocabulary/NIE>
#endif
namespace {
@ -302,6 +313,18 @@ void PlacesItemModel::requestTeardown(int index)
}
}
KUrl PlacesItemModel::convertedUrl(const KUrl& url)
{
KUrl newUrl = url;
if (url.protocol() == QLatin1String("timeline")) {
newUrl = createTimelineUrl(url);
} else if (url.protocol() == QLatin1String("search")) {
newUrl = createSearchUrl(url);
}
return newUrl;
}
void PlacesItemModel::onItemInserted(int index)
{
const PlacesItem* insertedItem = placesItem(index);
@ -583,23 +606,7 @@ void PlacesItemModel::loadBookmarks()
// bookmarks.
foreach (const SystemBookmarkData& data, m_systemBookmarks) {
if (missingSystemBookmarks.contains(data.url)) {
KBookmark bookmark = PlacesItem::createBookmark(m_bookmarkManager,
data.text,
data.url,
data.icon);
const QString protocol = data.url.protocol();
if (protocol == QLatin1String("timeline") || protocol == QLatin1String("search")) {
// As long as the KFilePlacesView from kdelibs is available, the system-bookmarks
// for "Recently Accessed" and "Search For" should be a setting available only
// in the Places Panel (see description of AppNamePrefix for more details).
const QString appName = KGlobal::mainComponent().componentName() + AppNamePrefix;
bookmark.setMetaDataItem("OnlyInApp", appName);
}
PlacesItem* item = new PlacesItem(bookmark);
item->setSystemItem(true);
PlacesItem* item = createSystemPlacesItem(data);
switch (item->groupType()) {
case PlacesItem::PlacesType: placesItems.append(item); break;
case PlacesItem::RecentlyAccessedType: recentlyAccessedItems.append(item); break;
@ -653,6 +660,61 @@ bool PlacesItemModel::acceptBookmark(const KBookmark& bookmark) const
return (udi.isEmpty() && allowedHere) || deviceAvailable;
}
PlacesItem* PlacesItemModel::createSystemPlacesItem(const SystemBookmarkData& data)
{
KBookmark bookmark = PlacesItem::createBookmark(m_bookmarkManager,
data.text,
data.url,
data.icon);
const QString protocol = data.url.protocol();
if (protocol == QLatin1String("timeline") || protocol == QLatin1String("search")) {
// As long as the KFilePlacesView from kdelibs is available, the system-bookmarks
// for "Recently Accessed" and "Search For" should be a setting available only
// in the Places Panel (see description of AppNamePrefix for more details).
const QString appName = KGlobal::mainComponent().componentName() + AppNamePrefix;
bookmark.setMetaDataItem("OnlyInApp", appName);
}
PlacesItem* item = new PlacesItem(bookmark);
item->setSystemItem(true);
// Create default view-properties for all "Search For" and "Recently Accessed" bookmarks
// in case if the user has not already created custom view-properties for a corresponding
// query yet.
const bool createDefaultViewProperties = (item->groupType() == PlacesItem::SearchForType ||
item->groupType() == PlacesItem::RecentlyAccessedType) &&
!GeneralSettings::self()->globalViewProps();
if (createDefaultViewProperties) {
ViewProperties props(convertedUrl(data.url));
if (!props.exist()) {
const QString path = data.url.path();
if (path == QLatin1String("/documents")) {
props.setViewMode(DolphinView::DetailsView);
props.setPreviewsShown(false);
props.setVisibleRoles(QList<QByteArray>() << "text" << "path");
} else if (path == QLatin1String("/images")) {
props.setViewMode(DolphinView::IconsView);
props.setPreviewsShown(true);
props.setVisibleRoles(QList<QByteArray>() << "text" << "imageSize");
} else if (path == QLatin1String("/audio")) {
props.setViewMode(DolphinView::DetailsView);
props.setPreviewsShown(false);
props.setVisibleRoles(QList<QByteArray>() << "text" << "artist" << "album");
} else if (path == QLatin1String("/videos")) {
props.setViewMode(DolphinView::IconsView);
props.setPreviewsShown(true);
props.setVisibleRoles(QList<QByteArray>() << "text");
} else if (data.url.protocol() == "timeline") {
props.setViewMode(DolphinView::DetailsView);
props.setVisibleRoles(QList<QByteArray>() << "text" << "date");
}
}
}
return item;
}
void PlacesItemModel::createSystemBookmarks()
{
Q_ASSERT(m_systemBookmarks.isEmpty());
@ -804,6 +866,88 @@ bool PlacesItemModel::equalBookmarkIdentifiers(const KBookmark& b1, const KBookm
}
}
KUrl PlacesItemModel::createTimelineUrl(const KUrl& url)
{
// TODO: Clarify with the Nepomuk-team whether it makes sense
// provide default-timeline-URLs like 'yesterday', 'this month'
// and 'last month'.
KUrl timelineUrl;
const QString path = url.pathOrUrl();
if (path.endsWith("yesterday")) {
const QDate date = QDate::currentDate().addDays(-1);
const int year = date.year();
const int month = date.month();
const int day = date.day();
timelineUrl = "timeline:/" + timelineDateString(year, month) +
'/' + timelineDateString(year, month, day);
} else if (path.endsWith("thismonth")) {
const QDate date = QDate::currentDate();
timelineUrl = "timeline:/" + timelineDateString(date.year(), date.month());
} else if (path.endsWith("lastmonth")) {
const QDate date = QDate::currentDate().addMonths(-1);
timelineUrl = "timeline:/" + timelineDateString(date.year(), date.month());
} else {
Q_ASSERT(path.endsWith("today"));
timelineUrl= url;
}
return timelineUrl;
}
QString PlacesItemModel::timelineDateString(int year, int month, int day)
{
QString date = QString::number(year) + '-';
if (month < 10) {
date += '0';
}
date += QString::number(month);
if (day >= 1) {
date += '-';
if (day < 10) {
date += '0';
}
date += QString::number(day);
}
return date;
}
KUrl PlacesItemModel::createSearchUrl(const KUrl& url)
{
KUrl searchUrl;
#ifdef HAVE_NEPOMUK
const QString path = url.pathOrUrl();
if (path.endsWith("documents")) {
searchUrl = searchUrlForTerm(Nepomuk::Query::ResourceTypeTerm(Nepomuk::Vocabulary::NFO::Document()));
} else if (path.endsWith("images")) {
searchUrl = searchUrlForTerm(Nepomuk::Query::ResourceTypeTerm(Nepomuk::Vocabulary::NFO::Image()));
} else if (path.endsWith("audio")) {
searchUrl = searchUrlForTerm(Nepomuk::Query::ComparisonTerm(Nepomuk::Vocabulary::NIE::mimeType(),
Nepomuk::Query::LiteralTerm("audio")));
} else if (path.endsWith("videos")) {
searchUrl = searchUrlForTerm(Nepomuk::Query::ComparisonTerm(Nepomuk::Vocabulary::NIE::mimeType(),
Nepomuk::Query::LiteralTerm("video")));
} else {
Q_ASSERT(false);
}
#else
Q_UNUSED(url);
#endif
return searchUrl;
}
#ifdef HAVE_NEPOMUK
KUrl PlacesItemModel::searchUrlForTerm(const Nepomuk::Query::Term& term)
{
const Nepomuk::Query::Query query(term);
return query.toSearchUrl();
}
#endif
#ifdef PLACESITEMMODEL_DEBUG
void PlacesItemModel::showModelState()
{

View file

@ -37,6 +37,16 @@ class PlacesItem;
class QAction;
class QTimer;
#ifdef HAVE_NEPOMUK
namespace Nepomuk
{
namespace Query
{
class Term;
}
}
#endif
// #define PLACESITEMMODEL_DEBUG
/**
@ -95,6 +105,14 @@ public:
void requestEject(int index);
void requestTeardown(int index);
/**
* @return Converts the URL, which contains "virtual" URLs for system-items like
* "search:/documents" into a Nepomuk-Query-URL that will be handled by
* the corresponding IO-slave. Virtual URLs for bookmarks are used to
* be independent from internal format changes.
*/
static KUrl convertedUrl(const KUrl& url);
signals:
void errorMessage(const QString& message);
@ -124,6 +142,8 @@ private slots:
void saveBookmarks();
private:
struct SystemBookmarkData;
/**
* Loads the bookmarks from the bookmark-manager and creates items for
* the model or moves hidden items to m_bookmarkedItems.
@ -137,6 +157,14 @@ private:
*/
bool acceptBookmark(const KBookmark& bookmark) const;
/**
* Creates a PlacesItem for a system-bookmark:
* - PlacesItem::isSystemItem() will return true
* - Default view-properties will be created for "Search For" items
* The item is not inserted to the model yet.
*/
PlacesItem* createSystemPlacesItem(const SystemBookmarkData& data);
/**
* Creates system bookmarks that are shown per default and can
* only be hidden but not removed. The result will be stored
@ -171,6 +199,34 @@ private:
*/
static bool equalBookmarkIdentifiers(const KBookmark& b1, const KBookmark& b2);
/**
* @return URL using the timeline-protocol for searching (see convertedUrl()).
*/
static KUrl createTimelineUrl(const KUrl& url);
/**
* Helper method for createTimelineUrl().
* @return String that represents a date-path in the format that
* the timeline-protocol expects.
*/
static QString timelineDateString(int year, int month, int day = 0);
/**
* @return URL that can be listed by KIO and results in searching
* for a given term. The URL \a url represents a places-internal
* URL like e.g. "search:/documents" (see convertedUrl()).
*/
static KUrl createSearchUrl(const KUrl& url);
#ifdef HAVE_NEPOMUK
/**
* Helper method for createSearchUrl().
* @return URL that can be listed by KIO and results in searching
* for the given term.
*/
static KUrl searchUrlForTerm(const Nepomuk::Query::Term& term);
#endif
#ifdef PLACESITEMMODEL_DEBUG
void showModelState();
#endif

View file

@ -47,15 +47,6 @@
#include <QVBoxLayout>
#include <QShowEvent>
#ifdef HAVE_NEPOMUK
#include <Nepomuk/Query/ComparisonTerm>
#include <Nepomuk/Query/LiteralTerm>
#include <Nepomuk/Query/Query>
#include <Nepomuk/Query/ResourceTypeTerm>
#include <Nepomuk/Vocabulary/NFO>
#include <Nepomuk/Vocabulary/NIE>
#endif
PlacesPanel::PlacesPanel(QWidget* parent) :
Panel(parent),
m_controller(0),
@ -117,7 +108,7 @@ void PlacesPanel::slotItemActivated(int index)
{
const KUrl url = m_model->data(index).value("url").value<KUrl>();
if (!url.isEmpty()) {
emit placeActivated(convertedUrl(url));
emit placeActivated(PlacesItemModel::convertedUrl(url));
}
}
@ -125,7 +116,7 @@ void PlacesPanel::slotItemMiddleClicked(int index)
{
const KUrl url = m_model->data(index).value("url").value<KUrl>();
if (!url.isEmpty()) {
emit placeMiddleClicked(convertedUrl(url));
emit placeMiddleClicked(PlacesItemModel::convertedUrl(url));
}
}
@ -368,98 +359,4 @@ void PlacesPanel::selectClosestItem()
selectionManager->setSelected(index);
}
KUrl PlacesPanel::convertedUrl(const KUrl& url)
{
KUrl newUrl = url;
if (url.protocol() == QLatin1String("timeline")) {
newUrl = createTimelineUrl(url);
} else if (url.protocol() == QLatin1String("search")) {
newUrl = createSearchUrl(url);
}
return newUrl;
}
KUrl PlacesPanel::createTimelineUrl(const KUrl& url)
{
// TODO: Clarify with the Nepomuk-team whether it makes sense
// provide default-timeline-URLs like 'yesterday', 'this month'
// and 'last month'.
KUrl timelineUrl;
const QString path = url.pathOrUrl();
if (path.endsWith("yesterday")) {
const QDate date = QDate::currentDate().addDays(-1);
const int year = date.year();
const int month = date.month();
const int day = date.day();
timelineUrl = "timeline:/" + timelineDateString(year, month) +
'/' + timelineDateString(year, month, day);
} else if (path.endsWith("thismonth")) {
const QDate date = QDate::currentDate();
timelineUrl = "timeline:/" + timelineDateString(date.year(), date.month());
} else if (path.endsWith("lastmonth")) {
const QDate date = QDate::currentDate().addMonths(-1);
timelineUrl = "timeline:/" + timelineDateString(date.year(), date.month());
} else {
Q_ASSERT(path.endsWith("today"));
timelineUrl= url;
}
return timelineUrl;
}
QString PlacesPanel::timelineDateString(int year, int month, int day)
{
QString date = QString::number(year) + '-';
if (month < 10) {
date += '0';
}
date += QString::number(month);
if (day >= 1) {
date += '-';
if (day < 10) {
date += '0';
}
date += QString::number(day);
}
return date;
}
KUrl PlacesPanel::createSearchUrl(const KUrl& url)
{
KUrl searchUrl;
#ifdef HAVE_NEPOMUK
const QString path = url.pathOrUrl();
if (path.endsWith("documents")) {
searchUrl = searchUrlForTerm(Nepomuk::Query::ResourceTypeTerm(Nepomuk::Vocabulary::NFO::Document()));
} else if (path.endsWith("images")) {
searchUrl = searchUrlForTerm(Nepomuk::Query::ResourceTypeTerm(Nepomuk::Vocabulary::NFO::Image()));
} else if (path.endsWith("audio")) {
searchUrl = searchUrlForTerm(Nepomuk::Query::ComparisonTerm(Nepomuk::Vocabulary::NIE::mimeType(),
Nepomuk::Query::LiteralTerm("audio")));
} else if (path.endsWith("videos")) {
searchUrl = searchUrlForTerm(Nepomuk::Query::ComparisonTerm(Nepomuk::Vocabulary::NIE::mimeType(),
Nepomuk::Query::LiteralTerm("video")));
} else {
Q_ASSERT(false);
}
#else
Q_UNUSED(url);
#endif
return searchUrl;
}
#ifdef HAVE_NEPOMUK
KUrl PlacesPanel::searchUrlForTerm(const Nepomuk::Query::Term& term)
{
const Nepomuk::Query::Query query(term);
return query.toSearchUrl();
}
#endif
#include "placespanel.moc"

View file

@ -21,8 +21,6 @@
#ifndef PLACESPANEL_H
#define PLACESPANEL_H
#include <config-nepomuk.h>
#include <KUrl>
#include <panels/panel.h>
@ -31,16 +29,6 @@ class PlacesItemEditDialog;
class PlacesItem;
class PlacesItemModel;
#ifdef HAVE_NEPOMUK
namespace Nepomuk
{
namespace Query
{
class Term;
}
}
#endif
/**
* @brief Combines bookmarks and mounted devices as list.
*/
@ -80,42 +68,6 @@ private:
*/
void selectClosestItem();
/**
* @return Converts the URL, which contains "virtual" URLs for system-items like
* "search:/documents" into a Nepomuk-Query-URL that will be handled by
* the corresponding IO-slave. Virtual URLs for bookmarks are used to
* be independent from internal format changes.
*/
static KUrl convertedUrl(const KUrl& url);
/**
* @return URL using the timeline-protocol for searching (see convertedUrl()).
*/
static KUrl createTimelineUrl(const KUrl& url);
/**
* Helper method for createTimelineUrl().
* @return String that represents a date-path in the format that
* the timeline-protocol expects.
*/
static QString timelineDateString(int year, int month, int day = 0);
/**
* @return URL that can be listed by KIO and results in searching
* for a given term. The URL \a url represents a places-internal
* URL like e.g. "search:/documents" (see convertedUrl()).
*/
static KUrl createSearchUrl(const KUrl& url);
#ifdef HAVE_NEPOMUK
/**
* Helper method for createSearchUrl().
* @return URL that can be listed by KIO and results in searching
* for the given term.
*/
static KUrl searchUrlForTerm(const Nepomuk::Query::Term& term);
#endif
private:
KItemListController* m_controller;
PlacesItemModel* m_model;

View file

@ -42,6 +42,9 @@ namespace {
// the details view as customized by the user. See
// ViewProperties::visibleRoles() for more information.
const char* CustomizedDetailsString = "CustomizedDetails";
// Filename that is used for storing the properties
const char* ViewPropertiesFileName = ".directory";
}
ViewProperties::ViewProperties(const KUrl& url) :
@ -78,13 +81,13 @@ ViewProperties::ViewProperties(const KUrl& url) :
m_filePath = destinationDir("remote") + m_filePath;
}
const QString file = m_filePath + QDir::separator() + QLatin1String(".directory");
const QString file = m_filePath + QDir::separator() + ViewPropertiesFileName;
m_node = new ViewPropertySettings(KSharedConfig::openConfig(file));
// If the .directory file does not exist or the timestamp is too old,
// use default values instead.
const bool useDefaultProps = (!useGlobalViewProps || useDetailsViewWithPath) &&
(!QFileInfo(file).exists() ||
(!QFile::exists(file) ||
(m_node->timestamp() < settings->viewPropsTimestamp()));
if (useDefaultProps) {
if (useDetailsViewWithPath) {
@ -353,11 +356,10 @@ void ViewProperties::save()
m_changedProps = false;
}
KUrl ViewProperties::mirroredDirectory()
bool ViewProperties::exist() const
{
QString basePath = KGlobal::mainComponent().componentName();
basePath.append("/view_properties/");
return KUrl(KStandardDirs::locateLocal("data", basePath));
const QString file = m_filePath + QDir::separator() + ViewPropertiesFileName;
return QFile::exists(file);
}
QString ViewProperties::destinationDir(const QString& subDir) const
@ -453,3 +455,10 @@ QString ViewProperties::directoryHashForUrl(const KUrl& url)
hashString.replace('/', '-');
return hashString;
}
KUrl ViewProperties::mirroredDirectory()
{
QString basePath = KGlobal::mainComponent().componentName();
basePath.append("/view_properties/");
return KUrl(KStandardDirs::locateLocal("data", basePath));
}

View file

@ -118,13 +118,12 @@ public:
void save();
/**
* Returns the URL of the directory, where the mirrored view properties
* are stored into. Mirrored view properties are used if:
* - there is no write access for storing the view properties into
* the original directory
* - for non local directories
* @return True if properties for the given URL exist:
* As soon as the properties for an URL have been saved with
* ViewProperties::save(), true will be returned. If false is
* returned, the default view-properties are used.
*/
static KUrl mirroredDirectory();
bool exist() const;
private:
/**
@ -165,6 +164,15 @@ private:
*/
static QString directoryHashForUrl(const KUrl& url);
/**
* Returns the URL of the directory, where the mirrored view properties
* are stored into. Mirrored view properties are used if:
* - there is no write access for storing the view properties into
* the original directory
* - for non local directories
*/
static KUrl mirroredDirectory();
Q_DISABLE_COPY(ViewProperties)
private: