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