#include "placesitemmodel.h"
+#include "dolphin_generalsettings.h"
+
#include <KBookmark>
#include <KBookmarkGroup>
#include <KBookmarkManager>
#include <KComponentData>
#include <KDebug>
#include <KIcon>
+#include <kprotocolinfo.h>
#include <KLocale>
#include <KStandardDirs>
#include <KUser>
#include "placesitem.h"
#include <QAction>
#include <QDate>
+#include <QMimeData>
#include <QTimer>
#include <Solid/Device>
#include <Solid/StorageAccess>
#include <Solid/StorageDrive>
+#include <views/dolphinview.h>
+#include <views/viewproperties.h>
+
#ifdef HAVE_NEPOMUK
- #include <Nepomuk/ResourceManager>
+ #include <Nepomuk2/ResourceManager>
+ #include <Nepomuk2/Query/ComparisonTerm>
+ #include <Nepomuk2/Query/LiteralTerm>
+ #include <Nepomuk2/Query/FileQuery>
+ #include <Nepomuk2/Query/ResourceTypeTerm>
+ #include <Nepomuk2/Vocabulary/NFO>
+ #include <Nepomuk2/Vocabulary/NIE>
#endif
namespace {
PlacesItemModel::PlacesItemModel(QObject* parent) :
KStandardItemModel(parent),
- m_nepomukRunning(false),
+ m_fileIndexingEnabled(false),
m_hiddenItemsShown(false),
m_availableDevices(),
m_predicate(),
m_bookmarkedItems(),
m_hiddenItemToRemove(-1),
m_saveBookmarksTimer(0),
- m_updateBookmarksTimer(0)
+ m_updateBookmarksTimer(0),
+ m_storageSetupInProgress()
{
#ifdef HAVE_NEPOMUK
- m_nepomukRunning = (Nepomuk::ResourceManager::instance()->initialized());
+ if (Nepomuk2::ResourceManager::instance()->initialized()) {
+ KConfig config("nepomukserverrc");
+ m_fileIndexingEnabled = config.group("Service-nepomukfileindexer").readEntry("autostart", true);
+ }
+
#endif
const QString file = KStandardDirs::locateLocal("data", "kfileplaces/bookmarks.xml");
m_bookmarkManager = KBookmarkManager::managerForFile(file, "kfilePlaces");
initializeAvailableDevices();
loadBookmarks();
- const int syncBookmarksTimeout = 1000;
+ const int syncBookmarksTimeout = 100;
m_saveBookmarksTimer = new QTimer(this);
m_saveBookmarksTimer->setInterval(syncBookmarksTimeout);
return foundIndex;
}
+void PlacesItemModel::appendItemToGroup(PlacesItem* item)
+{
+ if (!item) {
+ return;
+ }
+
+ int i = 0;
+ while (i < count() && placesItem(i)->group() != item->group()) {
+ ++i;
+ }
+
+ bool inserted = false;
+ while (!inserted && i < count()) {
+ if (placesItem(i)->group() != item->group()) {
+ insertItem(i, item);
+ inserted = true;
+ }
+ ++i;
+ }
+
+ if (!inserted) {
+ appendItem(item);
+ }
+}
+
+
QAction* PlacesItemModel::ejectAction(int index) const
{
const PlacesItem* item = placesItem(index);
this, SLOT(slotStorageTeardownDone(Solid::ErrorType,QVariant)));
drive->eject();
} else {
-
+ const QString label = item->text();
+ const QString message = i18nc("@info", "The device '%1' is not a disk and cannot be ejected.", label);
+ emit errorMessage(message);
}
}
}
connect(access, SIGNAL(teardownDone(Solid::ErrorType,QVariant,QString)),
this, SLOT(slotStorageTeardownDone(Solid::ErrorType,QVariant)));
access->teardown();
- } else {
- const QString label = item->text();
- const QString message = i18nc("@info", "The device '%1' is not a disk and cannot be ejected.", label);
- emit errorMessage(message);
}
}
}
+bool PlacesItemModel::storageSetupNeeded(int index) const
+{
+ const PlacesItem* item = placesItem(index);
+ return item ? item->storageSetupNeeded() : false;
+}
+
+void PlacesItemModel::requestStorageSetup(int index)
+{
+ const PlacesItem* item = placesItem(index);
+ if (!item) {
+ return;
+ }
+
+ Solid::Device device = item->device();
+ const bool setup = device.is<Solid::StorageAccess>()
+ && !m_storageSetupInProgress.contains(device.as<Solid::StorageAccess>())
+ && !device.as<Solid::StorageAccess>()->isAccessible();
+ if (setup) {
+ Solid::StorageAccess* access = device.as<Solid::StorageAccess>();
+
+ m_storageSetupInProgress[access] = index;
+
+ connect(access, SIGNAL(setupDone(Solid::ErrorType,QVariant,QString)),
+ this, SLOT(slotStorageSetupDone(Solid::ErrorType,QVariant,QString)));
+
+ access->setup();
+ }
+}
+
+QMimeData* PlacesItemModel::createMimeData(const QSet<int>& indexes) const
+{
+ KUrl::List urls;
+ QByteArray itemData;
+
+ QDataStream stream(&itemData, QIODevice::WriteOnly);
+
+ foreach (int index, indexes) {
+ const KUrl itemUrl = placesItem(index)->url();
+ if (itemUrl.isValid()) {
+ urls << itemUrl;
+ }
+ stream << index;
+ }
+
+ QMimeData* mimeData = new QMimeData();
+ if (!urls.isEmpty()) {
+ urls.populateMimeData(mimeData);
+ }
+ mimeData->setData(internalMimeType(), itemData);
+
+ return mimeData;
+}
+
+bool PlacesItemModel::supportsDropping(int index) const
+{
+ return index >= 0 && index < count();
+}
+
+void PlacesItemModel::dropMimeDataBefore(int index, const QMimeData* mimeData)
+{
+ if (mimeData->hasFormat(internalMimeType())) {
+ // The item has been moved inside the view
+ QByteArray itemData = mimeData->data(internalMimeType());
+ QDataStream stream(&itemData, QIODevice::ReadOnly);
+ int oldIndex;
+ stream >> oldIndex;
+ if (oldIndex == index || oldIndex == index - 1) {
+ // No moving has been done
+ return;
+ }
+
+ PlacesItem* oldItem = placesItem(oldIndex);
+ if (!oldItem) {
+ return;
+ }
+
+ PlacesItem* newItem = new PlacesItem(oldItem->bookmark());
+ removeItem(oldIndex);
+
+ if (oldIndex < index) {
+ --index;
+ }
+
+ const int dropIndex = groupedDropIndex(index, newItem);
+ insertItem(dropIndex, newItem);
+ } else if (mimeData->hasFormat("text/uri-list")) {
+ // One or more items must be added to the model
+ const KUrl::List urls = KUrl::List::fromMimeData(mimeData);
+ for (int i = urls.count() - 1; i >= 0; --i) {
+ const KUrl& url = urls[i];
+
+ QString text = url.fileName();
+ if (text.isEmpty()) {
+ text = url.host();
+ }
+
+ PlacesItem* newItem = createPlacesItem(text, url);
+ const int dropIndex = groupedDropIndex(index, newItem);
+ insertItem(dropIndex, newItem);
+ }
+ }
+}
+
+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);
{
const PlacesItem* changedItem = placesItem(index);
if (changedItem) {
- // Take care to apply the PlacesItemModel-order of the inserted item
+ // Take care to apply the PlacesItemModel-order of the changed item
// also to the bookmark-manager.
const KBookmark insertedBookmark = changedItem->bookmark();
}
if (changedRoles.contains("isHidden")) {
- const PlacesItem* shownItem = placesItem(index);
- Q_ASSERT(shownItem);
- if (!m_hiddenItemsShown && shownItem->isHidden()) {
+ if (!m_hiddenItemsShown && changedItem->isHidden()) {
m_hiddenItemToRemove = index;
QTimer::singleShot(0, this, SLOT(hideItem()));
}
void PlacesItemModel::slotDeviceAdded(const QString& udi)
{
const Solid::Device device(udi);
- if (m_predicate.matches(device)) {
- m_availableDevices << udi;
- const KBookmark bookmark = PlacesItem::createDeviceBookmark(m_bookmarkManager, udi);
- appendItem(new PlacesItem(bookmark));
+
+ if (!m_predicate.matches(device)) {
+ return;
}
+
+ m_availableDevices << udi;
+ const KBookmark bookmark = PlacesItem::createDeviceBookmark(m_bookmarkManager, udi);
+ appendItem(new PlacesItem(bookmark));
}
void PlacesItemModel::slotDeviceRemoved(const QString& udi)
delete item;
return;
}
- }
+ }
- for (int i = 0; i < count(); ++i) {
- if (placesItem(i)->udi() == udi) {
- removeItem(i);
- return;
- }
- }
+ for (int i = 0; i < count(); ++i) {
+ if (placesItem(i)->udi() == udi) {
+ removeItem(i);
+ return;
+ }
+ }
}
void PlacesItemModel::slotStorageTeardownDone(Solid::ErrorType error, const QVariant& errorData)
}
}
+void PlacesItemModel::slotStorageSetupDone(Solid::ErrorType error,
+ const QVariant& errorData,
+ const QString& udi)
+{
+ Q_UNUSED(udi);
+
+ const int index = m_storageSetupInProgress.take(sender());
+ const PlacesItem* item = placesItem(index);
+ if (!item) {
+ return;
+ }
+
+ if (error) {
+ // TODO: Request message-freeze exception
+ if (errorData.isValid()) {
+ // emit errorMessage(i18nc("@info", "An error occurred while accessing '%1', the system responded: %2",
+ // item->text(),
+ // errorData.toString()));
+ emit errorMessage(QString("An error occurred while accessing '%1', the system responded: %2")
+ .arg(item->text()).arg(errorData.toString()));
+ } else {
+ // emit errorMessage(i18nc("@info", "An error occurred while accessing '%1'",
+ // item->text()));
+ emit errorMessage(QString("An error occurred while accessing '%1'").arg(item->text()));
+ }
+ emit storageSetupDone(index, false);
+ } else {
+ emit storageSetupDone(index, true);
+ }
+}
+
void PlacesItemModel::hideItem()
{
hideItem(m_hiddenItemToRemove);
KBookmarkGroup root = m_bookmarkManager->root();
KBookmark newBookmark = root.first();
while (!newBookmark.isNull()) {
- if (acceptBookmark(newBookmark)) {
+ if (acceptBookmark(newBookmark, m_availableDevices)) {
bool found = false;
int modelIndex = 0;
for (int i = 0; i < m_bookmarkedItems.count(); ++i) {
}
if (!found) {
- PlacesItem* item = new PlacesItem(newBookmark);
- if (item->isHidden() && !m_hiddenItemsShown) {
- m_bookmarkedItems.append(item);
- } else {
- appendItem(item);
+ const QString udi = newBookmark.metaDataItem("UDI");
+
+ /*
+ * See Bug 304878
+ * Only add a new places item, if the item text is not empty
+ * and if the device is available. Fixes the strange behaviour -
+ * add a places item without text in the Places section - when you
+ * remove a device (e.g. a usb stick) without unmounting.
+ */
+ if (udi.isEmpty() || Solid::Device(udi).isValid()) {
+ PlacesItem* item = new PlacesItem(newBookmark);
+ if (item->isHidden() && !m_hiddenItemsShown) {
+ m_bookmarkedItems.append(item);
+ } else {
+ appendItemToGroup(item);
+ }
}
}
}
QList<PlacesItem*> devicesItems;
while (!bookmark.isNull()) {
- const bool deviceAvailable = devices.remove(bookmark.metaDataItem("UDI"));
- if (acceptBookmark(bookmark)) {
+ if (acceptBookmark(bookmark, devices)) {
PlacesItem* item = new PlacesItem(bookmark);
- if (deviceAvailable) {
+ if (item->groupType() == PlacesItem::DevicesType) {
+ devices.remove(item->udi());
devicesItems.append(item);
} else {
const KUrl url = bookmark.url();
if (missingSystemBookmarks.contains(url)) {
missingSystemBookmarks.remove(url);
- // Apply the translated text to the system bookmarks, otherwise an outdated
- // translation might be shown.
- const int index = m_systemBookmarksIndexes.value(url);
- item->setText(m_systemBookmarks[index].text);
+ // Try to retranslate the text of system bookmarks to have translated
+ // items when changing the language. In case if the user has applied a custom
+ // text, the retranslation will fail and the users custom text is still used.
+ // It is important to use "KFile System Bookmarks" as context (see
+ // createSystemBookmarks()).
+ item->setText(i18nc("KFile System Bookmarks", bookmark.text().toUtf8().data()));
item->setSystemItem(true);
}
// 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;
#endif
}
-bool PlacesItemModel::acceptBookmark(const KBookmark& bookmark) const
+bool PlacesItemModel::acceptBookmark(const KBookmark& bookmark,
+ const QSet<QString>& availableDevices) const
{
const QString udi = bookmark.metaDataItem("UDI");
const KUrl url = bookmark.url();
const QString appName = bookmark.metaDataItem("OnlyInApp");
- const bool deviceAvailable = m_availableDevices.contains(udi);
+ const bool deviceAvailable = availableDevices.contains(udi);
const bool allowedHere = (appName.isEmpty()
|| appName == KGlobal::mainComponent().componentName()
|| appName == KGlobal::mainComponent().componentName() + AppNamePrefix)
- && (m_nepomukRunning || (url.protocol() != QLatin1String("timeline") &&
- url.protocol() != QLatin1String("search")));
+ && (m_fileIndexingEnabled || (url.protocol() != QLatin1String("timeline") &&
+ url.protocol() != QLatin1String("search")));
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());
Q_ASSERT(m_systemBookmarksIndexes.isEmpty());
- const QString timeLineIcon = "package_utility_time"; // TODO: Ask the Oxygen team to create
- // a custom icon for the timeline-protocol
-
+ // Note: The context of the I18N_NOOP2 must be "KFile System Bookmarks". The real
+ // i18nc call is done after reading the bookmark. The reason why the i18nc call is not
+ // done here is because otherwise switching the language would not result in retranslating the
+ // bookmarks.
m_systemBookmarks.append(SystemBookmarkData(KUrl(KUser().homeDir()),
"user-home",
- i18nc("@item", "Home")));
+ I18N_NOOP2("KFile System Bookmarks", "Home")));
m_systemBookmarks.append(SystemBookmarkData(KUrl("remote:/"),
"network-workgroup",
- i18nc("@item", "Network")));
+ I18N_NOOP2("KFile System Bookmarks", "Network")));
m_systemBookmarks.append(SystemBookmarkData(KUrl("/"),
"folder-red",
- i18nc("@item", "Root")));
+ I18N_NOOP2("KFile System Bookmarks", "Root")));
m_systemBookmarks.append(SystemBookmarkData(KUrl("trash:/"),
"user-trash",
- i18nc("@item", "Trash")));
+ I18N_NOOP2("KFile System Bookmarks", "Trash")));
- if (m_nepomukRunning) {
+ if (m_fileIndexingEnabled) {
m_systemBookmarks.append(SystemBookmarkData(KUrl("timeline:/today"),
- timeLineIcon,
- i18nc("@item Recently Accessed", "Today")));
+ "go-jump-today",
+ I18N_NOOP2("KFile System Bookmarks", "Today")));
m_systemBookmarks.append(SystemBookmarkData(KUrl("timeline:/yesterday"),
- timeLineIcon,
- i18nc("@item Recently Accessed", "Yesterday")));
+ "view-calendar-day",
+ I18N_NOOP2("KFile System Bookmarks", "Yesterday")));
m_systemBookmarks.append(SystemBookmarkData(KUrl("timeline:/thismonth"),
- timeLineIcon,
- i18nc("@item Recently Accessed", "This Month")));
+ "view-calendar-month",
+ I18N_NOOP2("KFile System Bookmarks", "This Month")));
m_systemBookmarks.append(SystemBookmarkData(KUrl("timeline:/lastmonth"),
- timeLineIcon,
- i18nc("@item Recently Accessed", "Last Month")));
+ "view-calendar-month",
+ I18N_NOOP2("KFile System Bookmarks", "Last Month")));
m_systemBookmarks.append(SystemBookmarkData(KUrl("search:/documents"),
"folder-txt",
- i18nc("@item Commonly Accessed", "Documents")));
+ I18N_NOOP2("KFile System Bookmarks", "Documents")));
m_systemBookmarks.append(SystemBookmarkData(KUrl("search:/images"),
"folder-image",
- i18nc("@item Commonly Accessed", "Images")));
+ I18N_NOOP2("KFile System Bookmarks", "Images")));
m_systemBookmarks.append(SystemBookmarkData(KUrl("search:/audio"),
"folder-sound",
- i18nc("@item Commonly Accessed", "Audio Files")));
+ I18N_NOOP2("KFile System Bookmarks", "Audio Files")));
m_systemBookmarks.append(SystemBookmarkData(KUrl("search:/videos"),
"folder-video",
- i18nc("@item Commonly Accessed", "Videos")));
+ I18N_NOOP2("KFile System Bookmarks", "Videos")));
}
for (int i = 0; i < m_systemBookmarks.count(); ++i) {
void PlacesItemModel::initializeAvailableDevices()
{
- m_predicate = Solid::Predicate::fromString(
- "[[[[ StorageVolume.ignored == false AND [ StorageVolume.usage == 'FileSystem' OR StorageVolume.usage == 'Encrypted' ]]"
+ QString predicate("[[[[ StorageVolume.ignored == false AND [ StorageVolume.usage == 'FileSystem' OR StorageVolume.usage == 'Encrypted' ]]"
" OR "
"[ IS StorageAccess AND StorageDrive.driveType == 'Floppy' ]]"
" OR "
"OpticalDisc.availableContent & 'Audio' ]"
" OR "
"StorageAccess.ignored == false ]");
+
+
+ if (KProtocolInfo::isKnownProtocol("mtp")) {
+ predicate.prepend("[");
+ predicate.append(" OR PortableMediaPlayer.supportedProtocols == 'mtp']");
+ }
+
+ m_predicate = Solid::Predicate::fromString(predicate);
Q_ASSERT(m_predicate.isValid());
Solid::DeviceNotifier* notifier = Solid::DeviceNotifier::instance();
connect(notifier, SIGNAL(deviceRemoved(QString)), this, SLOT(slotDeviceRemoved(QString)));
const QList<Solid::Device>& deviceList = Solid::Device::listFromQuery(m_predicate);
- foreach(const Solid::Device& device, deviceList) {
+ foreach (const Solid::Device& device, deviceList) {
m_availableDevices << device.udi();
}
}
}
}
+QString PlacesItemModel::internalMimeType() const
+{
+ return "application/x-dolphinplacesmodel-" +
+ QString::number((qptrdiff)this);
+}
+
+int PlacesItemModel::groupedDropIndex(int index, const PlacesItem* item) const
+{
+ Q_ASSERT(item);
+
+ int dropIndex = index;
+ const PlacesItem::GroupType type = item->groupType();
+
+ const int itemCount = count();
+ if (index < 0) {
+ dropIndex = itemCount;
+ }
+
+ // Search nearest previous item with the same group
+ int previousIndex = -1;
+ for (int i = dropIndex - 1; i >= 0; --i) {
+ if (placesItem(i)->groupType() == type) {
+ previousIndex = i;
+ break;
+ }
+ }
+
+ // Search nearest next item with the same group
+ int nextIndex = -1;
+ for (int i = dropIndex; i < count(); ++i) {
+ if (placesItem(i)->groupType() == type) {
+ nextIndex = i;
+ break;
+ }
+ }
+
+ // Adjust the drop-index to be inserted to the
+ // nearest item with the same group.
+ if (previousIndex >= 0 && nextIndex >= 0) {
+ dropIndex = (dropIndex - previousIndex < nextIndex - dropIndex) ?
+ previousIndex + 1 : nextIndex;
+ } else if (previousIndex >= 0) {
+ dropIndex = previousIndex + 1;
+ } else if (nextIndex >= 0) {
+ dropIndex = nextIndex;
+ }
+
+ return dropIndex;
+}
+
bool PlacesItemModel::equalBookmarkIdentifiers(const KBookmark& b1, const KBookmark& b2)
{
const QString udi1 = b1.metaDataItem("UDI");
}
}
+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(QLatin1String("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(QLatin1String("thismonth"))) {
+ const QDate date = QDate::currentDate();
+ timelineUrl = "timeline:/" + timelineDateString(date.year(), date.month());
+ } else if (path.endsWith(QLatin1String("lastmonth"))) {
+ const QDate date = QDate::currentDate().addMonths(-1);
+ timelineUrl = "timeline:/" + timelineDateString(date.year(), date.month());
+ } else {
+ Q_ASSERT(path.endsWith(QLatin1String("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(QLatin1String("documents"))) {
+ searchUrl = searchUrlForTerm(Nepomuk2::Query::ResourceTypeTerm(Nepomuk2::Vocabulary::NFO::Document()));
+ } else if (path.endsWith(QLatin1String("images"))) {
+ searchUrl = searchUrlForTerm(Nepomuk2::Query::ResourceTypeTerm(Nepomuk2::Vocabulary::NFO::Image()));
+ } else if (path.endsWith(QLatin1String("audio"))) {
+ searchUrl = searchUrlForTerm(Nepomuk2::Query::ComparisonTerm(Nepomuk2::Vocabulary::NIE::mimeType(),
+ Nepomuk2::Query::LiteralTerm("audio")));
+ } else if (path.endsWith(QLatin1String("videos"))) {
+ searchUrl = searchUrlForTerm(Nepomuk2::Query::ComparisonTerm(Nepomuk2::Vocabulary::NIE::mimeType(),
+ Nepomuk2::Query::LiteralTerm("video")));
+ } else {
+ Q_ASSERT(false);
+ }
+#else
+ Q_UNUSED(url);
+#endif
+
+ return searchUrl;
+}
+
+#ifdef HAVE_NEPOMUK
+KUrl PlacesItemModel::searchUrlForTerm(const Nepomuk2::Query::Term& term)
+{
+ const Nepomuk2::Query::FileQuery query(term);
+ return query.toSearchUrl();
+}
+#endif
+
#ifdef PLACESITEMMODEL_DEBUG
void PlacesItemModel::showModelState()
{