.directory
*.kdev4
/build*/
+.cmake/
# KDE Application Version, managed by release script
set (RELEASE_SERVICE_VERSION_MAJOR "20")
-set (RELEASE_SERVICE_VERSION_MINOR "04")
-set (RELEASE_SERVICE_VERSION_MICRO "0")
+set (RELEASE_SERVICE_VERSION_MINOR "07")
+set (RELEASE_SERVICE_VERSION_MICRO "70")
set (RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
project(Dolphin VERSION ${RELEASE_SERVICE_VERSION})
set(QT_MIN_VERSION "5.11.0")
-set(KF5_MIN_VERSION "5.67.0")
+set(KF5_MIN_VERSION "5.70.0")
# ECM setup
find_package(ECM ${KF5_MIN_VERSION} CONFIG REQUIRED)
qt5_generate_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/dolphinmainwindow.h org.kde.DolphinMainWindow.xml)
qt5_add_dbus_adaptor(dolphinstatic_SRCS ${CMAKE_CURRENT_BINARY_DIR}/org.kde.DolphinMainWindow.xml dolphinmainwindow.h DolphinMainWindow)
qt5_add_dbus_interface(dolphinstatic_SRCS ${CMAKE_CURRENT_BINARY_DIR}/org.kde.DolphinMainWindow.xml dolphinmainwindowinterface)
+qt5_add_dbus_interface(dolphinstatic_SRCS panels/terminal/org.kde.KIOFuse.VFS.xml kiofuse_interface)
add_library(dolphinstatic STATIC ${dolphinstatic_SRCS})
Q_SCRIPTABLE void ShowItemProperties(const QStringList& uriList, const QString& startUpId);
/**
- * Set whether this interface has been created by dolphin --deamon.
+ * Set whether this interface has been created by dolphin --daemon.
*/
void setAsDaemon();
/**
- * @return Whether this interface has been created by dolphin --deamon.
+ * @return Whether this interface has been created by dolphin --daemon.
*/
bool isDaemon() const;
#include "dolphinmainwindow.h"
#include "dolphinviewcontainer.h"
#include "global.h"
+#include <KActionCollection>
#include <KBookmarkMenu>
#include <KIO/Global>
#include <QDebug>
}
m_bookmarkManager = KBookmarkManager::managerForFile(bookmarksFile, QStringLiteral("dolphin"));
m_bookmarkManager->setUpdate(true);
- m_bookmarkMenu.reset(new KBookmarkMenu(m_bookmarkManager, this, menu, collection));
+ m_bookmarkMenu.reset(new KBookmarkMenu(m_bookmarkManager, this, menu));
+
+ collection->addAction(QStringLiteral("add_bookmark"), m_bookmarkMenu->addBookmarkAction());
+ collection->addAction(QStringLiteral("edit_bookmarks"), m_bookmarkMenu->editBookmarksAction());
+ collection->addAction(QStringLiteral("add_bookmarks_list"), m_bookmarkMenu->bookmarkTabsAsFolderAction());
}
DolphinBookmarkHandler::~DolphinBookmarkHandler()
#include <KDualAction>
#include <KFileItemListProperties>
#include <KHelpMenu>
+#include <KIO/CommandLauncherJob>
#include <KIO/JobUiDelegate>
#include <KIO/OpenFileManagerWindowJob>
#include <KJobWidgets>
command.append("\" \"");
command.append(urlB.toDisplayString(QUrl::PreferLocalFile));
command.append('\"');
- KRun::runCommand(command, QStringLiteral("Kompare"), QStringLiteral("kompare"), this);
+
+ KIO::CommandLauncherJob *job = new KIO::CommandLauncherJob(command, this);
+ job->setDesktopName(QStringLiteral("org.kde.kompare"));
+ job->start();
}
void DolphinMainWindow::toggleShowMenuBar()
void DolphinMainWindow::updateWindowTitle()
{
- const QString newTitle = m_activeViewContainer->caption();
+ const QString newTitle = m_activeViewContainer->captionWindowTitle();
if (windowTitle() != newTitle) {
setWindowTitle(newTitle);
}
#include <KActionCollection>
#include <KAuthorized>
#include <KConfigGroup>
+#include <KDialogJobUiDelegate>
#include <KFileItemListProperties>
#include <KIconLoader>
#include <KJobWidgets>
#include <KMimeTypeEditor>
#include <KNS3/KMoreToolsMenuFactory>
#include <KPluginFactory>
-#include <KRun>
+#include <KIO/CommandLauncherJob>
#include <KSharedConfig>
#include <KToolInvocation>
if (!(actions.isEmpty())) {
actions.first()->trigger();
} else {
- KRun::run(QStringLiteral("kfind"), {url()}, widget());
+ KIO::CommandLauncherJob *job = new KIO::CommandLauncherJob(QStringLiteral("kfind"), {url().toString()}, this);
+ job->setDesktopName(QStringLiteral("org.kde.kfind"));
+ job->setUiDelegate(new KDialogJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, widget()));
+ job->start();
}
}
#include "dolphinviewcontainer.h"
#include <KConfigGroup>
-#include <KRun>
#include <KShell>
#include <kio/global.h>
+#include <KIO/CommandLauncherJob>
#include <KAcceleratorManager>
#include <QApplication>
}
args << QStringLiteral("--new-window");
- const QString command = QStringLiteral("dolphin %1").arg(KShell::joinArgs(args));
- KRun::runCommand(command, this);
+ KIO::CommandLauncherJob *job = new KIO::CommandLauncherJob("dolphin", args, this);
+ job->setDesktopName(QStringLiteral("org.kde.dolphin"));
+ job->start();
closeTab(index);
}
connect(m_searchBox, &DolphinSearchBox::activated, this, &DolphinViewContainer::activate);
connect(m_searchBox, &DolphinSearchBox::closeRequest, this, &DolphinViewContainer::closeSearchBox);
connect(m_searchBox, &DolphinSearchBox::searchRequest, this, &DolphinViewContainer::startSearching);
- connect(m_searchBox, &DolphinSearchBox::returnPressed, this, &DolphinViewContainer::requestFocus);
+ connect(m_searchBox, &DolphinSearchBox::focusViewRequest, this, &DolphinViewContainer::requestFocus);
m_searchBox->setWhatsThis(xi18nc("@info:whatsthis findbar",
"<para>This helps you find files and folders. Enter a <emphasis>"
"search term</emphasis> and specify search settings with the "
m_messageWidget->hide();
}
+QString DolphinViewContainer::captionWindowTitle() const
+{
+ if (GeneralSettings::showFullPathInTitlebar() && !isSearchModeEnabled()) {
+ if (!url().isLocalFile()) {
+ return url().adjusted(QUrl::StripTrailingSlash).toString();
+ }
+ return url().adjusted(QUrl::StripTrailingSlash).path();
+ } else {
+ return DolphinViewContainer::caption();
+ }
+}
+
QString DolphinViewContainer::caption() const
{
if (isSearchModeEnabled()) {
}
}
- if (GeneralSettings::showFullPathInTitlebar()) {
- if (!url().isLocalFile()) {
- return url().adjusted(QUrl::StripTrailingSlash).toString();
- }
- return url().adjusted(QUrl::StripTrailingSlash).path();
- }
-
KFilePlacesModel *placesModel = DolphinPlacesModelSingleton::instance().placesModel();
const auto& matchedPlaces = placesModel->match(placesModel->index(0,0), KFilePlacesModel::UrlRole, QUrl(url().adjusted(QUrl::StripTrailingSlash).toString(QUrl::FullyEncoded).append("/?")), 1, Qt::MatchRegExp);
*/
void reload();
+ /**
+ * @return Returns a Caption suitable for display in the window title.
+ * It is calculated depending on GeneralSettings::showFullPathInTitlebar().
+ * If it's false, it calls caption().
+ */
+ QString captionWindowTitle() const;
+
/**
* @return Returns a Caption suitable for display to the user. It is
* calculated depending on settings, if a search is active and other
#include "dolphindebug.h"
#include "dolphinmainwindowinterface.h"
-#include <KRun>
+#include <KDialogJobUiDelegate>
+#include <KIO/ApplicationLauncherJob>
+#include <KService>
#include <KWindowSystem>
#include <QApplication>
if (!urls.isEmpty()) {
command.append(QLatin1String(" %U"));
}
- KRun::run(
- command,
- urls,
- window,
- QApplication::applicationDisplayName(),
- QApplication::windowIcon().name()
- );
+ KService::Ptr service(new KService(QApplication::applicationDisplayName(), command, QApplication::windowIcon().name()));
+ auto *job = new KIO::ApplicationLauncherJob(service, window);
+ job->setUrls(urls);
+ job->setUiDelegate(new KDialogJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, window));
+ job->start();
}
bool Dolphin::attachToExistingInstance(const QList<QUrl>& inputUrls, bool openFiles, bool splitView, const QString& preferredService)
const QPoint hotSpot((pixmap.width() / pixmap.devicePixelRatio()) / 2, 0);
drag->setHotSpot(hotSpot);
- drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::CopyAction);
+ drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::MoveAction);
QAccessibleEvent accessibilityEvent(view(), QAccessible::DragDropStart);
QAccessible::updateAccessibility(&accessibilityEvent);
<caption xml:lang="pt-BR">Gerenciamento de arquivos no Dolphin</caption>
<caption xml:lang="ru">Управление файлами</caption>
<caption xml:lang="sk">Správa súborov v Dolphin</caption>
+ <caption xml:lang="sl">Upravljanje datotek v Dolphinu</caption>
<caption xml:lang="sv">Filhantering i Dolphin</caption>
<caption xml:lang="uk">Керування файлами у Dolphin</caption>
<caption xml:lang="x-test">xxFile management in Dolphinxx</caption>
if (item.isNull()) {
// No item is hovered and no selection has been done: provide
// an item for the currently shown directory.
- m_folderStatJob = KIO::stat(url(), KIO::HideProgressInfo);
+ m_folderStatJob = KIO::statDetails(url(), KIO::StatJob::SourceSide, KIO::StatDefaultDetails | KIO::StatRecursiveSize, KIO::HideProgressInfo);
if (m_folderStatJob->uiDelegate()) {
KJobWidgets::setWindow(m_folderStatJob, this);
}
// in the case of a search-URL the URL is not readable for humans
// (at least not useful to show in the Information Panel)
m_preview->setPixmap(
- QIcon::fromTheme(QStringLiteral("baloo")).pixmap(KIconLoader::SizeEnormous, KIconLoader::SizeEnormous)
+ QIcon::fromTheme(QStringLiteral("baloo")).pixmap(m_preview->height(), m_preview->width())
);
} else {
m_preview->stopAnimatedImage();
m_preview->setPixmap(
- QIcon::fromTheme(QStringLiteral("dialog-information")).pixmap(KIconLoader::SizeEnormous, KIconLoader::SizeEnormous)
+ QIcon::fromTheme(QStringLiteral("dialog-information")).pixmap(m_preview->height(), m_preview->width())
);
setNameLabelText(i18ncp("@label", "%1 item selected", "%1 items selected", items.count()));
void InformationPanelContent::showIcon(const KFileItem& item)
{
m_outdatedPreviewTimer->stop();
- QPixmap pixmap = QIcon::fromTheme(item.iconName()).pixmap(KIconLoader::SizeEnormous, KIconLoader::SizeEnormous);
+ QPixmap pixmap = QIcon::fromTheme(item.iconName()).pixmap(m_preview->height(), m_preview->width());
KIconLoader::global()->drawOverlays(item.overlays(), pixmap, KIconLoader::Desktop);
m_preview->setPixmap(pixmap);
}
--- /dev/null
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.kde.KIOFuse.VFS">
+ <method name="mountUrl">
+ <arg name="remoteUrl" type="s" direction="in"/>
+ <arg type="s" direction="out"/>
+ </method>
+ <method name="remoteUrl">
+ <arg name="localUrl" type="s" direction="in"/>
+ <arg type="s" direction="out"/>
+ </method>
+ </interface>
+</node>
***************************************************************************/
#include "terminalpanel.h"
+#include "kiofuse_interface.h"
#include <KIO/DesktopExecParser>
#include <KIO/Job>
#include <KJobWidgets>
#include <KLocalizedString>
#include <KMessageWidget>
+#include <KMountPoint>
#include <KParts/ReadOnlyPart>
#include <KPluginFactory>
#include <KPluginLoader>
m_konsolePartMissingMessage(nullptr),
m_konsolePart(nullptr),
m_konsolePartCurrentDirectory(),
- m_sendCdToTerminalHistory()
+ m_sendCdToTerminalHistory(),
+ m_kiofuseInterface(QStringLiteral("org.kde.KIOFuse"),
+ QStringLiteral("/org/kde/KIOFuse"),
+ QDBusConnection::sessionBus())
{
m_layout = new QVBoxLayout(this);
m_layout->setContentsMargins(0, 0, 0, 0);
const QUrl url = statJob->mostLocalUrl();
if (url.isLocalFile()) {
sendCdToTerminal(url.toLocalFile());
+ } else {
+ // URL isn't local, only hope for the terminal to be in sync with the
+ // DolphinView is to mount the remote URL in KIOFuse and point to it.
+ // If we can't do that for any reason, silently fail.
+ auto reply = m_kiofuseInterface.mountUrl(url.toString());
+ QDBusPendingCallWatcher * watcher = new QDBusPendingCallWatcher(reply, this);
+ QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [=] (QDBusPendingCallWatcher* watcher) {
+ watcher->deleteLater();
+ if (!reply.isError()) {
+ // Successfully mounted, point to the KIOFuse equivalent path.
+ sendCdToTerminal(reply.value());
+ }
+ });
}
m_mostLocalUrlJob = nullptr;
}
}
+ // User may potentially be browsing inside a KIOFuse mount.
+ // If so lets try and change the DolphinView to point to the remote URL equivalent.
+ // instead of into the KIOFuse mount itself (which can cause performance issues!)
const QUrl url(QUrl::fromLocalFile(dir));
- emit changeUrl(url);
+
+ KMountPoint::Ptr mountPoint = KMountPoint::currentMountPoints().findByPath(m_konsolePartCurrentDirectory);
+ if (mountPoint && mountPoint->mountType() != QStringLiteral("fuse.kio-fuse")) {
+ // Not in KIOFUse mount, so just switch to the corresponding URL.
+ emit changeUrl(url);
+ return;
+ }
+
+ auto reply = m_kiofuseInterface.remoteUrl(m_konsolePartCurrentDirectory);
+ QDBusPendingCallWatcher * watcher = new QDBusPendingCallWatcher(reply, this);
+ QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [=] (QDBusPendingCallWatcher* watcher) {
+ watcher->deleteLater();
+ if (reply.isError()) {
+ // KIOFuse errored out... just show the normal URL
+ emit changeUrl(url);
+ } else {
+ // Our location happens to be in a KIOFuse mount and is mounted.
+ // Let's change the DolphinView to point to the remote URL equivalent.
+ emit changeUrl(QUrl::fromUserInput(reply.value()));
+ }
+ });
}
bool TerminalPanel::terminalHasFocus() const
#define TERMINALPANEL_H
#include "panels/panel.h"
+#include "kiofuse_interface.h"
#include <QQueue>
KParts::ReadOnlyPart* m_konsolePart;
QString m_konsolePartCurrentDirectory;
QQueue<QString> m_sendCdToTerminalHistory;
+ org::kde::KIOFuse::VFS m_kiofuseInterface;
};
#endif // TERMINALPANEL_H
m_searchInput->clear();
}
}
+ else if (event->key() == Qt::Key_Down) {
+ emit focusViewRequest();
+ }
}
bool DolphinSearchBox::eventFilter(QObject* obj, QEvent* event)
void DolphinSearchBox::slotReturnPressed()
{
emitSearchRequest();
- emit returnPressed();
+ emit focusViewRequest();
}
void DolphinSearchBox::slotFacetChanged()
*/
void searchTextChanged(const QString& text);
- void returnPressed();
-
/**
* Emitted as soon as the search box should get closed.
*/
* @see DolphinSearchBox::setActive()
*/
void activated();
+ void focusViewRequest();
private slots:
void emitSearchRequest();
KIO::filesize_t& totalFileSize) const
{
const int itemCount = m_model->count();
+
+ bool countFileSize = true;
+
+ // In case we have a precomputed value
+ const auto job = KIO::statDetails(m_model->rootItem().url(), KIO::StatJob::SourceSide, KIO::StatRecursiveSize);
+ job->exec();
+ const auto entry = job->statResult();
+ if (entry.contains(KIO::UDSEntry::UDS_RECURSIVE_SIZE)) {
+ totalFileSize = static_cast<KIO::filesize_t>(entry.numberValue(KIO::UDSEntry::UDS_RECURSIVE_SIZE));
+ countFileSize = false;
+ }
+
for (int i = 0; i < itemCount; ++i) {
const KFileItem item = m_model->fileItem(i);
if (item.isDir()) {
++folderCount;
} else {
++fileCount;
- totalFileSize += item.size();
+ if (countFileSize) {
+ totalFileSize += item.size();
+ }
}
}
}
"<para>Hidden items only differ from other ones in that their "
"name starts with a \".\". In general there is no need for "
"users to access them which is why they are hidden.</para>"));
- m_actionCollection->setDefaultShortcuts(showHiddenFiles, {Qt::ALT + Qt::Key_Period, Qt::CTRL + Qt::Key_H, Qt::Key_F8});
+ m_actionCollection->setDefaultShortcuts(showHiddenFiles, KStandardShortcut::showHideHiddenFiles());
connect(showHiddenFiles, &KToggleAction::triggered, this, &DolphinViewActionHandler::toggleShowHiddenFiles);
QAction* adjustViewProps = m_actionCollection->addAction(QStringLiteral("view_properties"));