diff options
Diffstat (limited to 'src/panels')
| -rw-r--r-- | src/panels/places/placesitemlistgroupheader.cpp | 40 | ||||
| -rw-r--r-- | src/panels/places/placesitemlistgroupheader.h | 38 | ||||
| -rw-r--r-- | src/panels/places/placespanel.cpp | 257 | ||||
| -rw-r--r-- | src/panels/places/placespanel.h | 66 |
4 files changed, 390 insertions, 11 deletions
diff --git a/src/panels/places/placesitemlistgroupheader.cpp b/src/panels/places/placesitemlistgroupheader.cpp new file mode 100644 index 000000000..27d4c7917 --- /dev/null +++ b/src/panels/places/placesitemlistgroupheader.cpp @@ -0,0 +1,40 @@ +/*************************************************************************** + * Copyright (C) 2012 by Peter Penz <[email protected]> * + * * + * Based on the Itemviews NG project from Trolltech Labs: * + * http://qt.gitorious.org/qt-labs/itemviews-ng * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include "placesitemlistgroupheader.h" + +PlacesItemListGroupHeader::PlacesItemListGroupHeader(QGraphicsWidget* parent) : + KStandardItemListGroupHeader(parent) +{ +} + +PlacesItemListGroupHeader::~PlacesItemListGroupHeader() +{ +} + +void PlacesItemListGroupHeader::paintSeparator(QPainter* painter, const QColor& color) +{ + Q_UNUSED(painter); + Q_UNUSED(color); +} + +#include "placesitemlistgroupheader.moc" diff --git a/src/panels/places/placesitemlistgroupheader.h b/src/panels/places/placesitemlistgroupheader.h new file mode 100644 index 000000000..fbcd116f1 --- /dev/null +++ b/src/panels/places/placesitemlistgroupheader.h @@ -0,0 +1,38 @@ +/*************************************************************************** + * Copyright (C) 2012 by Peter Penz <[email protected]> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef PLACESITEMLISTGROUPHEADER_H +#define PLACESITEMLISTGROUPHEADER_H + +#include <kitemviews/kstandarditemlistgroupheader.h> + +class PlacesItemListGroupHeader : public KStandardItemListGroupHeader +{ + Q_OBJECT + +public: + PlacesItemListGroupHeader(QGraphicsWidget* parent = 0); + virtual ~PlacesItemListGroupHeader(); + +protected: + virtual void paintSeparator(QPainter* painter, const QColor& color); +}; +#endif + + diff --git a/src/panels/places/placespanel.cpp b/src/panels/places/placespanel.cpp index 5ea4b971c..d13eb0812 100644 --- a/src/panels/places/placespanel.cpp +++ b/src/panels/places/placespanel.cpp @@ -23,28 +23,45 @@ #include "placespanel.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 + #include <KBookmark> #include <KBookmarkGroup> #include <KBookmarkManager> #include <KComponentData> #include <KDebug> #include <KIcon> +#include <KLocale> #include <kitemviews/kitemlistcontainer.h> #include <kitemviews/kitemlistcontroller.h> #include <kitemviews/kstandarditem.h> #include <kitemviews/kstandarditemlistview.h> #include <kitemviews/kstandarditemmodel.h> #include <KStandardDirs> +#include <KUser> +#include "placesitemlistgroupheader.h" #include <views/draganddrophelper.h> +#include <QDir> #include <QVBoxLayout> #include <QShowEvent> PlacesPanel::PlacesPanel(QWidget* parent) : Panel(parent), + m_nepomukRunning(false), m_controller(0), m_model(0), m_availableDevices(), - m_bookmarkManager(0) + m_bookmarkManager(0), + m_defaultBookmarks(), + m_defaultBookmarksIndexes() { } @@ -68,17 +85,27 @@ void PlacesPanel::showEvent(QShowEvent* event) // Postpone the creating of the controller to the first show event. // This assures that no performance and memory overhead is given when the folders panel is not // used at all and stays invisible. +#ifdef HAVE_NEPOMUK + m_nepomukRunning = (Nepomuk::ResourceManager::instance()->initialized()); +#endif + createDefaultBookmarks(); + const QString file = KStandardDirs::locateLocal("data", "kfileplaces/bookmarks.xml"); - m_bookmarkManager = KBookmarkManager::managerForFile(file, "kfileplaces"); + m_bookmarkManager = KBookmarkManager::managerForFile(file, "kfilePlaces"); m_model = new KStandardItemModel(this); + m_model->setGroupedSorting(true); + m_model->setSortRole("group"); loadBookmarks(); KStandardItemListView* view = new KStandardItemListView(); + view->setGroupHeaderCreator(new KItemListGroupHeaderCreator<PlacesItemListGroupHeader>()); m_controller = new KItemListController(m_model, view, this); m_controller->setSelectionBehavior(KItemListController::SingleSelection); connect(m_controller, SIGNAL(itemActivated(int)), this, SLOT(slotItemActivated(int))); connect(m_controller, SIGNAL(itemMiddleClicked(int)), this, SLOT(slotItemMiddleClicked(int))); + connect(m_controller, SIGNAL(itemContextMenuRequested(int,QPointF)), this, SLOT(slotItemContextMenuRequested(int,QPointF))); + connect(m_controller, SIGNAL(viewContextMenuRequested(QPointF)), this, SLOT(slotViewContextMenuRequested(QPointF))); KItemListContainer* container = new KItemListContainer(m_controller, this); container->setEnabledFrame(false); @@ -93,55 +120,263 @@ void PlacesPanel::showEvent(QShowEvent* event) void PlacesPanel::slotItemActivated(int index) { - const KStandardItem* item = m_model->item(index); - if (item) { - const KUrl url = item->dataValue("url").value<KUrl>(); + const KUrl url = urlForIndex(index); + if (!url.isEmpty()) { emit placeActivated(url); } } void PlacesPanel::slotItemMiddleClicked(int index) { - const KStandardItem* item = m_model->item(index); - if (item) { - const KUrl url = item->dataValue("url").value<KUrl>(); + const KUrl url = urlForIndex(index); + if (!url.isEmpty()) { emit placeMiddleClicked(url); } } +void PlacesPanel::slotItemContextMenuRequested(int index, const QPointF& pos) +{ + Q_UNUSED(index); + Q_UNUSED(pos); +} + +void PlacesPanel::slotViewContextMenuRequested(const QPointF& pos) +{ + Q_UNUSED(pos); +} + void PlacesPanel::slotUrlsDropped(const KUrl& dest, QDropEvent* event, QWidget* parent) { Q_UNUSED(parent); DragAndDropHelper::dropUrls(KFileItem(), dest, event); } +void PlacesPanel::createDefaultBookmarks() +{ + Q_ASSERT(m_defaultBookmarks.isEmpty()); + Q_ASSERT(m_defaultBookmarksIndexes.isEmpty()); + + const QString placesGroup = i18nc("@item", "Places"); + const QString recentlyAccessedGroup = i18nc("@item", "Recently Accessed"); + const QString searchForGroup = i18nc("@item", "Search For"); + const QString timeLineIcon = "package_utility_time"; // TODO: Ask the Oxygen team to create + // a custom icon for the timeline-protocol + + m_defaultBookmarks.append(DefaultBookmarkData(KUrl(KUser().homeDir()), + "user-home", + i18nc("@item", "Home"), + placesGroup)); + m_defaultBookmarks.append(DefaultBookmarkData(KUrl("remote:/"), + "network-workgroup", + i18nc("@item", "Network"), + placesGroup)); + m_defaultBookmarks.append(DefaultBookmarkData(KUrl("/"), + "folder-red", + i18nc("@item", "Root"), + placesGroup)); + m_defaultBookmarks.append(DefaultBookmarkData(KUrl("trash:/"), + "user-trash", + i18nc("@item", "Trash"), + placesGroup)); + + if (m_nepomukRunning) { + m_defaultBookmarks.append(DefaultBookmarkData(KUrl("timeline:/today"), + timeLineIcon, + i18nc("@item Recently Accessed", "Today"), + recentlyAccessedGroup)); + m_defaultBookmarks.append(DefaultBookmarkData(KUrl("timeline:/yesterday"), + timeLineIcon, + i18nc("@item Recently Accessed", "Yesterday"), + recentlyAccessedGroup)); + m_defaultBookmarks.append(DefaultBookmarkData(KUrl("timeline:/thismonth"), + timeLineIcon, + i18nc("@item Recently Accessed", "This Month"), + recentlyAccessedGroup)); + m_defaultBookmarks.append(DefaultBookmarkData(KUrl("timeline:/lastmonth"), + timeLineIcon, + i18nc("@item Recently Accessed", "Last Month"), + recentlyAccessedGroup)); + m_defaultBookmarks.append(DefaultBookmarkData(KUrl("search:/documents"), + "folder-txt", + i18nc("@item Commonly Accessed", "Documents"), + searchForGroup)); + m_defaultBookmarks.append(DefaultBookmarkData(KUrl("search:/images"), + "folder-image", + i18nc("@item Commonly Accessed", "Images"), + searchForGroup)); + m_defaultBookmarks.append(DefaultBookmarkData(KUrl("search:/music"), + "folder-sound", + i18nc("@item Commonly Accessed", "Music"), + searchForGroup)); + m_defaultBookmarks.append(DefaultBookmarkData(KUrl("search:/videos"), + "folder-video", + i18nc("@item Commonly Accessed", "Videos"), + searchForGroup)); + } + + for (int i = 0; i < m_defaultBookmarks.count(); ++i) { + m_defaultBookmarksIndexes.insert(m_defaultBookmarks[i].url, i); + } +} + void PlacesPanel::loadBookmarks() { KBookmarkGroup root = m_bookmarkManager->root(); KBookmark bookmark = root.first(); QSet<QString> devices = m_availableDevices; + QSet<KUrl> missingDefaultBookmarks; + foreach (const DefaultBookmarkData& data, m_defaultBookmarks) { + missingDefaultBookmarks.insert(data.url); + } + while (!bookmark.isNull()) { const QString udi = bookmark.metaDataItem("UDI"); + const KUrl url = bookmark.url(); const QString appName = bookmark.metaDataItem("OnlyInApp"); const bool deviceAvailable = devices.remove(udi); - const bool allowedHere = appName.isEmpty() || (appName == KGlobal::mainComponent().componentName()); + const bool allowedHere = (appName.isEmpty() || appName == KGlobal::mainComponent().componentName()) + && (m_nepomukRunning || url.protocol() != QLatin1String("timeline")); if ((udi.isEmpty() && allowedHere) || deviceAvailable) { KStandardItem* item = new KStandardItem(); item->setIcon(KIcon(bookmark.icon())); - item->setText(bookmark.text()); item->setDataValue("address", bookmark.address()); - item->setDataValue("url", bookmark.url()); + item->setDataValue("url", url); + + if (missingDefaultBookmarks.contains(url)) { + missingDefaultBookmarks.remove(url); + // Always apply the translated text to the default bookmarks, otherwise an outdated + // translation might be shown. + const int index = m_defaultBookmarksIndexes.value(url); + item->setText(m_defaultBookmarks[index].text); + } else { + item->setText(bookmark.text()); + } + if (deviceAvailable) { item->setDataValue("udi", udi); + item->setGroup(i18nc("@item", "Devices")); + } else { + item->setGroup(i18nc("@item", "Places")); } + m_model->appendItem(item); } bookmark = root.next(bookmark); } + + if (!missingDefaultBookmarks.isEmpty()) { + foreach (const DefaultBookmarkData& data, m_defaultBookmarks) { + if (missingDefaultBookmarks.contains(data.url)) { + KStandardItem* item = new KStandardItem(); + item->setIcon(KIcon(data.icon)); + item->setText(data.text); + item->setDataValue("url", data.url); + item->setGroup(data.group); + m_model->appendItem(item); + } + } + } +} + +KUrl PlacesPanel::urlForIndex(int index) const +{ + const KStandardItem* item = m_model->item(index); + if (!item) { + return KUrl(); + } + + KUrl url = item->dataValue("url").value<KUrl>(); + if (url.protocol() == QLatin1String("timeline")) { + url = createTimelineUrl(url); + } else if (url.protocol() == QLatin1String("search")) { + url = createSearchUrl(url); + } + + return url; +} + +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("music")) { + 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); + } +#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" diff --git a/src/panels/places/placespanel.h b/src/panels/places/placespanel.h index 80cb732f0..ea05601e0 100644 --- a/src/panels/places/placespanel.h +++ b/src/panels/places/placespanel.h @@ -21,13 +21,28 @@ #ifndef PLACESPANEL_H #define PLACESPANEL_H +#include <config-nepomuk.h> + +#include <KUrl> #include <panels/panel.h> +#include <QHash> +#include <QList> #include <QSet> class KBookmarkManager; class KItemListController; class KStandardItemModel; +#ifdef HAVE_NEPOMUK +namespace Nepomuk +{ + namespace Query + { + class Term; + } +} +#endif + /** * @brief Combines bookmarks and mounted devices as list. */ @@ -50,16 +65,67 @@ protected: private slots: void slotItemActivated(int index); void slotItemMiddleClicked(int index); + void slotItemContextMenuRequested(int index, const QPointF& pos); + void slotViewContextMenuRequested(const QPointF& pos); void slotUrlsDropped(const KUrl& dest, QDropEvent* event, QWidget* parent); private: + void createDefaultBookmarks(); void loadBookmarks(); + KUrl urlForIndex(int index) const; + + /** + * @return URL using the timeline-protocol for searching. + */ + 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" + */ + 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: + bool m_nepomukRunning; + KItemListController* m_controller; KStandardItemModel* m_model; + QSet<QString> m_availableDevices; KBookmarkManager* m_bookmarkManager; + + struct DefaultBookmarkData + { + DefaultBookmarkData(const KUrl& url, + const QString& icon, + const QString& text, + const QString& group) : + url(url), icon(icon), text(text), group(group) {} + KUrl url; + QString icon; + QString text; + QString group; + }; + + QList<DefaultBookmarkData> m_defaultBookmarks; + QHash<KUrl, int> m_defaultBookmarksIndexes; }; #endif // PLACESPANEL_H |
