File indexing completed on 2024-05-12 05:00:20

0001 /* This file is part of the KDE project
0002     SPDX-FileCopyrightText: 2000 David Faure <faure@kde.org>
0003     SPDX-FileCopyrightText: 2003 Waldo Bastian <bastian@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-only
0006 */
0007 
0008 #include "dirtree_item.h"
0009 
0010 #include "dirtree_module.h"
0011 #include "konqsidebar_oldtreemodule.h"
0012 
0013 #include <kfileitemlistproperties.h>
0014 #include <kactioncollection.h>
0015 #include <kglobalsettings.h>
0016 #include <kmimetypetrader.h>
0017 #include <kio/paste.h>
0018 #include <kconfiggroup.h>
0019 #include <kiconloader.h>
0020 #include <kde_file.h>
0021 
0022 #include <QFile>
0023 #include <QFileInfo>
0024 #include <QPainter>
0025 #include <QApplication>
0026 #include <QClipboard>
0027 #include <QCursor>
0028 #include <KSharedConfig>
0029 
0030 #define MYMODULE static_cast<KonqSidebarDirTreeModule*>(module())
0031 
0032 KonqSidebarDirTreeItem::KonqSidebarDirTreeItem(KonqSidebarTreeItem *parentItem, KonqSidebarTreeTopLevelItem *topLevelItem, const KFileItem &fileItem)
0033     : KonqSidebarTreeItem(parentItem, topLevelItem), m_fileItem(fileItem)
0034 {
0035     if (m_topLevelItem) {
0036         MYMODULE->addSubDir(this);
0037     }
0038     reset();
0039 }
0040 
0041 KonqSidebarDirTreeItem::KonqSidebarDirTreeItem(KonqSidebarTree *parent, KonqSidebarTreeTopLevelItem *topLevelItem, const KFileItem &fileItem)
0042     : KonqSidebarTreeItem(parent, topLevelItem), m_fileItem(fileItem)
0043 {
0044     if (m_topLevelItem) {
0045         MYMODULE->addSubDir(this);
0046     }
0047     reset();
0048 }
0049 
0050 KonqSidebarDirTreeItem::~KonqSidebarDirTreeItem()
0051 {
0052 }
0053 
0054 void KonqSidebarDirTreeItem::reset()
0055 {
0056     bool expandable = true;
0057     // For local dirs, find out if they have no children, to remove the "+"
0058     if (m_fileItem.isDir()) {
0059         QUrl url = m_fileItem.url();
0060         if (url.isLocalFile()) {
0061             struct stat buff;
0062             if (KDE::stat(url.toLocalFile(), &buff) != -1) {
0063                 //qCDebug(SIDEBAR_LOG) << "KonqSidebarDirTreeItem::init " << path << " : " << buff.st_nlink;
0064                 // The link count for a directory is generally subdir_count + 2.
0065                 // One exception is if there are hard links to the directory, in this case
0066                 // the link count can be > 2 even if no subdirs exist.
0067                 // The other exception are smb (and maybe netware) mounted directories
0068                 // of which the link count is always 1. Therefore, we only set the item
0069                 // as non-expandable if it's exactly 2 (one link from the parent dir,
0070                 // plus one from the '.' entry).
0071                 if (buff.st_nlink == 2) {
0072                     expandable = false;
0073                 }
0074             }
0075         }
0076     }
0077     setExpandable(expandable);
0078     id = m_fileItem.url().adjusted(QUrl::StripTrailingSlash).toString();
0079 }
0080 
0081 void KonqSidebarDirTreeItem::setOpen(bool open)
0082 {
0083     qCDebug(SIDEBAR_LOG) << "KonqSidebarDirTreeItem::setOpen " << open;
0084     if (open && !childCount() && m_bListable) {
0085         MYMODULE->openSubFolder(this);
0086     } else if (hasStandardIcon()) {
0087         int size = KIconLoader::global()->currentSize(KIconLoader::Small);
0088         if (open) {
0089             setPixmap(0, DesktopIcon("folder-open", size));
0090         } else {
0091             setPixmap(0, m_fileItem.pixmap(size));
0092         }
0093     }
0094     KonqSidebarTreeItem::setOpen(open);
0095 }
0096 
0097 bool KonqSidebarDirTreeItem::hasStandardIcon()
0098 {
0099     // The reason why we can't use KFileItem::iconName() is that it doesn't
0100     // take custom icons in .directory files into account
0101     return m_fileItem.determineMimeType()->iconName(m_fileItem.url()/*, m_fileItem->isLocalFile()*/) == "folder";
0102 }
0103 
0104 void KonqSidebarDirTreeItem::paintCell(QPainter *_painter, const QColorGroup &_cg, int _column, int _width, int _alignment)
0105 {
0106     if (m_fileItem.isLink()) {
0107         QFont f(_painter->font());
0108         f.setItalic(true);
0109         _painter->setFont(f);
0110     }
0111     Q3ListViewItem::paintCell(_painter, _cg, _column, _width, _alignment);
0112 }
0113 
0114 QUrl KonqSidebarDirTreeItem::externalURL() const
0115 {
0116     return m_fileItem.url();
0117 }
0118 
0119 QString KonqSidebarDirTreeItem::externalMimeType() const
0120 {
0121     if (m_fileItem.isMimeTypeKnown()) {
0122         return m_fileItem.mimetype();
0123     } else {
0124         return QString();
0125     }
0126 }
0127 
0128 bool KonqSidebarDirTreeItem::acceptsDrops(const Q3StrList &formats)
0129 {
0130     if (formats.contains("text/uri-list")) {
0131         // A directory ?
0132         if (S_ISDIR(m_fileItem.mode())) {
0133             return m_fileItem.isWritable();
0134         }
0135 
0136         // But only local .desktop files and executables
0137         if (!m_fileItem.isLocalFile()) {
0138             return false;
0139         }
0140 
0141         if (m_fileItem.mimetype() == "application/x-desktop") {
0142             return true;
0143         }
0144 
0145         // Executable, shell script ... ?
0146         if (QFileInfo(m_fileItem.url().toLocalFile()).isExecutable()) {
0147             return true;
0148         }
0149 
0150         return false;
0151     }
0152     return false;
0153 }
0154 
0155 void KonqSidebarDirTreeItem::drop(QDropEvent *ev)
0156 {
0157     KonqOperations::doDrop(m_fileItem, externalURL(), ev, tree());
0158 }
0159 
0160 bool KonqSidebarDirTreeItem::populateMimeData(QMimeData *mimeData, bool move)
0161 {
0162     QList<QUrl> lst;
0163     lst.append(m_fileItem.url());
0164     qCDebug(SIDEBAR_LOG) << lst;
0165 
0166     mimeData->setUrls(lst);
0167     KIO::setClipboardDataCut(mimeData, move);
0168     return true;
0169 }
0170 
0171 void KonqSidebarDirTreeItem::itemSelected()
0172 {
0173     const QMimeData *mimeData = QApplication::clipboard()->mimeData();
0174     const QList<QUrl> urls = mimeData->urls();
0175     const QList<QUrl> urls =
0176         const bool paste = !urls.isEmpty();
0177     tree()->enableActions(true, true, paste);
0178 }
0179 
0180 void KonqSidebarDirTreeItem::middleButtonClicked()
0181 {
0182     // Optimization to avoid KRun to call kfmclient that then tells us
0183     // to open a window :-)
0184     KService::Ptr offer = KMimeTypeTrader::self()->preferredService(m_fileItem.mimetype(), "Application");
0185     if (offer) {
0186         qCDebug(SIDEBAR_LOG) << "KonqDirPart::mmbClicked: got service " << offer->desktopEntryName();
0187     }
0188     if (offer && offer->desktopEntryName().startsWith("kfmclient")) {
0189         qCDebug(SIDEBAR_LOG) << "Emitting createNewWindow";
0190         KParts::OpenUrlArguments args;
0191         args.setMimeType(m_fileItem.mimetype());
0192         emit tree()->createNewWindow(m_fileItem.url(), args);
0193     } else {
0194         m_fileItem.run();
0195     }
0196 }
0197 
0198 void KonqSidebarDirTreeItem::rightButtonPressed()
0199 {
0200     KParts::NavigationExtension::PopupFlags popupFlags = KParts::NavigationExtension::DefaultPopupItems
0201             | KParts::NavigationExtension::ShowProperties
0202             | KParts::NavigationExtension::ShowUrlOperations;
0203     KParts::NavigationExtension::ActionGroupMap actionGroups;
0204     QList<QAction *> editActions;
0205     KActionCollection *actionCollection = tree()->actionCollection();
0206 
0207     KFileItemList items;
0208     items.append(m_fileItem);
0209     KFileItemListProperties capabilities(items);
0210 
0211     // ###### most of this is duplicated from DolphinPart::slotOpenContextMenu :(
0212 
0213     bool supportsDeleting = capabilities.supportsDeleting();
0214     bool supportsMoving = capabilities.supportsMoving();
0215     if (!supportsDeleting) {
0216         popupFlags |= KParts::NavigationExtension::NoDeletion;
0217     }
0218 
0219     Q_ASSERT(actionCollection->action("rename"));
0220     Q_ASSERT(actionCollection->action("trash"));
0221     Q_ASSERT(actionCollection->action("delete"));
0222 
0223     if (supportsMoving) {
0224         editActions.append(actionCollection->action("rename"));
0225     }
0226 
0227     bool addTrash = capabilities.isLocal() && supportsMoving;
0228     bool addDel = false;
0229 
0230     if (supportsDeleting) {
0231         if (!m_fileItem.isLocalFile()) {
0232             addDel = true;
0233         } else if (QApplication::keyboardModifiers() & Qt::ShiftModifier) {
0234             addTrash = false;
0235             addDel = true;
0236         } else {
0237             KSharedConfig::Ptr globalConfig = KSharedConfig::openConfig("kdeglobals", KConfig::IncludeGlobals);
0238             KConfigGroup configGroup(globalConfig, "KDE");
0239             addDel = configGroup.readEntry("ShowDeleteCommand", false);
0240         }
0241     }
0242 
0243     if (addTrash) {
0244         editActions.append(actionCollection->action("trash"));
0245     }
0246     if (addDel) {
0247         editActions.append(actionCollection->action("delete"));
0248     }
0249     // Normally KonqPopupMenu only shows the "Create new" submenu in the current view
0250     // since otherwise the created file would not be visible.
0251     // But in treeview mode we should allow it.
0252     popupFlags |= KParts::NavigationExtension::ShowCreateDirectory;
0253 
0254     actionGroups.insert("editactions", editActions);
0255 
0256     emit tree()->sidebarModule()->showPopupMenu(QCursor::pos(), items,
0257             KParts::OpenUrlArguments(), BrowserArguments(),
0258             popupFlags, actionGroups);
0259 }
0260 
0261 void KonqSidebarDirTreeItem::paste()
0262 {
0263     // move or not move ?
0264     bool move = false;
0265     const QMimeData *data = QApplication::clipboard()->mimeData();
0266     if (data->hasFormat("application/x-kde-cutselection")) {
0267         move = KonqMimeData::decodeIsCutSelection(data);
0268         qCDebug(SIDEBAR_LOG) << "move (from clipboard data) = " << move;
0269     }
0270 
0271     KIO::pasteClipboard(m_fileItem.url(), listView(), move);
0272 }
0273 
0274 void KonqSidebarDirTreeItem::trash()
0275 {
0276     delOperation(KonqOperations::TRASH);
0277 }
0278 
0279 void KonqSidebarDirTreeItem::del()
0280 {
0281     delOperation(KonqOperations::DEL);
0282 }
0283 
0284 void KonqSidebarDirTreeItem::delOperation(KonqOperations::Operation method)
0285 {
0286     QList<QUrl> lst;
0287     lst.append(m_fileItem.url());
0288 
0289     KonqOperations::del(tree(), method, lst);
0290 }
0291 
0292 QString KonqSidebarDirTreeItem::toolTipText() const
0293 {
0294     return m_fileItem.url().pathOrUrl();
0295 }
0296 
0297 void KonqSidebarDirTreeItem::rename()
0298 {
0299     tree()->rename(this, 0);
0300 }
0301 
0302 void KonqSidebarDirTreeItem::rename(const QString &name)
0303 {
0304     QUrl url(m_fileItem.url());
0305     KonqOperations::rename(tree(), url, name);
0306     url.setPath(url.adjusted(QUrl::RemoveFilename).path() + name);
0307     m_fileItem.setUrl(url);
0308 }
0309