kdelibs/kfile/kfileplacesmodel.cpp
Ivailo Monev 5cb62b9388 solid: use QString instead of QVariant for the Solid::StorageAccess signals arguments
to avoid needless conversion to and from QVariant

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2023-07-05 07:03:18 +03:00

846 lines
26 KiB
C++

/* This file is part of the KDE project
Copyright (C) 2007 Kevin Ottens <ervin@kde.org>
Copyright (C) 2007 David Faure <faure@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kfileplacesmodel.h"
#include "kfileplacesitem_p.h"
#include <QtCore/QMimeData>
#include <QtCore/QTimer>
#include <QtCore/QFile>
#include <QtGui/QColor>
#include <QtGui/QAction>
#include <kfileitem.h>
#include <kglobal.h>
#include <klocale.h>
#include <kuser.h>
#include <kstandarddirs.h>
#include <kcomponentdata.h>
#include <kicon.h>
#include <kmimetype.h>
#include <kdebug.h>
#include <kbookmarkmanager.h>
#include <kbookmark.h>
#include <kio/netaccess.h>
#include <kprotocolinfo.h>
#include <solid/devicenotifier.h>
#include <solid/storageaccess.h>
#include <solid/storagedrive.h>
#include <solid/storagevolume.h>
#include <solid/opticaldrive.h>
#include <solid/opticaldisc.h>
#include <solid/portablemediaplayer.h>
#include <solid/predicate.h>
class KFilePlacesModel::Private
{
public:
Private(KFilePlacesModel *self) : q(self), bookmarkManager(0) {}
~Private()
{
qDeleteAll(items);
}
KFilePlacesModel *q;
QList<KFilePlacesItem*> items;
QSet<QString> availableDevices;
QMap<QObject*, QPersistentModelIndex> setupInProgress;
Solid::Predicate predicate;
KBookmarkManager *bookmarkManager;
void reloadAndSignal();
QList<KFilePlacesItem *> loadBookmarkList();
void _k_initDeviceList();
void _k_deviceAdded(const QString &udi);
void _k_deviceRemoved(const QString &udi);
void _k_contentChanged(const QString &udi, const bool hascontent);
void _k_itemChanged(const QString &udi);
void _k_reloadBookmarks();
void _k_storageSetupDone(Solid::ErrorType error, const QString &errorData, const QString &udi);
void _k_storageTeardownDone(Solid::ErrorType error, const QString &errorData, const QString &udi);
};
KFilePlacesModel::KFilePlacesModel(QObject *parent)
: QAbstractItemModel(parent), d(new Private(this))
{
// TODO: use XDG shortcuts.xbel instead, see:
// https://www.freedesktop.org/wiki/Specifications/desktop-bookmark-spec/
const QString file = KStandardDirs::locateLocal("data", "kfileplaces/bookmarks.xml");
d->bookmarkManager = KBookmarkManager::managerForFile(file, "kfilePlaces");
KBookmarkGroup root = d->bookmarkManager->root();
if (root.first().isNull()) {
// NOTE: The context for these I18N_NOOP2 calls has to be "KFile System Bookmarks".
// The real i18nc call is made later, with this context, so the two must match.
//
// createSystemBookmark actually does nothing with its third argument,
// but we have to give it something so the I18N_NOOP2 calls stay here for now.
//
// (coles, 13th May 2009)
KFilePlacesItem::createSystemBookmark(d->bookmarkManager,
"Home", I18N_NOOP2("KFile System Bookmarks", "Home"),
KUrl(KUser().homeDir()), "user-home");
KFilePlacesItem::createSystemBookmark(d->bookmarkManager,
"Network", I18N_NOOP2("KFile System Bookmarks", "Network"),
KUrl("remote:/"), "network-workgroup");
KFilePlacesItem::createSystemBookmark(d->bookmarkManager,
"Root", I18N_NOOP2("KFile System Bookmarks", "Root"),
KUrl("/"), "folder-red");
KFilePlacesItem::createSystemBookmark(d->bookmarkManager,
"Trash", I18N_NOOP2("KFile System Bookmarks", "Trash"),
KUrl("trash:/"), "user-trash");
// Force bookmarks to be saved.
d->bookmarkManager->saveAs(file);
}
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']");
}
d->predicate = Solid::Predicate::fromString(predicate);
Q_ASSERT(d->predicate.isValid());
connect(d->bookmarkManager, SIGNAL(changed(QString,QString)),
this, SLOT(_k_reloadBookmarks()));
connect(d->bookmarkManager, SIGNAL(bookmarksChanged(QString)),
this, SLOT(_k_reloadBookmarks()));
d->_k_reloadBookmarks();
QTimer::singleShot(0, this, SLOT(_k_initDeviceList()));
}
KFilePlacesModel::~KFilePlacesModel()
{
delete d;
}
KUrl KFilePlacesModel::url(const QModelIndex &index) const
{
return KUrl(data(index, UrlRole).toUrl());
}
bool KFilePlacesModel::setupNeeded(const QModelIndex &index) const
{
return data(index, SetupNeededRole).toBool();
}
KIcon KFilePlacesModel::icon(const QModelIndex &index) const
{
return KIcon(data(index, Qt::DecorationRole).value<QIcon>());
}
QString KFilePlacesModel::text(const QModelIndex &index) const
{
return data(index, Qt::DisplayRole).toString();
}
bool KFilePlacesModel::isHidden(const QModelIndex &index) const
{
return data(index, HiddenRole).toBool();
}
bool KFilePlacesModel::isDevice(const QModelIndex &index) const
{
if (!index.isValid())
return false;
KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
return item->isDevice();
}
Solid::Device KFilePlacesModel::deviceForIndex(const QModelIndex &index) const
{
if (!index.isValid())
return Solid::Device();
KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
if (item->isDevice()) {
return item->device();
} else {
return Solid::Device();
}
}
KBookmark KFilePlacesModel::bookmarkForIndex(const QModelIndex &index) const
{
if (!index.isValid())
return KBookmark();
KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
if (!item->isDevice()) {
return item->bookmark();
} else {
return KBookmark();
}
}
QVariant KFilePlacesModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
return item->data(role);
}
QModelIndex KFilePlacesModel::index(int row, int column, const QModelIndex &parent) const
{
if (row<0 || column!=0 || row>=d->items.size())
return QModelIndex();
if (parent.isValid())
return QModelIndex();
return createIndex(row, column, d->items.at(row));
}
QModelIndex KFilePlacesModel::parent(const QModelIndex &child) const
{
Q_UNUSED(child);
return QModelIndex();
}
int KFilePlacesModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
else
return d->items.size();
}
int KFilePlacesModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
// We only know 1 piece of information for a particular entry
return 1;
}
QModelIndex KFilePlacesModel::closestItem(const KUrl &url) const
{
int foundRow = -1;
int maxLength = 0;
// Search the item which is equal to the URL or at least is a parent URL.
// If there are more than one possible item URL candidates, choose the item
// which covers the bigger range of the URL.
for (int row = 0; row<d->items.size(); ++row) {
KFilePlacesItem *item = d->items[row];
KUrl itemUrl = KUrl(item->data(UrlRole).toUrl());
if (itemUrl.isParentOf(url)) {
const int length = itemUrl.prettyUrl().length();
if (length > maxLength) {
foundRow = row;
maxLength = length;
}
}
}
if (foundRow==-1)
return QModelIndex();
else
return createIndex(foundRow, 0, d->items[foundRow]);
}
void KFilePlacesModel::Private::_k_initDeviceList()
{
Solid::DeviceNotifier *notifier = Solid::DeviceNotifier::instance();
connect(notifier, SIGNAL(deviceAdded(QString)),
q, SLOT(_k_deviceAdded(QString)));
connect(notifier, SIGNAL(deviceRemoved(QString)),
q, SLOT(_k_deviceRemoved(QString)));
connect(notifier, SIGNAL(contentChanged(QString,bool)),
q, SLOT(_k_contentChanged(QString,bool)));
const QList<Solid::Device> &deviceList = Solid::Device::listFromQuery(predicate);
foreach(const Solid::Device &device, deviceList) {
availableDevices << device.udi();
}
_k_reloadBookmarks();
}
void KFilePlacesModel::Private::_k_deviceAdded(const QString &udi)
{
Solid::Device d(udi);
if (predicate.matches(d)) {
availableDevices << udi;
_k_reloadBookmarks();
}
}
void KFilePlacesModel::Private::_k_deviceRemoved(const QString &udi)
{
if (availableDevices.contains(udi)) {
availableDevices.remove(udi);
_k_reloadBookmarks();
}
}
void KFilePlacesModel::Private::_k_contentChanged(const QString &udi, const bool hascontent)
{
if (hascontent) {
_k_deviceAdded(udi);
} else {
_k_deviceRemoved(udi);
}
}
void KFilePlacesModel::Private::_k_itemChanged(const QString &id)
{
for (int row = 0; row<items.size(); ++row) {
if (items.at(row)->id()==id) {
QModelIndex index = q->index(row, 0);
emit q->dataChanged(index, index);
}
}
}
void KFilePlacesModel::Private::_k_reloadBookmarks()
{
QList<KFilePlacesItem*> currentItems = loadBookmarkList();
QList<KFilePlacesItem*>::Iterator it_i = items.begin();
QList<KFilePlacesItem*>::Iterator it_c = currentItems.begin();
QList<KFilePlacesItem*>::Iterator end_i = items.end();
QList<KFilePlacesItem*>::Iterator end_c = currentItems.end();
while (it_i!=end_i || it_c!=end_c) {
if (it_i==end_i && it_c!=end_c) {
int row = items.count();
q->beginInsertRows(QModelIndex(), row, row);
it_i = items.insert(it_i, *it_c);
++it_i;
it_c = currentItems.erase(it_c);
end_i = items.end();
end_c = currentItems.end();
q->endInsertRows();
} else if (it_i!=end_i && it_c==end_c) {
int row = items.indexOf(*it_i);
q->beginRemoveRows(QModelIndex(), row, row);
delete *it_i;
it_i = items.erase(it_i);
end_i = items.end();
end_c = currentItems.end();
q->endRemoveRows();
} else if ((*it_i)->id()==(*it_c)->id()) {
bool shouldEmit = !((*it_i)->bookmark()==(*it_c)->bookmark());
(*it_i)->setBookmark((*it_c)->bookmark());
if (shouldEmit) {
int row = items.indexOf(*it_i);
QModelIndex idx = q->index(row, 0);
emit q->dataChanged(idx, idx);
}
++it_i;
++it_c;
} else if ((*it_i)->id()!=(*it_c)->id()) {
int row = items.indexOf(*it_i);
if (it_i+1!=end_i && (*(it_i+1))->id()==(*it_c)->id()) { // if the next one matches, it's a remove
q->beginRemoveRows(QModelIndex(), row, row);
delete *it_i;
it_i = items.erase(it_i);
end_i = items.end();
end_c = currentItems.end();
q->endRemoveRows();
} else {
q->beginInsertRows(QModelIndex(), row, row);
it_i = items.insert(it_i, *it_c);
++it_i;
it_c = currentItems.erase(it_c);
end_i = items.end();
end_c = currentItems.end();
q->endInsertRows();
}
}
}
qDeleteAll(currentItems);
currentItems.clear();
}
QList<KFilePlacesItem *> KFilePlacesModel::Private::loadBookmarkList()
{
QList<KFilePlacesItem*> items;
KBookmarkGroup root = bookmarkManager->root();
KBookmark bookmark = root.first();
QSet<QString> devices = availableDevices;
while (!bookmark.isNull()) {
QString udi = bookmark.metaDataItem("UDI");
QString appName = bookmark.metaDataItem("OnlyInApp");
bool deviceAvailable = devices.remove(udi);
bool allowedHere = appName.isEmpty() || (appName==KGlobal::mainComponent().componentName());
if ((udi.isEmpty() && allowedHere) || deviceAvailable) {
KFilePlacesItem *item;
if (deviceAvailable) {
item = new KFilePlacesItem(bookmark, udi);
// TODO: Update bookmark internal element
} else {
item = new KFilePlacesItem(bookmark);
}
connect(item, SIGNAL(itemChanged(QString)),
q, SLOT(_k_itemChanged(QString)));
items << item;
}
bookmark = root.next(bookmark);
}
// Add bookmarks for the remaining devices, they were previously unknown
foreach (const QString &udi, devices) {
bookmark = KFilePlacesItem::createDeviceBookmark(bookmarkManager, udi);
if (!bookmark.isNull()) {
KFilePlacesItem *item = new KFilePlacesItem(bookmark, udi);
connect(item, SIGNAL(itemChanged(QString)),
q, SLOT(_k_itemChanged(QString)));
// TODO: Update bookmark internal element
items << item;
}
}
return items;
}
void KFilePlacesModel::Private::reloadAndSignal()
{
bookmarkManager->emitChanged(bookmarkManager->root()); // ... we'll get relisted anyway
}
Qt::DropActions KFilePlacesModel::supportedDropActions() const
{
return Qt::ActionMask;
}
Qt::ItemFlags KFilePlacesModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags res = Qt::ItemIsSelectable|Qt::ItemIsEnabled;
if (index.isValid())
res|= Qt::ItemIsDragEnabled;
if (!index.isValid())
res|= Qt::ItemIsDropEnabled;
return res;
}
static QString _k_internalMimetype(const KFilePlacesModel * const self)
{
return QString("application/x-kfileplacesmodel-")+QString::number((qptrdiff)self);
}
QStringList KFilePlacesModel::mimeTypes() const
{
QStringList types;
types << _k_internalMimetype(this) << "text/uri-list";
return types;
}
QMimeData *KFilePlacesModel::mimeData(const QModelIndexList &indexes) const
{
KUrl::List urls;
QByteArray itemData;
QDataStream stream(&itemData, QIODevice::WriteOnly);
foreach (const QModelIndex &index, indexes) {
KUrl itemUrl = url(index);
if (itemUrl.isValid())
urls << itemUrl;
stream << index.row();
}
QMimeData *mimeData = new QMimeData();
if (!urls.isEmpty())
urls.populateMimeData(mimeData);
mimeData->setData(_k_internalMimetype(this), itemData);
return mimeData;
}
bool KFilePlacesModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
int row, int column, const QModelIndex &parent)
{
if (action == Qt::IgnoreAction)
return true;
if (column > 0)
return false;
if (row==-1 && parent.isValid()) {
return false; // Don't allow to move an item onto another one,
// too easy for the user to mess something up
// If we really really want to allow copying files this way,
// let's do it in the views to get the good old drop menu
}
KBookmark afterBookmark;
if (row==-1) {
// The dropped item is moved or added to the last position
KFilePlacesItem *lastItem = d->items.last();
afterBookmark = lastItem->bookmark();
} else {
// The dropped item is moved or added before position 'row', ie after position 'row-1'
if (row>0) {
KFilePlacesItem *afterItem = d->items[row-1];
afterBookmark = afterItem->bookmark();
}
}
if (data->hasFormat(_k_internalMimetype(this))) {
// The operation is an internal move
QByteArray itemData = data->data(_k_internalMimetype(this));
QDataStream stream(&itemData, QIODevice::ReadOnly);
int itemRow;
stream >> itemRow;
KFilePlacesItem *item = d->items[itemRow];
KBookmark bookmark = item->bookmark();
int destRow = row == -1 ? d->items.count() : row;
// The item is not moved when the drop indicator is on either item edge
if (itemRow == destRow || itemRow + 1 == destRow) {
return false;
}
beginMoveRows(QModelIndex(), itemRow, itemRow, QModelIndex(), destRow);
d->bookmarkManager->root().moveBookmark(bookmark, afterBookmark);
// Move item ourselves so that _k_reloadBookmarks() does not consider
// the move as a remove + insert.
//
// 2nd argument of QList::move() expects the final destination index,
// but 'row' is the value of the destination index before the moved
// item has been removed from its original position. That is why we
// adjust if necessary.
d->items.move(itemRow, itemRow < destRow ? (destRow - 1) : destRow);
endMoveRows();
} else if (data->hasFormat("text/uri-list")) {
// The operation is an add
KUrl::List urls = KUrl::List::fromMimeData(data);
KBookmarkGroup group = d->bookmarkManager->root();
foreach (const KUrl &url, urls) {
// TODO: use KIO::stat in order to get the UDS_DISPLAY_NAME too
KMimeType::Ptr mimetype = KMimeType::mimeType(KIO::NetAccess::mimetype(url, 0));
if (!mimetype) {
kWarning() << "URL not added to Places as mimetype could not be determined!";
continue;
}
if (!mimetype->is("inode/directory")) {
// Only directories are allowed
continue;
}
KBookmark bookmark = KFilePlacesItem::createBookmark(d->bookmarkManager,
url.fileName(), url,
mimetype->iconName(url));
group.moveBookmark(bookmark, afterBookmark);
afterBookmark = bookmark;
}
} else {
// Oops, shouldn't happen thanks to mimeTypes()
kWarning() << ": received wrong mimedata, " << data->formats();
return false;
}
d->reloadAndSignal();
return true;
}
void KFilePlacesModel::addPlace(const QString &text, const KUrl &url,
const QString &iconName, const QString &appName)
{
addPlace(text, url, iconName, appName, QModelIndex());
}
void KFilePlacesModel::addPlace(const QString &text, const KUrl &url,
const QString &iconName, const QString &appName,
const QModelIndex &after)
{
KBookmark bookmark = KFilePlacesItem::createBookmark(d->bookmarkManager,
text, url, iconName);
if (!appName.isEmpty()) {
bookmark.setMetaDataItem("OnlyInApp", appName);
}
if (after.isValid()) {
KFilePlacesItem *item = static_cast<KFilePlacesItem*>(after.internalPointer());
d->bookmarkManager->root().moveBookmark(bookmark, item->bookmark());
}
d->reloadAndSignal();
}
void KFilePlacesModel::editPlace(const QModelIndex &index, const QString &text, const KUrl &url,
const QString &iconName, const QString &appName)
{
if (!index.isValid()) return;
KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
if (item->isDevice()) return;
KBookmark bookmark = item->bookmark();
if (bookmark.isNull()) return;
bookmark.setFullText(text);
bookmark.setUrl(url);
bookmark.setIcon(iconName);
bookmark.setMetaDataItem("OnlyInApp", appName);
d->reloadAndSignal();
emit dataChanged(index, index);
}
void KFilePlacesModel::removePlace(const QModelIndex &index) const
{
if (!index.isValid()) return;
KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
if (item->isDevice()) return;
KBookmark bookmark = item->bookmark();
if (bookmark.isNull()) return;
d->bookmarkManager->root().deleteBookmark(bookmark);
d->reloadAndSignal();
}
void KFilePlacesModel::setPlaceHidden(const QModelIndex &index, bool hidden)
{
if (!index.isValid()) return;
KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
KBookmark bookmark = item->bookmark();
if (bookmark.isNull()) return;
bookmark.setMetaDataItem("IsHidden", (hidden ? "true" : "false"));
d->reloadAndSignal();
emit dataChanged(index, index);
}
int KFilePlacesModel::hiddenCount() const
{
int rows = rowCount();
int hidden = 0;
for (int i=0; i<rows; ++i) {
if (isHidden(index(i, 0))) {
hidden++;
}
}
return hidden;
}
QAction *KFilePlacesModel::teardownActionForIndex(const QModelIndex &index) const
{
Solid::Device device = deviceForIndex(index);
if (device.is<Solid::StorageAccess>() && device.as<Solid::StorageAccess>()->isAccessible()) {
Solid::StorageDrive *drive = device.as<Solid::StorageDrive>();
bool hotpluggable = false;
bool removable = false;
if (drive!=0) {
hotpluggable = drive->isHotpluggable();
removable = drive->isRemovable();
}
QString iconName;
QString text;
QString label = data(index, Qt::DisplayRole).toString().replace('&',"&&");
if (device.is<Solid::OpticalDisc>()) {
text = i18n("&Release '%1'", label);
} else if (removable || hotpluggable) {
text = i18n("&Safely Remove '%1'", label);
iconName = "media-eject";
} else {
text = i18n("&Unmount '%1'", label);
iconName = "media-eject";
}
if (!iconName.isEmpty()) {
return new QAction(KIcon(iconName), text, 0);
} else {
return new QAction(text, 0);
}
}
return 0;
}
QAction *KFilePlacesModel::ejectActionForIndex(const QModelIndex &index) const
{
Solid::Device device = deviceForIndex(index);
if (device.is<Solid::OpticalDisc>()) {
QString label = data(index, Qt::DisplayRole).toString().replace('&',"&&");
QString text = i18n("&Eject '%1'", label);
return new QAction(KIcon("media-eject"), text, 0);
}
return 0;
}
void KFilePlacesModel::requestTeardown(const QModelIndex &index)
{
Solid::Device device = deviceForIndex(index);
Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
if (access!=0) {
connect(access, SIGNAL(teardownDone(Solid::ErrorType,QString,QString)),
this, SLOT(_k_storageTeardownDone(Solid::ErrorType,QString,QString)));
access->teardown();
}
}
void KFilePlacesModel::requestEject(const QModelIndex &index)
{
Solid::Device device = deviceForIndex(index);
Solid::OpticalDrive *drive = device.as<Solid::OpticalDrive>();
if (drive!=0) {
connect(drive, SIGNAL(ejectDone(Solid::ErrorType,QString,QString)),
this, SLOT(_k_storageTeardownDone(Solid::ErrorType,QString,QString)));
drive->eject();
} else {
QString label = data(index, Qt::DisplayRole).toString().replace('&',"&&");
QString message = i18n("The device '%1' is not a disk and cannot be ejected.", label);
emit errorMessage(message);
}
}
void KFilePlacesModel::requestSetup(const QModelIndex &index)
{
Solid::Device device = deviceForIndex(index);
if (device.is<Solid::StorageAccess>()
&& !d->setupInProgress.contains(device.as<Solid::StorageAccess>())
&& !device.as<Solid::StorageAccess>()->isAccessible()) {
Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
d->setupInProgress[access] = index;
connect(access, SIGNAL(setupDone(Solid::ErrorType,QString,QString)),
this, SLOT(_k_storageSetupDone(Solid::ErrorType,QString,QString)));
access->setup();
}
}
void KFilePlacesModel::Private::_k_storageSetupDone(Solid::ErrorType error, const QString &errorData, const QString &udi)
{
Q_UNUSED(udi);
QPersistentModelIndex index = setupInProgress.take(q->sender());
if (!index.isValid()) {
return;
}
if (!error) {
emit q->setupDone(index, true);
} else {
if (!errorData.isEmpty()) {
emit q->errorMessage(i18n("An error occurred while accessing '%1', the system responded: %2",
q->text(index),
errorData));
} else {
emit q->errorMessage(i18n("An error occurred while accessing '%1'",
q->text(index)));
}
emit q->setupDone(index, false);
}
}
void KFilePlacesModel::Private::_k_storageTeardownDone(Solid::ErrorType error, const QString &errorData, const QString &udi)
{
Q_UNUSED(udi);
if (error && !errorData.isEmpty()) {
emit q->errorMessage(errorData);
}
}
#include "moc_kfileplacesmodel.cpp"