File indexing completed on 2024-04-28 04:58:27
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 2000 David Faure <faure@kde.org> 0003 SPDX-FileCopyrightText: 2000 Carsten Pfeiffer <pfeiffer@kde.org> 0004 SPDX-FileCopyrightText: 2003 Waldo Bastian <bastian@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-only 0007 */ 0008 0009 #include "konq_sidebartree.h" 0010 #include "konq_sidebartreemodule.h" 0011 #include "konqsidebar_oldtreemodule.h" 0012 0013 #include <QClipboard> 0014 #include <QCursor> 0015 #include <QDir> 0016 #include <Qt3Support/Q3Header> 0017 #include <QMenu> 0018 #include <QTimer> 0019 #include <QApplication> 0020 0021 #include <QAction> 0022 #include <kactioncollection.h> 0023 #include <kdirnotify.h> 0024 #include <kdesktopfile.h> 0025 #include <kglobalsettings.h> 0026 #include <klibrary.h> 0027 #include <QIcon> 0028 #include <kiconloader.h> 0029 #include <kinputdialog.h> 0030 #include <kio/netaccess.h> 0031 #include <KLocalizedString> 0032 #include <kmimetype.h> 0033 #include <kshell.h> 0034 #include <kpropertiesdialog.h> 0035 #include <kprotocolinfo.h> 0036 #include <kstandarddirs.h> 0037 #include <k3urldrag.h> 0038 0039 #include <stdlib.h> 0040 #include <assert.h> 0041 #include <QStandardPaths> 0042 0043 static const int autoOpenTimeout = 750; 0044 0045 getModule KonqSidebarTree::getPluginFactory(const QString &name) 0046 { 0047 if (!pluginFactories.contains(name)) { 0048 QString libName = pluginInfo[name]; 0049 KLibrary lib(libName); 0050 if (lib.load()) { 0051 // get the create_ function 0052 QString factory = "create_" + libName; 0053 KLibrary::void_function_ptr create = lib.resolveFunction(QFile::encodeName(factory)); 0054 if (create) { 0055 getModule func = (getModule)create; 0056 pluginFactories.insert(name, func); 0057 qCDebug(SIDEBAR_LOG) << "Added a module"; 0058 } else { 0059 kWarning() << "No create function found in" << libName; 0060 } 0061 } else { 0062 kWarning() << "Module " << libName << " can't be loaded!"; 0063 } 0064 } 0065 0066 return pluginFactories[name]; 0067 } 0068 0069 void KonqSidebarTree::loadModuleFactories() 0070 { 0071 pluginFactories.clear(); 0072 pluginInfo.clear(); 0073 KStandardDirs *dirs = KGlobal::dirs(); 0074 const QStringList list = dirs->findAllResources("data", "konqsidebartng/dirtree/*.desktop", KStandardDirs::NoDuplicates); 0075 0076 for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) { 0077 KConfig _ksc(*it, KConfig::SimpleConfig); 0078 KConfigGroup ksc(&_ksc, "Desktop Entry"); 0079 QString name = ksc.readEntry("X-KDE-TreeModule"); 0080 QString libName = ksc.readEntry("X-KDE-TreeModule-Lib"); 0081 if ((name.isEmpty()) || (libName.isEmpty())) { 0082 kWarning() << "Bad Configuration file for a dirtree module " << *it; 0083 continue; 0084 } 0085 0086 //Register the library info. 0087 pluginInfo[name] = libName; 0088 } 0089 } 0090 0091 class KonqSidebarTree_Internal 0092 { 0093 public: 0094 DropAcceptType m_dropMode; 0095 QStringList m_dropFormats; 0096 }; 0097 0098 KonqSidebarTree::KonqSidebarTree(KonqSidebarOldTreeModule *parent, QWidget *parentWidget, ModuleType moduleType, const QString &path) 0099 : K3ListView(parentWidget), 0100 m_currentTopLevelItem(0), 0101 m_scrollingLocked(false), 0102 m_collection(0) 0103 { 0104 d = new KonqSidebarTree_Internal; 0105 d->m_dropMode = SidebarTreeMode; 0106 0107 loadModuleFactories(); 0108 0109 setAcceptDrops(true); 0110 viewport()->setAcceptDrops(true); 0111 installEventFilter(this); 0112 m_lstModules.setAutoDelete(true); 0113 0114 setSelectionMode(Q3ListView::Single); 0115 setDragEnabled(true); 0116 0117 m_sidebarModule = parent; 0118 0119 m_animationTimer = new QTimer(this); 0120 connect(m_animationTimer, SIGNAL(timeout()), 0121 this, SLOT(slotAnimation())); 0122 0123 m_currentBeforeDropItem = 0; 0124 m_dropItem = 0; 0125 m_bOpeningFirstChild = false; 0126 0127 addColumn(QString()); 0128 header()->hide(); 0129 setTreeStepSize(15); 0130 0131 m_autoOpenTimer = new QTimer(this); 0132 connect(m_autoOpenTimer, SIGNAL(timeout()), 0133 this, SLOT(slotAutoOpenFolder())); 0134 0135 connect(this, SIGNAL(doubleClicked(Q3ListViewItem*)), 0136 this, SLOT(slotDoubleClicked(Q3ListViewItem*))); 0137 connect(this, SIGNAL(mouseButtonPressed(int,Q3ListViewItem*,QPoint,int)), 0138 this, SLOT(slotMouseButtonPressed(int,Q3ListViewItem*,QPoint,int))); 0139 connect(this, SIGNAL(mouseButtonClicked(int,Q3ListViewItem*,QPoint,int)), 0140 this, SLOT(slotMouseButtonClicked(int,Q3ListViewItem*,QPoint,int))); 0141 connect(this, SIGNAL(returnPressed(Q3ListViewItem*)), 0142 this, SLOT(slotDoubleClicked(Q3ListViewItem*))); 0143 connect(this, SIGNAL(selectionChanged()), 0144 this, SLOT(slotSelectionChanged())); 0145 connect(qApp->clipboard(), SIGNAL(dataChanged()), 0146 this, SLOT(slotSelectionChanged())); // so that "paste" can be updated 0147 0148 connect(this, SIGNAL(itemRenamed(Q3ListViewItem*,QString,int)), 0149 this, SLOT(slotItemRenamed(Q3ListViewItem*,QString,int))); 0150 0151 if (moduleType == VIRT_Folder) { 0152 m_dirtreeDir.dir.setPath(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + "konqsidebartng/virtual_folders/" + path + '/'); 0153 m_dirtreeDir.relDir = path; 0154 } else { 0155 m_dirtreeDir.dir.setPath(path); 0156 } 0157 qCDebug(SIDEBAR_LOG) << m_dirtreeDir.dir.path(); 0158 m_dirtreeDir.type = moduleType; 0159 // Initial parsing 0160 rescanConfiguration(); 0161 0162 if (firstChild()) { 0163 m_bOpeningFirstChild = true; 0164 firstChild()->setOpen(true); 0165 m_bOpeningFirstChild = false; 0166 } 0167 0168 OrgKdeKDirNotifyInterface *kdirnotify = new OrgKdeKDirNotifyInterface(QString(), QString(), QDBusConnection::sessionBus()); 0169 kdirnotify->setParent(this); 0170 connect(kdirnotify, SIGNAL(FilesAdded(QString)), SLOT(slotFilesAdded(QString))); 0171 connect(kdirnotify, SIGNAL(FilesChanged(QStringList)), SLOT(slotFilesChanged(QStringList))); 0172 connect(kdirnotify, SIGNAL(FilesRemoved(QStringList)), SLOT(slotFilesRemoved(QStringList))); 0173 0174 m_collection = new KActionCollection(this); 0175 m_collection->addAssociatedWidget(this); 0176 m_collection->setObjectName(QLatin1String("bookmark actions")); 0177 QAction *action = new QAction(QIcon::fromTheme("folder-new"), i18n("&Create New Folder..."), this); 0178 m_collection->addAction("create_folder", action); 0179 connect(action, SIGNAL(triggered(bool)), SLOT(slotCreateFolder())); 0180 0181 action = new QAction(QIcon::fromTheme("edit-delete"), i18n("Delete Folder"), this); 0182 m_collection->addAction("delete", action); 0183 connect(action, SIGNAL(triggered(bool)), SLOT(slotDelete())); 0184 0185 action = new QAction(QIcon::fromTheme("user-trash"), i18n("Move to Trash"), this); 0186 m_collection->addAction("trash", action); 0187 connect(action, SIGNAL(triggered(bool)), SLOT(slotTrash())); 0188 0189 action = new QAction(i18n("Rename"), this); 0190 action->setIcon(QIcon::fromTheme("edit-rename")); 0191 m_collection->addAction("rename", action); 0192 connect(action, SIGNAL(triggered(bool)), SLOT(slotRename())); 0193 0194 action = new QAction(QIcon::fromTheme("edit-delete"), i18n("Delete Link"), this); 0195 m_collection->addAction("delete_link", action); 0196 connect(action, SIGNAL(triggered(bool)), SLOT(slotDelete())); 0197 0198 action = new QAction(QIcon::fromTheme("document-properties"), i18n("Properties"), this); 0199 m_collection->addAction("item_properties", action); 0200 connect(action, SIGNAL(triggered(bool)), SLOT(slotProperties())); 0201 0202 action = new QAction(QIcon::fromTheme("window-new"), i18n("Open in New Window"), this); 0203 m_collection->addAction("open_window", action); 0204 connect(action, SIGNAL(triggered(bool)), SLOT(slotOpenNewWindow())); 0205 0206 action = new QAction(QIcon::fromTheme("tab-new"), i18n("Open in New Tab"), this); 0207 m_collection->addAction("open_tab", action); 0208 connect(action, SIGNAL(triggered(bool)), SLOT(slotOpenTab())); 0209 0210 action = new QAction(QIcon::fromTheme("edit-copy"), i18n("Copy Link Address"), this); 0211 m_collection->addAction("copy_location", action); 0212 connect(action, SIGNAL(triggered(bool)), SLOT(slotCopyLocation())); 0213 } 0214 0215 KonqSidebarTree::~KonqSidebarTree() 0216 { 0217 clearTree(); 0218 0219 delete d; 0220 } 0221 0222 void KonqSidebarTree::itemDestructed(KonqSidebarTreeItem *item) 0223 { 0224 stopAnimation(item); 0225 0226 if (item == m_currentBeforeDropItem) { 0227 m_currentBeforeDropItem = 0; 0228 } 0229 } 0230 0231 void KonqSidebarTree::setDropFormats(const QStringList &formats) 0232 { 0233 d->m_dropFormats = formats; 0234 } 0235 0236 void KonqSidebarTree::clearTree() 0237 { 0238 m_lstModules.clear(); 0239 m_topLevelItems.clear(); 0240 m_mapCurrentOpeningFolders.clear(); 0241 m_currentBeforeDropItem = 0; 0242 clear(); 0243 0244 if (m_dirtreeDir.type == VIRT_Folder) { 0245 setRootIsDecorated(true); 0246 } else { 0247 setRootIsDecorated(false); 0248 } 0249 } 0250 0251 void KonqSidebarTree::followURL(const QUrl &url) 0252 { 0253 // Maybe we're there already ? 0254 KonqSidebarTreeItem *selection = static_cast<KonqSidebarTreeItem *>(selectedItem()); 0255 if (selection && selection->externalURL().equals(url, QUrl::CompareWithoutTrailingSlash)) { 0256 ensureItemVisible(selection); 0257 return; 0258 } 0259 0260 qCDebug(SIDEBAR_LOG) << url.url(); 0261 Q3PtrListIterator<KonqSidebarTreeTopLevelItem> topItem(m_topLevelItems); 0262 for (; topItem.current(); ++topItem) { 0263 if (topItem.current()->externalURL().isParentOf(url)) { 0264 topItem.current()->module()->followURL(url); 0265 return; // done 0266 } 0267 } 0268 qCDebug(SIDEBAR_LOG) << "Not found"; 0269 } 0270 0271 void KonqSidebarTree::contentsDragEnterEvent(QDragEnterEvent *ev) 0272 { 0273 m_dropItem = 0; 0274 m_currentBeforeDropItem = selectedItem(); 0275 // Save the available formats 0276 m_lstDropFormats.clear(); 0277 for (int i = 0; ev->format(i); i++) 0278 if (*(ev->format(i))) { 0279 m_lstDropFormats.append(ev->format(i)); 0280 } 0281 K3ListView::contentsDragEnterEvent(ev); 0282 } 0283 0284 void KonqSidebarTree::contentsDragMoveEvent(QDragMoveEvent *e) 0285 { 0286 Q3ListViewItem *item = itemAt(contentsToViewport(e->pos())); 0287 0288 // Accept drops on the background, if URLs 0289 if (!item && m_lstDropFormats.contains("text/uri-list")) { 0290 m_dropItem = 0; 0291 e->acceptProposedAction(); 0292 if (selectedItem()) { 0293 setSelected(selectedItem(), false); // no item selected 0294 } 0295 return; 0296 } 0297 0298 if (item && static_cast<KonqSidebarTreeItem *>(item)->acceptsDrops(m_lstDropFormats)) { 0299 d->m_dropMode = SidebarTreeMode; 0300 0301 if (!item->isSelectable()) { 0302 m_dropItem = 0; 0303 m_autoOpenTimer->stop(); 0304 e->ignore(); 0305 return; 0306 } 0307 0308 e->acceptProposedAction(); 0309 0310 setSelected(item, true); 0311 0312 if (item != m_dropItem) { 0313 m_autoOpenTimer->stop(); 0314 m_dropItem = item; 0315 m_autoOpenTimer->start(autoOpenTimeout); 0316 } 0317 } else { 0318 d->m_dropMode = K3ListViewMode; 0319 K3ListView::contentsDragMoveEvent(e); 0320 } 0321 } 0322 0323 void KonqSidebarTree::contentsDragLeaveEvent(QDragLeaveEvent *ev) 0324 { 0325 // Restore the current item to what it was before the dragging (#17070) 0326 if (m_currentBeforeDropItem) { 0327 setSelected(m_currentBeforeDropItem, true); 0328 } else { 0329 setSelected(m_dropItem, false); // no item selected 0330 } 0331 m_currentBeforeDropItem = 0; 0332 m_dropItem = 0; 0333 m_lstDropFormats.clear(); 0334 0335 if (d->m_dropMode == K3ListViewMode) { 0336 K3ListView::contentsDragLeaveEvent(ev); 0337 } 0338 } 0339 0340 void KonqSidebarTree::contentsDropEvent(QDropEvent *ev) 0341 { 0342 if (d->m_dropMode == SidebarTreeMode) { 0343 m_autoOpenTimer->stop(); 0344 0345 if (!selectedItem()) { 0346 // KonqOperations::doDrop( 0L, m_dirtreeDir.dir, ev, this ); 0347 QList<QUrl> urls; 0348 if (K3URLDrag::decode(ev, urls)) { 0349 for (QList<QUrl>::ConstIterator it = urls.constBegin(); 0350 it != urls.constEnd(); ++it) { 0351 addUrl(0, *it); 0352 } 0353 } 0354 } else { 0355 KonqSidebarTreeItem *selection = static_cast<KonqSidebarTreeItem *>(selectedItem()); 0356 selection->drop(ev); 0357 } 0358 } else { 0359 K3ListView::contentsDropEvent(ev); 0360 } 0361 } 0362 0363 static QString findUniqueFilename(const QString &path, const QString &filename) 0364 { 0365 QString tempFilename = filename; 0366 if (tempFilename.endsWith(".desktop")) { 0367 tempFilename.truncate(tempFilename.length() - 8); 0368 } 0369 0370 QString name = tempFilename; 0371 int n = 2; 0372 while (QFile::exists(path + tempFilename + ".desktop")) { 0373 tempFilename = QString("%2_%1").arg(n++).arg(name); 0374 } 0375 return path + tempFilename + ".desktop"; 0376 } 0377 0378 void KonqSidebarTree::addUrl(KonqSidebarTreeTopLevelItem *item, const QUrl &url) 0379 { 0380 QString path; 0381 if (item) { 0382 path = item->path(); 0383 } else { 0384 path = m_dirtreeDir.dir.path(); 0385 } 0386 0387 QUrl destUrl; 0388 0389 if (url.isLocalFile() && url.fileName().endsWith(".desktop")) { 0390 QString filename = findUniqueFilename(path, url.fileName()); 0391 destUrl.setPath(filename); 0392 KIO::NetAccess::file_copy(url, destUrl, this); 0393 } else { 0394 QString name = url.host(); 0395 if (name.isEmpty()) { 0396 name = url.fileName(); 0397 } 0398 QString filename = findUniqueFilename(path, name); 0399 destUrl.setPath(filename); 0400 0401 KDesktopFile desktopFile(filename); 0402 KConfigGroup cfg = desktopFile.desktopGroup(); 0403 cfg.writeEntry("Encoding", "UTF-8"); 0404 cfg.writeEntry("Type", "Link"); 0405 cfg.writeEntry("URL", url.url()); 0406 QString icon = "folder"; 0407 if (!url.isLocalFile()) { 0408 icon = KMimeType::favIconForUrl(url); 0409 } 0410 if (icon.isEmpty()) { 0411 icon = KProtocolInfo::icon(url.scheme()); 0412 } 0413 cfg.writeEntry("Icon", icon); 0414 cfg.writeEntry("Name", name); 0415 cfg.writeEntry("Open", false); 0416 cfg.sync(); 0417 } 0418 0419 destUrl.setPath(destUrl.adjusted(QUrl::RemoveFilename|QUrl::StripTrailingSlash).path()); 0420 OrgKdeKDirNotifyInterface::emitFilesAdded(destUrl.url()); 0421 0422 if (item) { 0423 item->setOpen(true); 0424 } 0425 } 0426 0427 bool KonqSidebarTree::acceptDrag(QDropEvent *e) const 0428 { 0429 // for K3ListViewMode... 0430 for (int i = 0; e->format(i); i++) 0431 if (d->m_dropFormats.contains(e->format(i))) { 0432 return true; 0433 } 0434 return false; 0435 } 0436 0437 Q3DragObject *KonqSidebarTree::dragObject() 0438 { 0439 KonqSidebarTreeItem *item = static_cast<KonqSidebarTreeItem *>(selectedItem()); 0440 if (!item) { 0441 return 0; 0442 } 0443 0444 QMimeData *mimeData = new QMimeData; 0445 if (item->populateMimeData(mimeData, false)) { 0446 QDrag *drag = new QDrag(viewport()); 0447 drag->setMimeData(mimeData); 0448 const QPixmap *pix = item->pixmap(0); 0449 if (pix && drag->pixmap().isNull()) { 0450 drag->setPixmap(*pix); 0451 } 0452 } else { 0453 delete mimeData; 0454 mimeData = 0; 0455 } 0456 0457 #ifdef __GNUC__ 0458 #warning TODO port to QDrag (only possible once porting away from Q3ListView?) 0459 #endif 0460 return 0; 0461 //return drag; 0462 } 0463 0464 void KonqSidebarTree::leaveEvent(QEvent *e) 0465 { 0466 K3ListView::leaveEvent(e); 0467 // emitStatusBarText( QString() ); 0468 } 0469 0470 void KonqSidebarTree::slotDoubleClicked(Q3ListViewItem *item) 0471 { 0472 //qCDebug(SIDEBAR_LOG) << item; 0473 if (!item) { 0474 return; 0475 } 0476 0477 if (!static_cast<KonqSidebarTreeItem *>(item)->isClickable()) { 0478 return; 0479 } 0480 0481 slotExecuted(item); 0482 item->setOpen(!item->isOpen()); 0483 } 0484 0485 void KonqSidebarTree::slotExecuted(Q3ListViewItem *item) 0486 { 0487 qCDebug(SIDEBAR_LOG) << item; 0488 if (!item) { 0489 return; 0490 } 0491 0492 if (!static_cast<KonqSidebarTreeItem *>(item)->isClickable()) { 0493 return; 0494 } 0495 0496 KonqSidebarTreeItem *dItem = static_cast<KonqSidebarTreeItem *>(item); 0497 0498 KParts::OpenUrlArguments args; 0499 args.setMimeType(dItem->externalMimeType()); 0500 BrowserArguments browserArgs; 0501 browserArgs.trustedSource = true; // is this needed? 0502 QUrl externalURL = dItem->externalURL(); 0503 if (!externalURL.isEmpty()) { 0504 openUrlRequest(externalURL, args, browserArgs); 0505 } 0506 } 0507 0508 void KonqSidebarTree::slotMouseButtonPressed(int _button, Q3ListViewItem *_item, const QPoint &, int col) 0509 { 0510 KonqSidebarTreeItem *item = static_cast<KonqSidebarTreeItem *>(_item); 0511 if (_button == Qt::RightButton) { 0512 if (item && col < 2) { 0513 item->setSelected(true); 0514 item->rightButtonPressed(); 0515 } 0516 } 0517 } 0518 0519 void KonqSidebarTree::slotMouseButtonClicked(int _button, Q3ListViewItem *_item, const QPoint &, int col) 0520 { 0521 KonqSidebarTreeItem *item = static_cast<KonqSidebarTreeItem *>(_item); 0522 if (_item && col < 2) { 0523 switch (_button) { 0524 case Qt::LeftButton: 0525 slotExecuted(item); 0526 break; 0527 case Qt::MiddleButton: 0528 item->middleButtonClicked(); 0529 break; 0530 } 0531 } 0532 } 0533 0534 void KonqSidebarTree::slotAutoOpenFolder() 0535 { 0536 m_autoOpenTimer->stop(); 0537 0538 if (!m_dropItem || m_dropItem->isOpen()) { 0539 return; 0540 } 0541 0542 m_dropItem->setOpen(true); 0543 m_dropItem->repaint(); 0544 } 0545 0546 void KonqSidebarTree::rescanConfiguration() 0547 { 0548 qCDebug(SIDEBAR_LOG); 0549 m_autoOpenTimer->stop(); 0550 clearTree(); 0551 if (m_dirtreeDir.type == VIRT_Folder) { 0552 qCDebug(SIDEBAR_LOG) << "-->scanDir"; 0553 scanDir(0, m_dirtreeDir.dir.path(), true); 0554 0555 } else { 0556 qCDebug(SIDEBAR_LOG) << "-->loadTopLevel"; 0557 loadTopLevelItem(0, m_dirtreeDir.dir.path()); 0558 } 0559 } 0560 0561 void KonqSidebarTree::slotSelectionChanged() 0562 { 0563 if (!m_dropItem) { // don't do this while the dragmove thing 0564 KonqSidebarTreeItem *item = static_cast<KonqSidebarTreeItem *>(selectedItem()); 0565 if (item) { 0566 item->itemSelected(); 0567 } 0568 /* else -- doesn't seem to happen 0569 {} */ 0570 } 0571 } 0572 0573 void KonqSidebarTree::slotFilesAdded(const QString &dir) 0574 { 0575 QUrl urlDir(dir); 0576 qCDebug(SIDEBAR_LOG) << dir; 0577 if (m_dirtreeDir.dir.isParentOf(urlDir)) 0578 // We use a timer in case of DBus re-entrance.. 0579 { 0580 QTimer::singleShot(0, this, SLOT(rescanConfiguration())); 0581 } 0582 } 0583 0584 void KonqSidebarTree::slotFilesRemoved(const QStringList &urls) 0585 { 0586 //qCDebug(SIDEBAR_LOG) << "KonqSidebarTree::slotFilesRemoved " << urls.count(); 0587 for (QStringList::ConstIterator it = urls.constBegin(); it != urls.constEnd(); ++it) { 0588 QUrl u(*it); 0589 //qCDebug(SIDEBAR_LOG) << "KonqSidebarTree::slotFilesRemoved " << u; 0590 if (m_dirtreeDir.dir.isParentOf(u)) { 0591 QTimer::singleShot(0, this, SLOT(rescanConfiguration())); 0592 qCDebug(SIDEBAR_LOG) << "done"; 0593 return; 0594 } 0595 } 0596 } 0597 0598 void KonqSidebarTree::slotFilesChanged(const QStringList &urls) 0599 { 0600 //qCDebug(SIDEBAR_LOG) << "KonqSidebarTree::slotFilesChanged"; 0601 // not same signal, but same implementation 0602 slotFilesRemoved(urls); 0603 } 0604 0605 void KonqSidebarTree::scanDir(KonqSidebarTreeItem *parent, const QString &path, bool isRoot) 0606 { 0607 QDir dir(path); 0608 0609 if (!dir.isReadable()) { 0610 return; 0611 } 0612 0613 qCDebug(SIDEBAR_LOG) << "scanDir" << path; 0614 0615 QStringList entries = dir.entryList(QDir::Files); 0616 QStringList dirEntries = dir.entryList(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot); 0617 0618 if (isRoot) { 0619 bool copyConfig = (entries.isEmpty() && dirEntries.isEmpty()); 0620 if (!copyConfig) { 0621 // Check version number 0622 // Version 1 was the dirtree of KDE 2.0.x (no versioning at that time, so default) 0623 // Version 2 includes the history 0624 // Version 3 includes the bookmarks 0625 // Version 4 includes lan.desktop and floppy.desktop, Alex 0626 // Version 5 includes the audiocd browser 0627 // Version 6 includes the printmanager and lan browser 0628 const int currentVersion = 6; 0629 QString key = QString::fromLatin1("X-KDE-DirTreeVersionNumber"); 0630 KConfig versionCfg(path + "/.directory", KConfig::SimpleConfig); 0631 KConfigGroup generalGroup(&versionCfg, "General"); 0632 int versionNumber = generalGroup.readEntry(key, 1); 0633 qCDebug(SIDEBAR_LOG) << "found version " << versionNumber; 0634 if (versionNumber < currentVersion) { 0635 generalGroup.writeEntry(key, currentVersion); 0636 versionCfg.sync(); 0637 copyConfig = true; 0638 } 0639 } 0640 if (copyConfig) { 0641 // We will copy over the configuration for the dirtree, from the global directory 0642 const QStringList dirtree_dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "konqsidebartng/virtual_folders/" + m_dirtreeDir.relDir + '/'); 0643 0644 // QString dirtree_dir = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "konqsidebartng/virtual_folders/"+m_dirtreeDir.relDir+"/").last(); // most global 0645 // qCDebug(SIDEBAR_LOG) << "dirtree_dir=" << dirtree_dir; 0646 0647 /* 0648 // debug code 0649 0650 const QStringList blah = m_sidebarModule->getInterfaces->componentData()->dirs()->dirs()->findDirs( "data", "konqueror/dirtree" ); 0651 QStringList::ConstIterator eIt = blah.constBegin(); 0652 QStringList::ConstIterator eEnd = blah.constEnd(); 0653 for (; eIt != eEnd; ++eIt ) 0654 qCDebug(SIDEBAR_LOG) << "findDirs got me " << *eIt; 0655 // end debug code 0656 */ 0657 0658 for (QStringList::const_iterator ddit = dirtree_dirs.constBegin(); ddit != dirtree_dirs.constEnd(); ++ddit) { 0659 QString dirtree_dir = *ddit; 0660 if (dirtree_dir == path) { 0661 continue; 0662 } 0663 // if ( !dirtree_dir.isEmpty() && dirtree_dir != path ) 0664 { 0665 QDir globalDir(dirtree_dir); 0666 Q_ASSERT(globalDir.isReadable()); 0667 // Only copy the entries that don't exist yet in the local dir 0668 const QStringList globalDirEntries = globalDir.entryList(); 0669 QStringList::ConstIterator eIt = globalDirEntries.constBegin(); 0670 QStringList::ConstIterator eEnd = globalDirEntries.constEnd(); 0671 for (; eIt != eEnd; ++eIt) { 0672 //qCDebug(SIDEBAR_LOG) << "dirtree_dir contains " << *eIt; 0673 if (*eIt != "." && *eIt != ".." 0674 && !entries.contains(*eIt) && !dirEntries.contains(*eIt)) { 0675 // we don't have that one yet -> copy it. 0676 QString cp("cp -R -- "); 0677 cp += KShell::quoteArg(dirtree_dir + *eIt); 0678 cp += ' '; 0679 cp += KShell::quoteArg(path); 0680 qCDebug(SIDEBAR_LOG) << "executing " << cp; 0681 ::system(QFile::encodeName(cp)); 0682 } 0683 } 0684 } 0685 } 0686 // hack to make QDir refresh the lists 0687 dir.setPath(path); 0688 entries = dir.entryList(QDir::Files); 0689 dirEntries = dir.entryList(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot); 0690 } 0691 } 0692 0693 // TODO: currently the filename order is used. Implement SortOrder? #69667 0694 0695 QStringList::ConstIterator eIt = entries.constBegin(); 0696 QStringList::ConstIterator eEnd = entries.constEnd(); 0697 for (; eIt != eEnd; ++eIt) { 0698 const QString filePath = path + *eIt; 0699 if (KDesktopFile::isDesktopFile(filePath)) { 0700 loadTopLevelItem(parent, filePath); 0701 } 0702 } 0703 0704 eIt = dirEntries.constBegin(); 0705 eEnd = dirEntries.constEnd(); 0706 0707 for (; eIt != eEnd; eIt++) { 0708 const QString newPath = QString(path).append(*eIt).append(QLatin1Char('/')); 0709 loadTopLevelGroup(parent, newPath); 0710 } 0711 } 0712 0713 void KonqSidebarTree::loadTopLevelGroup(KonqSidebarTreeItem *parent, const QString &path) 0714 { 0715 QDir dir(path); 0716 QString name = dir.dirName(); 0717 QString icon = "folder"; 0718 bool open = false; 0719 0720 qCDebug(SIDEBAR_LOG) << "Scanning " << path; 0721 0722 QString dotDirectoryFile = QString(path).append("/.directory"); 0723 0724 if (QFile::exists(dotDirectoryFile)) { 0725 qCDebug(SIDEBAR_LOG) << "Reading the .directory"; 0726 KDesktopFile cfg(dotDirectoryFile); 0727 const KConfigGroup group = cfg.desktopGroup(); 0728 name = group.readEntry("Name", name); 0729 icon = group.readEntry("Icon", icon); 0730 //stripIcon( icon ); 0731 open = group.readEntry("Open", open); 0732 } 0733 0734 KonqSidebarTreeTopLevelItem *item; 0735 if (parent) { 0736 qCDebug(SIDEBAR_LOG) << "Inserting new group under parent "; 0737 item = new KonqSidebarTreeTopLevelItem(parent, 0 /* no module */, path); 0738 } else { 0739 item = new KonqSidebarTreeTopLevelItem(this, 0 /* no module */, path); 0740 } 0741 item->setText(0, name); 0742 item->setPixmap(0, SmallIcon(icon)); 0743 item->setListable(false); 0744 item->setClickable(false); 0745 item->setTopLevelGroup(true); 0746 item->setOpen(open); 0747 0748 m_topLevelItems.append(item); 0749 0750 qCDebug(SIDEBAR_LOG) << "Inserting group " << name << " " << path; 0751 0752 scanDir(item, path); 0753 0754 if (item->childCount() == 0) { 0755 item->setExpandable(false); 0756 } 0757 } 0758 0759 void KonqSidebarTree::loadTopLevelItem(KonqSidebarTreeItem *parent, const QString &path) 0760 { 0761 KDesktopFile cfg(path); 0762 KConfigGroup desktopGroup = cfg.desktopGroup(); 0763 const QString name = cfg.readName(); 0764 0765 // Here's where we need to create the right module... 0766 // ### TODO: make this KTrader/KLibrary based. 0767 const QString moduleName = desktopGroup.readPathEntry("X-KDE-TreeModule", QString("Directory")); 0768 const QString showHidden = desktopGroup.readEntry("X-KDE-TreeModule-ShowHidden"); 0769 0770 qCDebug(SIDEBAR_LOG) << "##### Loading module: " << moduleName << " file: " << path; 0771 0772 KonqSidebarTreeModule *module = NULL; 0773 getModule func = getPluginFactory(moduleName); 0774 if (func) { 0775 qCDebug(SIDEBAR_LOG) << "showHidden: " << showHidden; 0776 module = func(this, showHidden.toUpper() == "TRUE"); 0777 } 0778 0779 if (!module) { 0780 qCDebug(SIDEBAR_LOG) << "No Module loaded for" << moduleName; 0781 return; 0782 } 0783 0784 KonqSidebarTreeTopLevelItem *item; 0785 if (parent) { 0786 item = new KonqSidebarTreeTopLevelItem(parent, module, path); 0787 } else { 0788 item = new KonqSidebarTreeTopLevelItem(this, module, path); 0789 } 0790 0791 item->setText(0, name); 0792 item->setPixmap(0, SmallIcon(cfg.readIcon())); 0793 0794 module->addTopLevelItem(item); 0795 0796 m_topLevelItems.append(item); 0797 m_lstModules.append(module); 0798 0799 bool open = desktopGroup.readEntry("Open", false); 0800 if (open && item->isExpandable()) { 0801 item->setOpen(true); 0802 } 0803 } 0804 0805 void KonqSidebarTree::slotAnimation() 0806 { 0807 MapCurrentOpeningFolders::Iterator it = m_mapCurrentOpeningFolders.begin(); 0808 MapCurrentOpeningFolders::Iterator end = m_mapCurrentOpeningFolders.end(); 0809 for (; it != end; ++it) { 0810 uint &iconNumber = it.value().iconNumber; 0811 QString icon = QString::fromLatin1(it.value().iconBaseName).append(QString::number(iconNumber)); 0812 it.key()->setPixmap(0, SmallIcon(icon)); 0813 0814 iconNumber++; 0815 if (iconNumber > it.value().iconCount) { 0816 iconNumber = 1; 0817 } 0818 } 0819 } 0820 0821 void KonqSidebarTree::startAnimation(KonqSidebarTreeItem *item, const char *iconBaseName, uint iconCount, const QPixmap *originalPixmap) 0822 { 0823 const QPixmap *pix = originalPixmap ? originalPixmap : item->pixmap(0); 0824 if (pix) { 0825 m_mapCurrentOpeningFolders.insert(item, AnimationInfo(iconBaseName, iconCount, *pix)); 0826 if (!m_animationTimer->isActive()) { 0827 m_animationTimer->start(50); 0828 } 0829 } 0830 } 0831 0832 void KonqSidebarTree::stopAnimation(KonqSidebarTreeItem *item) 0833 { 0834 MapCurrentOpeningFolders::Iterator it = m_mapCurrentOpeningFolders.find(item); 0835 if (it != m_mapCurrentOpeningFolders.end()) { 0836 item->setPixmap(0, it.value().originalPixmap); 0837 m_mapCurrentOpeningFolders.remove(item); 0838 0839 if (m_mapCurrentOpeningFolders.isEmpty()) { 0840 m_animationTimer->stop(); 0841 } 0842 } 0843 } 0844 0845 KonqSidebarTreeItem *KonqSidebarTree::currentItem() const 0846 { 0847 return static_cast<KonqSidebarTreeItem *>(selectedItem()); 0848 } 0849 0850 void KonqSidebarTree::setContentsPos(int x, int y) 0851 { 0852 if (!m_scrollingLocked) { 0853 K3ListView::setContentsPos(x, y); 0854 } 0855 } 0856 0857 void KonqSidebarTree::slotItemRenamed(Q3ListViewItem *item, const QString &name, int col) 0858 { 0859 Q_ASSERT(col == 0); 0860 if (col != 0) { 0861 return; 0862 } 0863 Q_ASSERT(item); 0864 KonqSidebarTreeItem *treeItem = static_cast<KonqSidebarTreeItem *>(item); 0865 treeItem->rename(name); 0866 } 0867 0868 void KonqSidebarTree::enableActions(bool copy, bool cut, bool paste) 0869 { 0870 qCDebug(SIDEBAR_LOG) << copy << cut << paste; 0871 m_sidebarModule->enableCopy(copy); 0872 m_sidebarModule->enableCut(cut); 0873 m_sidebarModule->enablePaste(paste); 0874 } 0875 0876 void KonqSidebarTree::showToplevelContextMenu() 0877 { 0878 KonqSidebarTreeTopLevelItem *item = 0; 0879 KonqSidebarTreeItem *treeItem = currentItem(); 0880 if (treeItem && treeItem->isTopLevelItem()) { 0881 item = static_cast<KonqSidebarTreeTopLevelItem *>(treeItem); 0882 } 0883 0884 QMenu *menu = new QMenu; 0885 0886 if (item) { 0887 if (item->isTopLevelGroup()) { 0888 menu->addAction(m_collection->action("rename")); 0889 menu->addAction(m_collection->action("delete")); 0890 menu->addSeparator(); 0891 menu->addAction(m_collection->action("create_folder")); 0892 } else { 0893 menu->addAction(m_collection->action("open_tab")); 0894 menu->addAction(m_collection->action("open_window")); 0895 menu->addAction(m_collection->action("copy_location")); 0896 menu->addSeparator(); 0897 menu->addAction(m_collection->action("rename")); 0898 menu->addAction(m_collection->action("delete_link")); 0899 } 0900 menu->addSeparator(); 0901 menu->addAction(m_collection->action("item_properties")); 0902 } else { 0903 menu->addAction(m_collection->action("create_folder")); 0904 } 0905 0906 m_currentTopLevelItem = item; 0907 0908 menu->exec(QCursor::pos()); 0909 delete menu; 0910 0911 m_currentTopLevelItem = 0; 0912 } 0913 0914 void KonqSidebarTree::slotCreateFolder() 0915 { 0916 QString path; 0917 QString name = i18n("New Folder"); 0918 0919 while (true) { 0920 name = KInputDialog::getText(i18nc("@title:window", "Create New Folder"), 0921 i18n("Enter folder name:"), name); 0922 if (name.isEmpty()) { 0923 return; 0924 } 0925 0926 if (m_currentTopLevelItem) { 0927 path = m_currentTopLevelItem->path(); 0928 } else { 0929 path = m_dirtreeDir.dir.path(); 0930 } 0931 0932 if (!path.endsWith('/')) { 0933 path += '/'; 0934 } 0935 0936 path = path + name; 0937 0938 if (!QFile::exists(path)) { 0939 break; 0940 } 0941 0942 name = name + "-2"; 0943 } 0944 0945 KGlobal::dirs()->makeDir(path); 0946 0947 loadTopLevelGroup(m_currentTopLevelItem, path); 0948 } 0949 0950 void KonqSidebarTree::slotDelete() 0951 { 0952 if (currentItem()) { 0953 currentItem()->del(); 0954 } 0955 } 0956 0957 void KonqSidebarTree::slotTrash() 0958 { 0959 if (currentItem()) { 0960 currentItem()->trash(); 0961 } 0962 } 0963 0964 void KonqSidebarTree::slotRename() 0965 { 0966 if (currentItem()) { 0967 currentItem()->rename(); 0968 } 0969 } 0970 0971 void KonqSidebarTree::slotProperties() 0972 { 0973 if (!m_currentTopLevelItem) { 0974 return; 0975 } 0976 0977 QUrl url(m_currentTopLevelItem->path()); 0978 0979 QPointer<KPropertiesDialog> dlg(new KPropertiesDialog(url, this)); 0980 dlg->setFileNameReadOnly(true); 0981 dlg->exec(); 0982 delete dlg; 0983 } 0984 0985 void KonqSidebarTree::slotOpenNewWindow() 0986 { 0987 if (!m_currentTopLevelItem) { 0988 return; 0989 } 0990 emit createNewWindow(m_currentTopLevelItem->externalURL()); 0991 } 0992 0993 void KonqSidebarTree::slotOpenTab() 0994 { 0995 if (!m_currentTopLevelItem) { 0996 return; 0997 } 0998 BrowserArguments browserArgs; 0999 browserArgs.setNewTab(true); 1000 emit createNewWindow(m_currentTopLevelItem->externalURL(), 1001 KParts::OpenUrlArguments(), 1002 browserArgs); 1003 } 1004 1005 static QMimeData *mimeDataFor(const QUrl &url) 1006 { 1007 QMimeData *data = new QMimeData(); 1008 QList<QUrl> urlList; 1009 urlList.append(url); 1010 data->setUrls(urlList); 1011 return data; 1012 } 1013 1014 void KonqSidebarTree::slotCopyLocation() 1015 { 1016 if (!m_currentTopLevelItem) { 1017 return; 1018 } 1019 QUrl url = m_currentTopLevelItem->externalURL(); 1020 qApp->clipboard()->setMimeData(mimeDataFor(url), QClipboard::Selection); 1021 qApp->clipboard()->setMimeData(mimeDataFor(url), QClipboard::Clipboard); 1022 } 1023 1024 /////////////////////////////////////////////////////////////////// 1025 /////////////////////////////////////////////////////////////////// 1026 /* 1027 #ifdef __GNUC__ 1028 #warning KonqSidebarTreeToolTip removed, must implemented in event() function 1029 #endif 1030 void KonqSidebarTreeToolTip::maybeTip( const QPoint &point ) 1031 { 1032 Q3ListViewItem *item = m_view->itemAt( point ); 1033 if ( item ) { 1034 QString text = static_cast<KonqSidebarTreeItem*>( item )->toolTipText(); 1035 if ( !text.isEmpty() ) 1036 tip ( m_view->itemRect( item ), text ); 1037 } 1038 } 1039 */ 1040 1041 bool KonqSidebarTree::overrideShortcut(const QKeyEvent *e) 1042 { 1043 const int key = e->key() | e->modifiers(); 1044 if (key == Qt::Key_F2) { 1045 slotRename(); 1046 return true; 1047 } else if (key == Qt::Key_Delete) { 1048 qCDebug(SIDEBAR_LOG) << "delete key -> trash"; 1049 slotTrash(); 1050 return true; 1051 } else if (key == (Qt::SHIFT | Qt::Key_Delete)) { 1052 qCDebug(SIDEBAR_LOG) << "shift+delete -> delete"; 1053 slotDelete(); 1054 return true; 1055 } else if (KStandardShortcut::copy().contains(key)) { 1056 qCDebug(SIDEBAR_LOG) << "copy"; 1057 emit copy(); 1058 return true; 1059 } else if (KStandardShortcut::cut().contains(key)) { 1060 qCDebug(SIDEBAR_LOG) << "cut"; 1061 emit cut(); 1062 return true; 1063 } else if (KStandardShortcut::paste().contains(key)) { 1064 qCDebug(SIDEBAR_LOG) << "paste"; 1065 emit paste(); 1066 return true; 1067 } 1068 return false; 1069 } 1070 1071 // For F2 and other shortcuts to work we can't use a QAction; it would conflict with the 1072 // QAction from the active dolphinpart. So we have to use ShortcutOverride. 1073 // Many users requested keyboard shortcuts to work in the sidebar, so it's worth the ugliness (#80584) 1074 bool KonqSidebarTree::eventFilter(QObject *obj, QEvent *ev) 1075 { 1076 if (ev->type() == QEvent::ShortcutOverride) { 1077 QKeyEvent *e = static_cast<QKeyEvent *>(ev); 1078 if (overrideShortcut(e)) { 1079 e->accept(); 1080 return true; 1081 } 1082 } 1083 return K3ListView::eventFilter(obj, ev); 1084 } 1085