***************************************************************************/
#include "kstandarditemmodel.h"
+
+#include <KDebug>
#include "kstandarditem.h"
KStandardItemModel::KStandardItemModel(QObject* parent) :
KStandardItemModel::~KStandardItemModel()
{
+ qDeleteAll(m_items);
+ m_items.clear();
+ m_indexesForItems.clear();
}
void KStandardItemModel::insertItem(int index, KStandardItem* item)
}
}
+void KStandardItemModel::replaceItem(int index, KStandardItem* item)
+{
+ if (index >= 0 && index < count()) {
+ QSet<QByteArray> changedRoles;
+
+ KStandardItem* oldItem= m_items[index];
+ const QHash<QByteArray, QVariant> oldData = oldItem->data();
+ const QHash<QByteArray, QVariant> newData = item->data();
+
+ // Determine which roles have been changed
+ QHashIterator<QByteArray, QVariant> it(oldData);
+ while (it.hasNext()) {
+ it.next();
+ const QByteArray role = it.key();
+ const QVariant oldValue = it.value();
+ if (newData.contains(role) && newData.value(role) != oldValue) {
+ changedRoles.insert(role);
+ }
+ }
+
+ m_indexesForItems.remove(oldItem);
+ delete oldItem;
+ oldItem = 0;
+
+ m_items[index] = item;
+ m_indexesForItems.insert(item, index);
+
+ emit itemsChanged(KItemRangeList() << KItemRange(index, 1), changedRoles);
+ } else {
+ kWarning() << "No item available to replace on the given index" << index;
+ delete item;
+ item = 0;
+ }
+}
+
void KStandardItemModel::appendItem(KStandardItem *item)
{
insertItem(m_items.count(), item);
}
-void KStandardItemModel::removeItem(KStandardItem* item)
+void KStandardItemModel::removeItem(int index)
{
- const int index = m_indexesForItems.value(item, -1);
- if (index >= 0) {
- m_items.removeAt(index);
+ if (index >= 0 && index < count()) {
+ KStandardItem* item = m_items[index];
m_indexesForItems.remove(item);
+ m_items.removeAt(index);
delete item;
+ item = 0;
+
+ emit itemsRemoved(KItemRangeList() << KItemRange(index, 1));
// TODO: no hierarchical items are handled yet
}
}
QHash<QByteArray, QVariant> KStandardItemModel::data(int index) const
{
- const KStandardItem* item = m_items[index];
- if (item) {
- return item->data();
+ if (index >= 0 && index < count()) {
+ const KStandardItem* item = m_items[index];
+ if (item) {
+ return item->data();
+ }
}
return QHash<QByteArray, QVariant>();
}
virtual ~KStandardItemModel();
void insertItem(int index, KStandardItem* item);
+ void replaceItem(int index, KStandardItem* item);
void appendItem(KStandardItem* item);
- void removeItem(KStandardItem* item);
+ void removeItem(int index);
KStandardItem* item(int index) const;
int index(const KStandardItem* item) const;
QString PlacesItemEditDialog::icon() const
{
- return m_icon;
+ return m_iconButton->icon();
}
void PlacesItemEditDialog::setText(const QString& text)
QString PlacesItemEditDialog::text() const
{
- return m_text;
+ return m_textEdit->text().isEmpty() ? m_urlEdit->url().fileName() : m_textEdit->text();
}
void PlacesItemEditDialog::setUrl(const KUrl& url)
KUrl PlacesItemEditDialog::url() const
{
- return m_url;
+ return m_urlEdit->url();
}
void PlacesItemEditDialog::setAllowGlobal(bool allow)
return QWidget::event(event);
}
+void PlacesItemEditDialog::slotUrlChanged(const QString& text)
+{
+ enableButtonOk(!text.isEmpty());
+}
+
PlacesItemEditDialog::~PlacesItemEditDialog()
{
}
formLayout->addRow(i18nc("@label", "Location:"), m_urlEdit);
// Provide room for at least 40 chars (average char width is half of height)
m_urlEdit->setMinimumWidth(m_urlEdit->fontMetrics().height() * (40 / 2));
+ connect(m_urlEdit->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(slotUrlChanged(QString)));
m_iconButton = new KIconButton(mainWidget);
formLayout->addRow(i18nc("@label", "Choose an icon:"), m_iconButton);
m_textEdit->setFocus();
}
- setMainWidget( mainWidget );
+ setMainWidget(mainWidget);
}
#include "placesitemeditdialog.moc"
protected:
virtual bool event(QEvent* event);
+private slots:
+ void slotUrlChanged(const QString& text);
+
private:
void initialize();
m_nepomukRunning(false),
m_availableDevices(),
m_bookmarkManager(0),
- m_defaultBookmarks(),
- m_defaultBookmarksIndexes()
+ m_systemBookmarks(),
+ m_systemBookmarksIndexes()
{
#ifdef HAVE_NEPOMUK
m_nepomukRunning = (Nepomuk::ResourceManager::instance()->initialized());
const QString file = KStandardDirs::locateLocal("data", "kfileplaces/bookmarks.xml");
m_bookmarkManager = KBookmarkManager::managerForFile(file, "kfilePlaces");
- createDefaultBookmarks();
+ createSystemBookmarks();
loadBookmarks();
}
return 0;
}
+bool PlacesItemModel::isSystemItem(int index) const
+{
+ if (index >= 0 && index < count()) {
+ const KUrl url = data(index).value("url").value<KUrl>();
+ return m_systemBookmarksIndexes.contains(url);
+ }
+ return false;
+}
+
+int PlacesItemModel::closestItem(const KUrl& url) const
+{
+ int foundIndex = -1;
+ int maxLength = 0;
+
+ for (int i = 0; i < count(); ++i) {
+ const KUrl itemUrl = data(i).value("url").value<KUrl>();
+ if (itemUrl.isParentOf(url)) {
+ const int length = itemUrl.prettyUrl().length();
+ if (length > maxLength) {
+ foundIndex = i;
+ maxLength = length;
+ }
+ }
+ }
+
+ return foundIndex;
+}
+
+QString PlacesItemModel::placesGroupName() const
+{
+ return i18nc("@item", "Places");
+}
+
+QString PlacesItemModel::recentlyAccessedGroupName() const
+{
+ return i18nc("@item", "Recently Accessed");
+}
+
+QString PlacesItemModel::searchForGroupName() const
+{
+ return i18nc("@item", "Search For");
+}
+
QAction* PlacesItemModel::ejectAction(int index) const
{
Q_UNUSED(index);
KBookmark bookmark = root.first();
QSet<QString> devices = m_availableDevices;
- QSet<KUrl> missingDefaultBookmarks;
- foreach (const DefaultBookmarkData& data, m_defaultBookmarks) {
- missingDefaultBookmarks.insert(data.url);
+ QSet<KUrl> missingSystemBookmarks;
+ foreach (const SystemBookmarkData& data, m_systemBookmarks) {
+ missingSystemBookmarks.insert(data.url);
}
while (!bookmark.isNull()) {
item->setDataValue("address", bookmark.address());
item->setDataValue("url", url);
- if (missingDefaultBookmarks.contains(url)) {
- missingDefaultBookmarks.remove(url);
- // Apply the translated text to the default bookmarks, otherwise an outdated
+ 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_defaultBookmarksIndexes.value(url);
- item->setText(m_defaultBookmarks[index].text);
+ const int index = m_systemBookmarksIndexes.value(url);
+ item->setText(m_systemBookmarks[index].text);
- // The default bookmarks don't contain "real" queries stored as URLs, so
+ // The system bookmarks don't contain "real" queries stored as URLs, so
// they must be translated first.
- item->setDataValue("url", translatedDefaultBookmarkUrl(url));
+ item->setDataValue("url", translatedSystemBookmarkUrl(url));
} else {
item->setText(bookmark.text());
}
bookmark = root.next(bookmark);
}
- if (!missingDefaultBookmarks.isEmpty()) {
- foreach (const DefaultBookmarkData& data, m_defaultBookmarks) {
- if (missingDefaultBookmarks.contains(data.url)) {
+ if (!missingSystemBookmarks.isEmpty()) {
+ foreach (const SystemBookmarkData& data, m_systemBookmarks) {
+ if (missingSystemBookmarks.contains(data.url)) {
KStandardItem* item = new KStandardItem();
item->setIcon(KIcon(data.icon));
item->setText(data.text);
- item->setDataValue("url", translatedDefaultBookmarkUrl(data.url));
+ item->setDataValue("url", translatedSystemBookmarkUrl(data.url));
item->setGroup(data.group);
appendItem(item);
}
}
}
-void PlacesItemModel::createDefaultBookmarks()
+void PlacesItemModel::createSystemBookmarks()
{
- Q_ASSERT(m_defaultBookmarks.isEmpty());
- Q_ASSERT(m_defaultBookmarksIndexes.isEmpty());
+ Q_ASSERT(m_systemBookmarks.isEmpty());
+ Q_ASSERT(m_systemBookmarksIndexes.isEmpty());
- const QString placesGroup = i18nc("@item", "Places");
- const QString recentlyAccessedGroup = i18nc("@item", "Recently Accessed");
- const QString searchForGroup = i18nc("@item", "Search For");
+ const QString placesGroup = placesGroupName();
+ const QString recentlyAccessedGroup = recentlyAccessedGroupName();
+ const QString searchForGroup = searchForGroupName();
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));
+ m_systemBookmarks.append(SystemBookmarkData(KUrl(KUser().homeDir()),
+ "user-home",
+ i18nc("@item", "Home"),
+ placesGroup));
+ m_systemBookmarks.append(SystemBookmarkData(KUrl("remote:/"),
+ "network-workgroup",
+ i18nc("@item", "Network"),
+ placesGroup));
+ m_systemBookmarks.append(SystemBookmarkData(KUrl("/"),
+ "folder-red",
+ i18nc("@item", "Root"),
+ placesGroup));
+ m_systemBookmarks.append(SystemBookmarkData(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:/audio"),
- "folder-sound",
- i18nc("@item Commonly Accessed", "Audio"),
- searchForGroup));
- m_defaultBookmarks.append(DefaultBookmarkData(KUrl("search:/videos"),
- "folder-video",
- i18nc("@item Commonly Accessed", "Videos"),
- searchForGroup));
+ m_systemBookmarks.append(SystemBookmarkData(KUrl("timeline:/today"),
+ timeLineIcon,
+ i18nc("@item Recently Accessed", "Today"),
+ recentlyAccessedGroup));
+ m_systemBookmarks.append(SystemBookmarkData(KUrl("timeline:/yesterday"),
+ timeLineIcon,
+ i18nc("@item Recently Accessed", "Yesterday"),
+ recentlyAccessedGroup));
+ m_systemBookmarks.append(SystemBookmarkData(KUrl("timeline:/thismonth"),
+ timeLineIcon,
+ i18nc("@item Recently Accessed", "This Month"),
+ recentlyAccessedGroup));
+ m_systemBookmarks.append(SystemBookmarkData(KUrl("timeline:/lastmonth"),
+ timeLineIcon,
+ i18nc("@item Recently Accessed", "Last Month"),
+ recentlyAccessedGroup));
+ m_systemBookmarks.append(SystemBookmarkData(KUrl("search:/documents"),
+ "folder-txt",
+ i18nc("@item Commonly Accessed", "Documents"),
+ searchForGroup));
+ m_systemBookmarks.append(SystemBookmarkData(KUrl("search:/images"),
+ "folder-image",
+ i18nc("@item Commonly Accessed", "Images"),
+ searchForGroup));
+ m_systemBookmarks.append(SystemBookmarkData(KUrl("search:/audio"),
+ "folder-sound",
+ i18nc("@item Commonly Accessed", "Audio"),
+ searchForGroup));
+ m_systemBookmarks.append(SystemBookmarkData(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);
+ for (int i = 0; i < m_systemBookmarks.count(); ++i) {
+ const KUrl url = translatedSystemBookmarkUrl(m_systemBookmarks[i].url);
+ m_systemBookmarksIndexes.insert(url, i);
}
}
-KUrl PlacesItemModel::translatedDefaultBookmarkUrl(const KUrl& url) const
+KUrl PlacesItemModel::translatedSystemBookmarkUrl(const KUrl& url) const
{
KUrl translatedUrl = url;
if (url.protocol() == QLatin1String("timeline")) {
int hiddenCount() const;
+ /**
+ * @return True if the item is a default item created by
+ * the system (e.g. the places for home, root, trash etc.)
+ */
+ bool isSystemItem(int index) const;
+
+ /**
+ * Search the item which is equal to the URL or at least
+ * is a parent URL. If there are more than one possible
+ * candidates, return the item which covers the biggest
+ * range of the URL. -1 is returned if no closest item
+ * could be found.
+ */
+ int closestItem(const KUrl& url) const;
+
+ QString placesGroupName() const;
+ QString recentlyAccessedGroupName() const;
+ QString searchForGroupName() const;
+
QAction* ejectAction(int index) const;
QAction* tearDownAction(int index) const;
private:
void loadBookmarks();
- void createDefaultBookmarks();
+ void createSystemBookmarks();
- KUrl translatedDefaultBookmarkUrl(const KUrl& url) const;
+ KUrl translatedSystemBookmarkUrl(const KUrl& url) const;
/**
* @return URL using the timeline-protocol for searching.
QSet<QString> m_availableDevices;
KBookmarkManager* m_bookmarkManager;
- struct DefaultBookmarkData
+ struct SystemBookmarkData
{
- DefaultBookmarkData(const KUrl& url,
+ SystemBookmarkData(const KUrl& url,
const QString& icon,
const QString& text,
const QString& group) :
QString group;
};
- QList<DefaultBookmarkData> m_defaultBookmarks;
- QHash<KUrl, int> m_defaultBookmarksIndexes;
+ QList<SystemBookmarkData> m_systemBookmarks;
+ QHash<KUrl, int> m_systemBookmarksIndexes;
};
#endif
#include "placespanel.h"
#include <KConfigGroup>
+#include <KDebug>
#include <KDirNotify>
#include <KIcon>
#include <KIO/Job>
#include <KLocale>
#include <kitemviews/kitemlistcontainer.h>
#include <kitemviews/kitemlistcontroller.h>
+#include <kitemviews/kitemlistselectionmanager.h>
+#include <kitemviews/kstandarditem.h>
#include <kitemviews/kstandarditemlistview.h>
#include <KMenu>
#include <KMessageBox>
QVBoxLayout* layout = new QVBoxLayout(this);
layout->setMargin(0);
layout->addWidget(container);
+
+ selectClosestItem();
}
Panel::showEvent(event);
QAction* tearDownAction = 0;
QAction* ejectAction = 0;
+ const bool isSystemItem = m_model->isSystemItem(index);
const bool isDevice = !data.value("udi").toString().isEmpty();
if (isDevice) {
ejectAction = m_model->ejectAction(index);
menu.addSeparator();
}
addAction = menu.addAction(KIcon("document-new"), i18nc("@item:inmenu", "Add Entry..."));
- mainSeparator = menu.addSeparator();
- editAction = menu.addAction(KIcon("document-properties"), i18nc("@item:inmenu", "Edit Entry '%1'...", label));
+ if (!isSystemItem) {
+ mainSeparator = menu.addSeparator();
+ editAction = menu.addAction(KIcon("document-properties"), i18nc("@item:inmenu", "Edit Entry '%1'...", label));
+ }
}
if (!addAction) {
}
QAction* removeAction = 0;
- if (!isDevice) {
+ if (!isDevice && !isSystemItem) {
removeAction = menu.addAction(KIcon("edit-delete"), i18nc("@item:inmenu", "Remove Entry '%1'", label));
}
}
QAction* action = menu.exec(pos.toPoint());
- if (!action) {
- return;
+ if (action) {
+ if (action == emptyTrashAction) {
+ emptyTrash();
+ } else if (action == addAction) {
+ addEntry();
+ } else if (action == editAction) {
+ editEntry(index);
+ } else if (action == removeAction) {
+ m_model->removeItem(index);
+ } else if (action == hideAction) {
+ } else if (action == showAllAction) {
+ } else if (action == tearDownAction) {
+ } else if (action == ejectAction) {
+ }
}
- if (action == emptyTrashAction) {
- emptyTrash();
- } else if (action == addAction) {
- addEntry();
- } else if (action == editAction) {
- editEntry(index);
- } else if (action == removeAction) {
- } else if (action == hideAction) {
- } else if (action == showAllAction) {
- } else if (action == tearDownAction) {
- } else if (action == ejectAction) {
- }
+ selectClosestItem();
}
void PlacesPanel::slotViewContextMenuRequested(const QPointF& pos)
if (action == addAction) {
addEntry();
}
+
+ selectClosestItem();
}
void PlacesPanel::slotUrlsDropped(const KUrl& dest, QDropEvent* event, QWidget* parent)
void PlacesPanel::addEntry()
{
+ const int index = m_controller->selectionManager()->currentItem();
+ const KUrl url = m_model->data(index).value("url").value<KUrl>();
+
QPointer<PlacesItemEditDialog> dialog = new PlacesItemEditDialog(this);
dialog->setCaption(i18nc("@title:window", "Add Places Entry"));
dialog->setAllowGlobal(true);
+ dialog->setUrl(url);
if (dialog->exec() == QDialog::Accepted) {
- // TODO
+ KStandardItem* item = createStandardItemFromDialog(dialog);
+
+ // Insert the item as last item of the "Places" group
+ bool inserted = false;
+ int i = 0;
+ while (!inserted && i < m_model->count()) {
+ if (m_model->item(i)->group() != m_model->placesGroupName()) {
+ m_model->insertItem(i, item);
+ inserted = true;
+ }
+ ++i;
+ }
+
+ if (!inserted) {
+ m_model->appendItem(item);
+ }
}
delete dialog;
void PlacesPanel::editEntry(int index)
{
- const QHash<QByteArray, QVariant> data = m_model->data(index);
+ QHash<QByteArray, QVariant> data = m_model->data(index);
QPointer<PlacesItemEditDialog> dialog = new PlacesItemEditDialog(this);
dialog->setCaption(i18nc("@title:window", "Edit Places Entry"));
dialog->setUrl(data.value("url").value<KUrl>());
dialog->setAllowGlobal(true);
if (dialog->exec() == QDialog::Accepted) {
- // TODO
+ KStandardItem* oldItem = m_model->item(index);
+ if (oldItem) {
+ KStandardItem* item = createStandardItemFromDialog(dialog);
+ item->setGroup(oldItem->group());
+ m_model->replaceItem(index, item);
+ }
}
delete dialog;
}
+void PlacesPanel::selectClosestItem()
+{
+ const int index = m_model->closestItem(url());
+ KItemListSelectionManager* selectionManager = m_controller->selectionManager();
+ selectionManager->setCurrentItem(index);
+ selectionManager->clearSelection();
+ selectionManager->setSelected(index);
+}
+
+KStandardItem* PlacesPanel::createStandardItemFromDialog(PlacesItemEditDialog* dialog) const
+{
+ Q_ASSERT(dialog);
+
+ KStandardItem* item = new KStandardItem();
+ item->setIcon(KIcon(dialog->icon()));
+ item->setText(dialog->text());
+ item->setDataValue("url", dialog->url());
+ item->setGroup(m_model->placesGroupName());
+
+ return item;
+}
+
#include "placespanel.moc"
#include <KUrl>
#include <panels/panel.h>
+class KStandardItem;
class KItemListController;
+class PlacesItemEditDialog;
class PlacesItemModel;
/**
void addEntry();
void editEntry(int index);
+ /**
+ * Selects the item that has the closest URL for the URL set
+ * for the panel (see Panel::setUrl()).
+ */
+ void selectClosestItem();
+
+ /**
+ * @return New instance of a KStandardItem containing the properties that have
+ * been set in the places-dialog.
+ */
+ KStandardItem* createStandardItemFromDialog(PlacesItemEditDialog* dialog) const;
+
private:
KItemListController* m_controller;
PlacesItemModel* m_model;