File indexing completed on 2024-05-05 16:45:35

0001 /*
0002     SPDX-FileCopyrightText: 2006-2007 Alexander Dymo <adymo@kdevelop.org>
0003     SPDX-FileCopyrightText: 2006 Andreas Pakulat <apaku@gmx.de>
0004     SPDX-FileCopyrightText: 2016 Imran Tatriev <itatriev@gmail.com>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #include "filemanager.h"
0010 
0011 #include <QDir>
0012 #include <QMenu>
0013 #include <QVBoxLayout>
0014 #include <QUrl>
0015 #include <QFileDialog>
0016 
0017 #include <KLocalizedString>
0018 #include <KIO/StoredTransferJob>
0019 #include <KFilePlacesModel>
0020 #include <KParts/MainWindow>
0021 #include <KActionCollection>
0022 #include <KActionMenu>
0023 #include <KJobWidgets>
0024 #include <KConfigGroup>
0025 #include <kio_version.h>
0026 
0027 #include <interfaces/icore.h>
0028 #include <interfaces/isession.h>
0029 #include <interfaces/iuicontroller.h>
0030 #include <interfaces/iplugincontroller.h>
0031 #include <interfaces/idocumentcontroller.h>
0032 #include <interfaces/context.h>
0033 #include <interfaces/contextmenuextension.h>
0034 #include <sublime/message.h>
0035 
0036 #include "../openwith/iopenwith.h"
0037 
0038 #include "kdevfilemanagerplugin.h"
0039 #include "bookmarkhandler.h"
0040 #include "debug.h"
0041 
0042 FileManager::FileManager(KDevFileManagerPlugin *plugin, QWidget* parent)
0043     : QWidget(parent), m_plugin(plugin)
0044 {
0045     setObjectName(QStringLiteral("FileManager"));
0046     setWindowIcon(QIcon::fromTheme(QStringLiteral("folder-sync"), windowIcon()));
0047     setWindowTitle(i18nc("@title:window", "File System"));
0048 
0049     KConfigGroup cg = KDevelop::ICore::self()->activeSession()->config()->group( "Filesystem" );
0050 
0051     auto *l = new QVBoxLayout(this);
0052     l->setContentsMargins(0, 0, 0, 0);
0053     l->setSpacing(0);
0054     auto* model = new KFilePlacesModel( this );
0055     urlnav = new KUrlNavigator(model, QUrl(cg.readEntry( "LastLocation", QUrl::fromLocalFile( QDir::homePath() ) )), this );
0056 
0057     connect(urlnav, &KUrlNavigator::urlChanged, this, &FileManager::gotoUrl);
0058 
0059     l->addWidget(urlnav);
0060     dirop = new KDirOperator( urlnav->locationUrl(), this);
0061 #if KIO_VERSION < QT_VERSION_CHECK(5, 100, 0)
0062     dirop->setView( KFile::Tree );
0063 #else
0064     dirop->setViewMode(KFile::Tree);
0065 #endif
0066     dirop->setupMenu( KDirOperator::SortActions | KDirOperator::FileActions | KDirOperator::NavActions | KDirOperator::ViewActions );
0067     connect(dirop, &KDirOperator::urlEntered, this, &FileManager::updateNav);
0068     connect(dirop, &KDirOperator::contextMenuAboutToShow, this, &FileManager::fillContextMenu);
0069     l->addWidget(dirop);
0070 
0071     connect( dirop, &KDirOperator::fileSelected, this, &FileManager::openFile );
0072 
0073     setFocusProxy(dirop);
0074 
0075     // includes some actions, but not hooked into the shortcut dialog atm
0076     m_actionCollection = new KActionCollection(this);
0077     m_actionCollection->addAssociatedWidget(this);
0078 
0079     setupActions();
0080 
0081     // Connect the bookmark handler
0082     connect(m_bookmarkHandler, &BookmarkHandler::openUrl, this, &FileManager::gotoUrl);
0083     connect(m_bookmarkHandler, &BookmarkHandler::openUrl, this, &FileManager::updateNav);
0084 }
0085 
0086 FileManager::~FileManager()
0087 {
0088     KConfigGroup cg = KDevelop::ICore::self()->activeSession()->config()->group( "Filesystem" );
0089     cg.writeEntry( "LastLocation", urlnav->locationUrl() );
0090     cg.sync();
0091 }
0092 
0093 void FileManager::fillContextMenu(const KFileItem& item, QMenu* menu)
0094 {
0095     for (QAction* a : qAsConst(contextActions)) {
0096         if(menu->actions().contains(a)){
0097             menu->removeAction(a);
0098         }
0099     }
0100     contextActions.clear();
0101     contextActions.append(menu->addSeparator());
0102     menu->addAction(newFileAction);
0103     contextActions.append(newFileAction);
0104     KDevelop::FileContext context(QList<QUrl>() << item.url());
0105     QList<KDevelop::ContextMenuExtension> extensions = KDevelop::ICore::self()->pluginController()->queryPluginsForContextMenuExtensions(&context, menu);
0106     KDevelop::ContextMenuExtension::populateMenu(menu, extensions);
0107     auto* tmpMenu = new QMenu();
0108     KDevelop::ContextMenuExtension::populateMenu(tmpMenu, extensions);
0109     contextActions.append(tmpMenu->actions());
0110     delete tmpMenu;
0111 }
0112 
0113 void FileManager::openFile(const KFileItem& file)
0114 {
0115     KDevelop::IOpenWith::openFiles(QList<QUrl>() << file.url());
0116 }
0117 
0118 
0119 void FileManager::gotoUrl( const QUrl& url )
0120 {
0121      dirop->setUrl( url, true );
0122 }
0123 
0124 void FileManager::updateNav( const QUrl& url )
0125 {
0126     urlnav->setLocationUrl( url );
0127 }
0128 
0129 void FileManager::setupActions()
0130 {
0131     auto* acmBookmarks = new KActionMenu(QIcon::fromTheme(QStringLiteral("bookmarks")), i18nc("@title:menu", "Bookmarks"), this);
0132     acmBookmarks->setPopupMode(QToolButton::InstantPopup);
0133     m_bookmarkHandler = new BookmarkHandler(this, acmBookmarks->menu());
0134     acmBookmarks->setShortcutContext(Qt::WidgetWithChildrenShortcut);
0135 
0136     auto* action = new QAction(this);
0137     action->setShortcutContext(Qt::WidgetWithChildrenShortcut);
0138     action->setText(i18nc("@action switch to directory of current document", "Current Document Directory"));
0139     action->setIcon(QIcon::fromTheme(QStringLiteral("dirsync")));
0140     connect(action, &QAction::triggered, this, &FileManager::syncCurrentDocumentDirectory);
0141 
0142 #if KIO_VERSION < QT_VERSION_CHECK(5, 100, 0)
0143     auto* diropActionCollection = dirop->actionCollection();
0144     tbActions = {
0145         diropActionCollection->action(QStringLiteral("back")),
0146         diropActionCollection->action(QStringLiteral("up")),
0147         diropActionCollection->action(QStringLiteral("home")),
0148         diropActionCollection->action(QStringLiteral("forward")),
0149         diropActionCollection->action(QStringLiteral("reload")),
0150         acmBookmarks,
0151         action,
0152         diropActionCollection->action(QStringLiteral("sorting menu")),
0153         diropActionCollection->action(QStringLiteral("show hidden")),
0154 #else
0155     tbActions = {
0156         dirop->action(KDirOperator::Back),
0157         dirop->action(KDirOperator::Up),
0158         dirop->action(KDirOperator::Home),
0159         dirop->action(KDirOperator::Forward),
0160         dirop->action(KDirOperator::Reload),
0161         acmBookmarks,
0162         action,
0163         dirop->action(KDirOperator::SortMenu),
0164         dirop->action(KDirOperator::ShowHiddenFiles),
0165 #endif
0166     };
0167 
0168     newFileAction = new QAction(this);
0169     newFileAction->setText(i18nc("@action", "New File..."));
0170     newFileAction->setIcon(QIcon::fromTheme(QStringLiteral("document-new")));
0171     connect(newFileAction, &QAction::triggered, this, &FileManager::createNewFile);
0172 }
0173 
0174 void FileManager::createNewFile()
0175 {
0176     QUrl destUrl = QFileDialog::getSaveFileUrl(KDevelop::ICore::self()->uiController()->activeMainWindow(), i18nc("@title:window", "Create New File"));
0177     if (destUrl.isEmpty()) {
0178         return;
0179     }
0180 
0181     KJob* job = KIO::storedPut(QByteArray(), destUrl, -1);
0182     KJobWidgets::setWindow(job, this);
0183     connect(job, &KJob::result, this, &FileManager::fileCreated);
0184 }
0185 
0186 void FileManager::fileCreated(KJob* job)
0187 {
0188     auto transferJob = qobject_cast<KIO::StoredTransferJob*>(job); Q_ASSERT(transferJob);
0189     if (!transferJob->error()) {
0190         KDevelop::ICore::self()->documentController()->openDocument( transferJob->url() );
0191     } else {
0192         const QString messageText = i18n("Unable to create file '%1'", transferJob->url().toDisplayString(QUrl::PreferLocalFile));
0193         auto* message = new Sublime::Message(messageText, Sublime::Message::Error);
0194         KDevelop::ICore::self()->uiController()->postMessage(message);
0195     }
0196 }
0197 
0198 void FileManager::syncCurrentDocumentDirectory()
0199 {
0200     if( KDevelop::IDocument* activeDoc = KDevelop::ICore::self()->documentController()->activeDocument() )
0201         updateNav( activeDoc->url().adjusted(QUrl::RemoveFilename) );
0202 }
0203 
0204 QList<QAction*> FileManager::toolBarActions() const
0205 {
0206     return tbActions;
0207 }
0208 
0209 KActionCollection* FileManager::actionCollection() const
0210 {
0211     return m_actionCollection;
0212 }
0213 
0214 KDirOperator* FileManager::dirOperator() const
0215 {
0216     return dirop;
0217 }
0218 
0219 KDevFileManagerPlugin* FileManager::plugin() const
0220 {
0221     return m_plugin;
0222 }
0223 
0224 #include "moc_filemanager.cpp"