You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
253 lines
7.5 KiB
253 lines
7.5 KiB
/* |
|
* Copyright 2013 Bhushan Shah <bhush94@gmail.com> |
|
* |
|
* 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) version 3 or any later version |
|
* accepted by the membership of KDE e.V. (or its successor approved |
|
* by the membership of KDE e.V.), which shall act as a proxy |
|
* defined in Section 14 of version 3 of the license. |
|
* |
|
* 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, see <http://www.gnu.org/licenses/> |
|
*/ |
|
|
|
#include "icon_p.h" |
|
|
|
#include <QApplication> |
|
#include <QDesktopWidget> |
|
#include <QDropEvent> |
|
#include <QFileInfo> |
|
#include <QJsonArray> |
|
#include <QMimeData> |
|
|
|
#include <KConfigGroup> |
|
#include <KFileItem> |
|
#include <KDesktopFile> |
|
#include <KRun> |
|
#include <KService> |
|
#include <KShell> |
|
#include <QMimeType> |
|
#include <QMimeDatabase> |
|
|
|
#include <KIO/Global> |
|
#include <KIO/DropJob> |
|
#include <KIO/StatJob> |
|
#include <KJobWidgets> |
|
|
|
IconPrivate::IconPrivate() { |
|
} |
|
|
|
IconPrivate::~IconPrivate() { |
|
} |
|
|
|
void IconPrivate::setUrl(const QUrl &url) |
|
{ |
|
if (url.isLocalFile()) { |
|
setUrlInternal(url); |
|
} else { |
|
KIO::StatJob *statJob = KIO::mostLocalUrl(url, KIO::HideProgressInfo); |
|
|
|
connect(statJob, &KJob::result, [=](KJob *job) { |
|
if (!job->error()) { |
|
setUrlInternal(static_cast<KIO::StatJob*>(job)->mostLocalUrl()); |
|
} |
|
}); |
|
|
|
statJob->start(); |
|
} |
|
} |
|
|
|
void IconPrivate::setUrlInternal(const QUrl &url) |
|
{ |
|
m_url = url; |
|
|
|
if (m_url.isLocalFile()) { |
|
const KFileItem fileItem(m_url); |
|
const QFileInfo fi(m_url.toLocalFile()); |
|
|
|
if (fileItem.isDesktopFile()) { |
|
const KDesktopFile f(m_url.toLocalFile()); |
|
m_name = f.readName(); |
|
m_icon = f.readIcon(); |
|
m_genericName = f.readGenericName(); |
|
if (m_name.isNull()) { |
|
m_name = QFileInfo(m_url.toLocalFile()).fileName(); |
|
} |
|
|
|
m_jumpListActions.clear(); |
|
|
|
const QStringList &actions = f.readActions(); |
|
|
|
foreach (const QString &actionName, actions) { |
|
const KConfigGroup &actionGroup = f.actionGroup(actionName); |
|
|
|
if (!actionGroup.isValid() || !actionGroup.exists()) { |
|
continue; |
|
} |
|
|
|
const QString &name = actionGroup.readEntry(QStringLiteral("Name")); |
|
const QString &exec = actionGroup.readEntry(QStringLiteral("Exec")); |
|
if (name.isEmpty() || exec.isEmpty()) { |
|
continue; |
|
} |
|
|
|
m_jumpListActions << QVariantMap{ |
|
{QStringLiteral("name"), name}, |
|
{QStringLiteral("icon"), actionGroup.readEntry("Icon")}, |
|
{QStringLiteral("exec"), exec} |
|
}; |
|
} |
|
} else { |
|
QMimeDatabase db; |
|
m_name = fi.baseName(); |
|
m_icon = db.mimeTypeForUrl(m_url).iconName(); |
|
m_genericName = fi.baseName(); |
|
} |
|
} else { |
|
if (m_url.scheme().contains(QStringLiteral("http"))) { |
|
m_name = m_url.host(); |
|
} else if (m_name.isEmpty()) { |
|
m_name = m_url.toString(); |
|
if (m_name.endsWith(QLatin1String(":/"))) { |
|
m_name = m_url.scheme(); |
|
} |
|
} |
|
m_icon = KIO::iconNameForUrl(url); |
|
} |
|
|
|
emit urlChanged(m_url); |
|
emit nameChanged(m_name); |
|
emit iconChanged(m_icon); |
|
emit genericNameChanged(m_genericName); |
|
emit jumpListActionsChanged(m_jumpListActions); |
|
} |
|
|
|
QUrl IconPrivate::url() const |
|
{ |
|
return m_url; |
|
} |
|
|
|
QString IconPrivate::name() const |
|
{ |
|
return m_name; |
|
} |
|
|
|
QString IconPrivate::icon() const |
|
{ |
|
return m_icon; |
|
} |
|
|
|
QString IconPrivate::genericName() const |
|
{ |
|
return m_genericName; |
|
} |
|
|
|
QVariantList IconPrivate::jumpListActions() const |
|
{ |
|
return m_jumpListActions; |
|
} |
|
|
|
bool IconPrivate::processDrop(QObject *dropEvent) |
|
{ |
|
Q_ASSERT(dropEvent); |
|
|
|
// DeclarativeDropEvent and co aren't public |
|
const QObject *mimeData = qvariant_cast<QObject *>(dropEvent->property("mimeData")); |
|
Q_ASSERT(mimeData); |
|
|
|
const QJsonArray &droppedUrls = mimeData->property("urls").toJsonArray(); |
|
|
|
QList<QUrl> urls; |
|
urls.reserve(droppedUrls.count()); |
|
foreach (const QJsonValue &droppedUrl, droppedUrls) { |
|
const QUrl url = QUrl::fromUserInput(droppedUrl.toString(), QString(), QUrl::AssumeLocalFile); |
|
if (url.isValid()) { |
|
urls.append(url); |
|
} |
|
} |
|
|
|
if (urls.isEmpty()) { |
|
return false; |
|
} |
|
|
|
const QString stringUrl = m_url.toLocalFile(); |
|
|
|
QMimeDatabase db; |
|
const QMimeType mimeType = db.mimeTypeForUrl(m_url); |
|
|
|
if (KDesktopFile::isDesktopFile(stringUrl)) { |
|
const KDesktopFile desktopFile(stringUrl); |
|
const QStringList &supportedMimeTypes = desktopFile.readMimeTypes(); |
|
|
|
// if no mime types are given just execute the command in the Desktop file |
|
if (supportedMimeTypes.isEmpty()) { |
|
KService service(stringUrl); |
|
KRun::runService(service, urls, nullptr); |
|
return true; |
|
} |
|
|
|
// otherwise check if the applicaton supports the dropped type |
|
// TODO should we execute if *any* of the urls are supported, or if *all* are? |
|
foreach (const QUrl &url, urls) { |
|
const QMimeType dropMimeType = db.mimeTypeForUrl(url); |
|
|
|
foreach (const QString &supportedType, supportedMimeTypes) { |
|
if (dropMimeType.inherits(supportedType)) { |
|
KService service(stringUrl); |
|
KRun::runService(service, urls, nullptr); |
|
return true; |
|
} |
|
} |
|
} |
|
|
|
return false; |
|
} |
|
|
|
if (mimeType.inherits(QStringLiteral("application/x-executable")) || mimeType.inherits(QStringLiteral("application/x-shellscript"))) { |
|
QString params; |
|
foreach (const QUrl &url, urls) { |
|
// TODO toEncoded? |
|
params += QLatin1Char(' ') + KShell::quoteArg(url.isLocalFile() ? url.toLocalFile() : url.toEncoded()); |
|
} |
|
|
|
KRun::runCommand(KShell::quoteArg(m_url.path()) + QLatin1Char(' ') + params, nullptr); |
|
return true; |
|
} else if (mimeType.inherits(QStringLiteral("inode/directory"))) { |
|
QMimeData mimeData; |
|
mimeData.setUrls(urls); |
|
|
|
// DeclarativeDropEvent isn't public |
|
QDropEvent de(QPointF(dropEvent->property("x").toInt(), dropEvent->property("y").toInt()), |
|
static_cast<Qt::DropActions>(dropEvent->property("proposedActions").toInt()), |
|
&mimeData, |
|
static_cast<Qt::MouseButtons>(dropEvent->property("buttons").toInt()), |
|
static_cast<Qt::KeyboardModifiers>(dropEvent->property("modifiers").toInt())); |
|
|
|
KIO::DropJob *dropJob = KIO::drop(&de, m_url); |
|
KJobWidgets::setWindow(dropJob, QApplication::desktop()); |
|
} |
|
|
|
return false; |
|
} |
|
|
|
void IconPrivate::open() |
|
{ |
|
new KRun(m_url, 0); |
|
} |
|
|
|
void IconPrivate::execJumpList(int index) |
|
{ |
|
const QString &exec = m_jumpListActions.at(index).toMap().value(QStringLiteral("exec")).toString(); |
|
if (exec.isEmpty()) { |
|
return; |
|
} |
|
|
|
KRun::run(exec, {}, nullptr, m_name, m_icon); |
|
}
|
|
|