File indexing completed on 2024-04-21 05:50:00
0001 //************************************************************************** 0002 // Copyright 2006 - 2018 Martin Koller, kollix@aon.at 0003 // 0004 // This program is free software; you can redistribute it and/or modify 0005 // it under the terms of the GNU General Public License as published by 0006 // the Free Software Foundation, version 2 of the License 0007 // 0008 //************************************************************************** 0009 0010 #include <Selector.hxx> 0011 0012 #include <kio/global.h> 0013 #include <KIconLoader> 0014 #include <KIconEffect> 0015 #include <KIconUtils> 0016 #include <KLocalizedString> 0017 #include <KPropertiesDialog> 0018 #include <KFileItem> 0019 #include <KApplicationTrader> 0020 #include <KActionCollection> 0021 #include <KMessageBox> 0022 0023 #include <KIO/ApplicationLauncherJob> 0024 #include <KIO/OpenUrlJob> 0025 #include <kio_version.h> 0026 #include <KIO/JobUiDelegateFactory> 0027 0028 #include <QDir> 0029 #include <QPixmap> 0030 #include <QDateTime> 0031 #include <QCollator> 0032 #include <QHeaderView> 0033 #include <QMenu> 0034 #include <QPointer> 0035 0036 #include <iostream> 0037 using namespace std; 0038 0039 //-------------------------------------------------------------------------------- 0040 //-------------------------------------------------------------------------------- 0041 0042 class Model : public QStandardItemModel 0043 { 0044 public: 0045 explicit Model(Selector *parent) : QStandardItemModel(parent), tree(parent) 0046 { 0047 const char *lc_collate = ::getenv("LC_COLLATE"); 0048 if ( lc_collate ) 0049 collator.setLocale(QLocale(QLatin1String(lc_collate))); 0050 0051 collator.setNumericMode(true); 0052 } 0053 0054 bool hasChildren(const QModelIndex &index = QModelIndex()) const override 0055 { 0056 QStandardItem *item = itemFromIndex(index); 0057 0058 if ( !item ) 0059 return true; // invisible root 0060 0061 return !(item->flags() & Qt::ItemNeverHasChildren); 0062 } 0063 0064 Selector *tree; 0065 QCollator collator; 0066 }; 0067 0068 //-------------------------------------------------------------------------------- 0069 //-------------------------------------------------------------------------------- 0070 0071 class ListItem : public QStandardItem 0072 { 0073 public: 0074 ListItem(QStandardItem *parent, const QString &text, bool dir) 0075 : isDir_(dir), partly(false) 0076 { 0077 parent->appendRow(this); 0078 parent->setChild(row(), 1, new QStandardItem); 0079 parent->setChild(row(), 2, new QStandardItem); 0080 0081 setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable); 0082 0083 if ( !isDir_ ) 0084 setFlags(flags() | Qt::ItemNeverHasChildren); 0085 0086 setCheckState(Qt::Unchecked); 0087 setText(0, text, key(text)); 0088 } 0089 0090 int type() const override { return QStandardItem::UserType; } 0091 0092 bool isOn() const { return checkState() == Qt::Checked; } 0093 void setOn(bool on) { setCheckState(on ? Qt::Checked : Qt::Unchecked); } 0094 0095 void setText(int column, const QString &txt, const QVariant &sortKey) 0096 { 0097 QStandardItem *item; 0098 0099 if ( parent() ) 0100 item = parent()->child(row(), column); 0101 else 0102 item = model()->item(row(), column); 0103 0104 item->setText(txt); 0105 item->setData(sortKey, Qt::UserRole); 0106 } 0107 0108 void setData(const QVariant &value, int role = Qt::UserRole + 1) override 0109 { 0110 if ( role == Qt::CheckStateRole ) 0111 { 0112 if ( value.toInt() != checkState() ) 0113 { 0114 QStandardItem::setData(value, role); 0115 stateChanged(); 0116 return; 0117 } 0118 } 0119 0120 QStandardItem::setData(value, role); 0121 } 0122 0123 // check if all siblings have the same state as the parent or are partly marked 0124 // If not, then the parent must have the partly flag set, otherwise the parents 0125 // partly flag can be cleared 0126 void recursSiblingsUp() 0127 { 0128 if ( !parent() ) return; 0129 0130 bool allSame = true, state = static_cast<ListItem*>(parent())->isOn(); 0131 0132 for (int i = 0; i < parent()->rowCount(); i++) 0133 { 0134 QStandardItem *item = parent()->child(i); 0135 0136 if ( (static_cast<ListItem*>(item)->isOn() != state) || static_cast<ListItem*>(item)->partly ) 0137 { 0138 allSame = false; 0139 break; 0140 } 0141 } 0142 0143 // only continue upwards if the parents partly status changes 0144 if ( static_cast<ListItem*>(parent())->partly != !allSame ) 0145 { 0146 static_cast<ListItem*>(parent())->partly = !allSame; 0147 0148 if ( !allSame ) 0149 static_cast<ListItem*>(parent())->setForeground(Qt::blue); 0150 else 0151 { 0152 QWidget *w = static_cast<Model *>(model())->tree; 0153 static_cast<ListItem*>(parent())->setForeground(w->palette().color(w->foregroundRole())); 0154 } 0155 0156 static_cast<ListItem*>(parent())->recursSiblingsUp(); 0157 } 0158 } 0159 0160 void stateChanged() 0161 { 0162 recursActivate(isOn()); 0163 recursSiblingsUp(); 0164 } 0165 0166 // set all children recursively below this to on 0167 void recursActivate(bool on) 0168 { 0169 partly = false; // all children will get the same state 0170 0171 QWidget *w = static_cast<Model *>(model())->tree; 0172 setForeground(w->palette().color(w->foregroundRole())); 0173 0174 setOn(on); 0175 0176 for (int i = 0; i < rowCount(); i++) 0177 static_cast<ListItem*>(child(i))->recursActivate(on); 0178 } 0179 0180 bool isDir() const { return isDir_; } 0181 0182 int key(const QString &text) const 0183 { 0184 bool hidden = text[0] == QLatin1Char('.'); 0185 0186 // sort directories _always_ first, and hidden before shown 0187 if ( isDir_ ) 0188 return hidden ? 0 : 1; 0189 else // file 0190 return hidden ? 2 : 3; 0191 } 0192 0193 bool operator<(const QStandardItem &other_) const override 0194 { 0195 QTreeView *w = static_cast<Model *>(model())->tree; 0196 Qt::SortOrder order = w->header()->sortIndicatorOrder(); 0197 0198 const ListItem &other = static_cast<const ListItem &>(other_); 0199 0200 int myKey = data(Qt::UserRole).toInt(); 0201 int otherKey = other.data(Qt::UserRole).toInt(); 0202 0203 if ( myKey != otherKey ) 0204 return (order == Qt::AscendingOrder) ? (myKey < otherKey) : (myKey > otherKey); 0205 else 0206 { 0207 // don't use localeAwareCompare. QLocale does not use LC_COLLATE QTBUG-29397 0208 return static_cast<Model *>(model())->collator.compare(text(), other.text()) < 0; 0209 } 0210 } 0211 0212 void setSize(KIO::filesize_t size) 0213 { 0214 setText(1, KIO::convertSize(size), size); 0215 } 0216 0217 void setLastModified(const QDateTime &time) 0218 { 0219 setText(2, QLocale().toString(time, QLocale::ShortFormat), time); 0220 } 0221 0222 void setShowHiddenFiles(bool show) 0223 { 0224 QTreeView *w = static_cast<Model *>(model())->tree; 0225 0226 QStandardItem *parentItem = parent() ? parent() : model()->invisibleRootItem(); 0227 0228 w->setRowHidden(row(), parentItem->index(), show ? false : text()[0] == QLatin1Char('.')); 0229 0230 for (int i = 0; i < rowCount(); i++) 0231 static_cast<ListItem*>(child(i))->setShowHiddenFiles(show); 0232 } 0233 0234 private: 0235 bool isDir_; 0236 bool partly; // is this an item which is not fully (but partly - some of the children) selected 0237 0238 }; 0239 0240 //-------------------------------------------------------------------------------- 0241 //-------------------------------------------------------------------------------- 0242 //-------------------------------------------------------------------------------- 0243 //-------------------------------------------------------------------------------- 0244 0245 Selector::Selector(QWidget *parent, KActionCollection *actionCollection) 0246 : QTreeView(parent) 0247 { 0248 itemModel = new Model(this); 0249 0250 setModel(itemModel); 0251 0252 itemModel->setSortRole(Qt::UserRole); 0253 itemModel->setHorizontalHeaderLabels(QStringList() << i18n("Name") << i18n("Size") << i18n("Last Modified")); 0254 0255 setRootIsDecorated(true); 0256 0257 // start with / as root node 0258 ListItem *item = new ListItem(itemModel->invisibleRootItem(), QStringLiteral("/"), true); 0259 QFileInfo info(QStringLiteral("/")); 0260 item->setSize(info.size()); 0261 item->setLastModified(info.lastModified()); 0262 item->setIcon(QIcon::fromTheme(QStringLiteral("folder"))); 0263 setExpanded(item->index(), true); 0264 0265 fillTree(item, QStringLiteral("/"), false); 0266 0267 connect(this, &Selector::expanded, this, &Selector::expandedSlot); 0268 0269 minSize = QSize(columnWidth(0) + columnWidth(1), -1); 0270 resizeColumnToContents(0); 0271 resizeColumnToContents(1); 0272 resizeColumnToContents(2); 0273 0274 sortByColumn(0, Qt::AscendingOrder); 0275 0276 // context menu 0277 menu = new QMenu(this); 0278 QAction *action; 0279 0280 action = KStandardAction::open(this, SLOT(open()), actionCollection); 0281 menu->addAction(action); 0282 0283 connect(this, &Selector::doubleClicked, this, &Selector::doubleClickedSlot); 0284 0285 openWithSubMenu = new QMenu(i18n("Open With"), this); 0286 menu->addMenu(openWithSubMenu); 0287 connect(openWithSubMenu, &QMenu::aboutToShow, this, &Selector::populateOpenMenu); 0288 connect(openWithSubMenu, &QMenu::triggered, this, &Selector::openWith); 0289 0290 // just since KF 5.25 0291 //deleteFileAction = KStandardAction::deleteFile(this, SLOT(deleteFile()), actionCollection); 0292 deleteFileAction = actionCollection->addAction(QStringLiteral("deleteFile"), this, SLOT(deleteFile())); 0293 deleteFileAction->setText(i18n("Delete File")); 0294 deleteFileAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete"))); 0295 deleteFileAction->setShortcut(QKeySequence(Qt::SHIFT | Qt::Key_Delete)); 0296 menu->addAction(deleteFileAction); 0297 0298 action = actionCollection->addAction(QStringLiteral("properties"), this, SLOT(properties())); 0299 action->setText(i18n("Properties...")); 0300 menu->addAction(action); 0301 } 0302 0303 //-------------------------------------------------------------------------------- 0304 0305 void Selector::openHomeDir() 0306 { 0307 const char *home = ::getenv("HOME"); 0308 if ( home ) 0309 { 0310 QStandardItem *homeItem = findItemByPath(QFile::decodeName(home)); 0311 if ( homeItem ) 0312 { 0313 setExpanded(homeItem->index(), true); 0314 scrollTo(homeItem->index()); 0315 } 0316 } 0317 } 0318 0319 //-------------------------------------------------------------------------------- 0320 0321 QSize Selector::minimumSizeHint() const 0322 { 0323 return minSize; 0324 } 0325 0326 //-------------------------------------------------------------------------------- 0327 0328 void Selector::fillTree(ListItem *parent, const QString &path, bool on) 0329 { 0330 setSortingEnabled(false); 0331 0332 const QDir::Filters filter = QDir::AllEntries | QDir::Hidden | QDir::System | QDir::NoDotAndDotDot; 0333 0334 QDir dir(path, QString(), QDir::NoSort, filter); 0335 const QFileInfoList list = dir.entryInfoList(); 0336 0337 ListItem *item; 0338 0339 for (int i = 0; i < list.count(); i++) 0340 { 0341 if ( parent ) 0342 item = new ListItem(parent, list[i].fileName(), list[i].isDir()); 0343 else 0344 item = new ListItem(itemModel->invisibleRootItem(), list[i].fileName(), list[i].isDir()); 0345 0346 item->setOn(on); 0347 item->setSize(list[i].size()); 0348 item->setLastModified(list[i].lastModified()); 0349 item->setShowHiddenFiles(showHiddenFiles); 0350 0351 if ( item->isDir() ) 0352 { 0353 QDir dir(list[i].absoluteFilePath(), QString(), QDir::NoSort, filter); 0354 0355 // symlinked dirs can not be expanded as they are stored as single files in the archive 0356 if ( (dir.count() > 0) && !list[i].isSymLink() ) 0357 ; // can have children 0358 else 0359 item->setFlags(item->flags() | Qt::ItemNeverHasChildren); 0360 0361 static QPixmap folderIcon; 0362 static QPixmap folderLinkIcon; 0363 static QPixmap folderIconHidden; 0364 static QPixmap folderLinkIconHidden; 0365 0366 if ( folderIcon.isNull() ) // only get the icons once 0367 { 0368 KIconEffect effect; 0369 0370 folderIcon = QIcon::fromTheme(QStringLiteral("folder")).pixmap(KIconLoader::SizeSmall); 0371 folderIconHidden = effect.apply(folderIcon, KIconEffect::DeSaturate, 0, QColor(), true); 0372 0373 folderLinkIcon = KIconUtils::addOverlay(folderIcon, 0374 QIcon::fromTheme(QStringLiteral("emblem-symbolic-link")), 0375 Qt::BottomRightCorner).pixmap(KIconLoader::SizeSmall); 0376 0377 folderLinkIconHidden = effect.apply(folderLinkIcon, KIconEffect::DeSaturate, 0, QColor(), true); 0378 } 0379 0380 item->setIcon(list[i].isSymLink() ? 0381 (list[i].isHidden() ? folderLinkIconHidden : folderLinkIcon) 0382 : (list[i].isHidden() ? folderIconHidden : folderIcon)); 0383 } 0384 else 0385 { 0386 static QPixmap documentIcon; 0387 static QPixmap documentLinkIcon; 0388 static QPixmap documentIconHidden; 0389 static QPixmap documentLinkIconHidden; 0390 0391 if ( documentIcon.isNull() ) // only get the icons once 0392 { 0393 KIconEffect effect; 0394 0395 documentIcon = QIcon::fromTheme(QStringLiteral("text-x-generic")).pixmap(KIconLoader::SizeSmall); 0396 documentIconHidden = effect.apply(documentIcon, KIconEffect::DeSaturate, 0, QColor(), true); 0397 0398 documentLinkIcon = KIconUtils::addOverlay(documentIcon, 0399 QIcon::fromTheme(QStringLiteral("emblem-symbolic-link")), 0400 Qt::BottomRightCorner).pixmap(KIconLoader::SizeSmall); 0401 0402 documentLinkIconHidden = effect.apply(documentLinkIcon, KIconEffect::DeSaturate, 0, QColor(), true); 0403 } 0404 0405 item->setIcon(list[i].isSymLink() ? 0406 (list[i].isHidden() ? documentLinkIconHidden : documentLinkIcon) 0407 : (list[i].isHidden() ? documentIconHidden : documentIcon)); 0408 } 0409 } 0410 setSortingEnabled(true); 0411 } 0412 0413 //-------------------------------------------------------------------------------- 0414 0415 QString Selector::getPath(QStandardItem *item) const 0416 { 0417 if ( !item ) 0418 return QString(); 0419 else if ( !item->parent() ) 0420 return item->text(); // root 0421 else if ( item->parent() == itemModel->item(0) ) 0422 return QStringLiteral("/") + item->text(); 0423 else 0424 return getPath(item->parent()) + QStringLiteral("/") + item->text(); 0425 } 0426 0427 //-------------------------------------------------------------------------------- 0428 0429 void Selector::expandedSlot(const QModelIndex &index) 0430 { 0431 QStandardItem *item = itemModel->itemFromIndex(index); 0432 0433 if ( item->rowCount() ) return; // already done 0434 0435 fillTree(static_cast<ListItem *>(item), getPath(item), static_cast<ListItem *>(item)->isOn()); 0436 } 0437 0438 //-------------------------------------------------------------------------------- 0439 0440 void Selector::getBackupList(QStringList &includes, QStringList &excludes) const 0441 { 0442 for (int i = 0; i < itemModel->rowCount(); i++) 0443 getBackupLists(itemModel->item(i, 0), includes, excludes); 0444 0445 /* 0446 cerr << "includes:" << includes.count() << endl; 0447 for (QStringList::const_iterator it = includes.begin(); (it != includes.end()); ++it) 0448 cerr << *it << endl; 0449 0450 cerr << "excludes:" << excludes.count() << endl; 0451 for (QStringList::const_iterator it = excludes.begin(); (it != excludes.end()); ++it) 0452 cerr << *it << endl; 0453 0454 cerr << endl; 0455 */ 0456 } 0457 0458 //-------------------------------------------------------------------------------- 0459 0460 void Selector::getBackupLists(QStandardItem *start, QStringList &includes, QStringList &excludes, bool add) const 0461 { 0462 if ( static_cast<ListItem*>(start)->isOn() ) 0463 { 0464 if ( add ) 0465 includes.append(getPath(start)); // include it 0466 0467 if ( static_cast<ListItem*>(start)->isDir() ) 0468 { 0469 // get excludes from this dir 0470 for (int i = 0; i < start->rowCount(); i++) 0471 { 0472 QStandardItem *item = start->child(i); 0473 0474 if ( !static_cast<ListItem*>(item)->isOn() ) 0475 excludes.append(getPath(item)); 0476 0477 if ( static_cast<ListItem*>(item)->isDir() ) 0478 getBackupLists(item, includes, excludes, false); 0479 } 0480 } 0481 } 0482 else 0483 if ( static_cast<ListItem*>(start)->isDir() ) 0484 { 0485 for (int i = 0; i < start->rowCount(); i++) 0486 getBackupLists(start->child(i), includes, excludes); 0487 } 0488 } 0489 0490 //-------------------------------------------------------------------------------- 0491 0492 void Selector::setBackupList(const QStringList &includes, const QStringList &excludes) 0493 { 0494 // clear all current settings 0495 for (int i = 0; i < itemModel->rowCount(); i++) 0496 static_cast<ListItem*>(itemModel->item(i, 0))->recursActivate(false); 0497 0498 for (QStringList::const_iterator it = includes.begin(); (it != includes.end()); ++it) 0499 { 0500 QStandardItem *item = findItemByPath(*it); 0501 if ( item ) 0502 static_cast<ListItem*>(item)->recursActivate(true); 0503 } 0504 0505 for (QStringList::const_iterator it = excludes.begin(); (it != excludes.end()); ++it) 0506 { 0507 QStandardItem *item = findItemByPath(*it); 0508 if ( item ) 0509 static_cast<ListItem*>(item)->setOn(false); 0510 } 0511 } 0512 0513 //-------------------------------------------------------------------------------- 0514 0515 QStandardItem *Selector::findItemByPath(const QString &path) 0516 { 0517 QStringList items = path.split(QLatin1Char('/'), Qt::SkipEmptyParts); 0518 QStandardItem *item = itemModel->invisibleRootItem()->child(0); 0519 0520 for (int i = 0; i < items.count(); i++) 0521 { 0522 item = findItem(item, items[i]); 0523 0524 if ( !item ) 0525 return nullptr; 0526 else 0527 { 0528 if ( (i != (items.count() - 1)) && 0529 static_cast<ListItem*>(item)->isDir() && (item->rowCount() == 0) ) 0530 expandedSlot(item->index()); 0531 } 0532 } 0533 0534 return item; 0535 } 0536 0537 //-------------------------------------------------------------------------------- 0538 0539 QStandardItem *Selector::findItem(QStandardItem *start, const QString &toFind) const 0540 { 0541 for (int i = 0; i < (start ? start->rowCount() : itemModel->rowCount()); i++) 0542 { 0543 QStandardItem *item = start ? start->child(i) : itemModel->item(i, 0); 0544 0545 if ( item->text() == toFind ) 0546 return item; 0547 } 0548 0549 return nullptr; 0550 } 0551 0552 //-------------------------------------------------------------------------------- 0553 0554 ListItem *Selector::getSelectedItem() const 0555 { 0556 QModelIndex index = selectionModel()->currentIndex(); 0557 if ( !index.isValid() ) 0558 return nullptr; 0559 0560 QStandardItem *item = itemModel->itemFromIndex(itemModel->index(index.row(), 0, index.parent())); 0561 0562 if ( !item || (item->type() != QStandardItem::UserType) ) // just be safe 0563 return nullptr; 0564 0565 return static_cast<ListItem *>(item); 0566 } 0567 0568 //-------------------------------------------------------------------------------- 0569 0570 void Selector::contextMenuEvent(QContextMenuEvent *) 0571 { 0572 ListItem *item = getSelectedItem(); 0573 0574 if ( !item ) 0575 return; 0576 0577 bool canDelete = true; 0578 0579 if ( item->isDir() ) 0580 { 0581 // only if it's empty 0582 canDelete = QDir(getPath(item), QString(), QDir::NoSort, 0583 QDir::AllEntries | QDir::System | QDir::NoDotAndDotDot).count() == 0; 0584 } 0585 0586 deleteFileAction->setEnabled(canDelete); 0587 0588 menu->exec(QCursor::pos()); 0589 } 0590 0591 //-------------------------------------------------------------------------------- 0592 0593 void Selector::deleteFile() 0594 { 0595 ListItem *item = getSelectedItem(); 0596 0597 if ( !item ) 0598 return; 0599 0600 QUrl sourceUrl = QUrl::fromLocalFile(getPath(item)); 0601 0602 if ( KMessageBox::warningTwoActions(this, 0603 i18n("Do you really want to delete '%1'?", sourceUrl.path()), 0604 i18n("Delete"), 0605 KStandardGuiItem::del(), KStandardGuiItem::cancel(), 0606 QStringLiteral("dontAskAgainDelete")) == KMessageBox::PrimaryAction ) 0607 { 0608 QStandardItem *parent = nullptr; 0609 0610 if ( item->isDir() ) 0611 { 0612 QDir dir(sourceUrl.path()); 0613 0614 if ( !dir.removeRecursively() ) 0615 KMessageBox::error(this, i18n("Could not delete directory '%1'.", sourceUrl.path())); 0616 else 0617 parent = item->parent(); 0618 } 0619 else 0620 { 0621 QFile theFile(sourceUrl.path()); 0622 0623 if ( !theFile.remove(sourceUrl.path()) ) 0624 KMessageBox::error(this, i18n("Could not delete file '%1'.\nReason: %2", sourceUrl.path(), theFile.errorString())); 0625 else 0626 parent = item->parent(); 0627 } 0628 0629 if ( parent ) 0630 { 0631 parent->removeRow(item->row()); 0632 0633 if ( parent->type() == QStandardItem::UserType ) 0634 static_cast<ListItem *>(parent)->stateChanged(); // make sure removed item is taken into account 0635 } 0636 } 0637 } 0638 0639 //-------------------------------------------------------------------------------- 0640 0641 void Selector::properties() 0642 { 0643 ListItem *item = getSelectedItem(); 0644 0645 if ( !item ) 0646 return; 0647 0648 QUrl sourceUrl = QUrl::fromLocalFile(getPath(item)); 0649 0650 QPointer<KPropertiesDialog> dialog = new KPropertiesDialog(sourceUrl, this); 0651 connect(dialog.data(), &KPropertiesDialog::applied, this, 0652 [item, dialog]() 0653 { 0654 // make sure a renamed file is shown with the new name in the tree 0655 item->setText(0, dialog->item().name(), item->key(dialog->item().name())); 0656 }); 0657 0658 dialog->exec(); 0659 delete dialog; 0660 } 0661 0662 //-------------------------------------------------------------------------------- 0663 0664 void Selector::populateOpenMenu() 0665 { 0666 ListItem *item = getSelectedItem(); 0667 0668 if ( !item ) 0669 return; 0670 0671 QUrl sourceUrl = QUrl::fromLocalFile(getPath(item)); 0672 0673 qDeleteAll(openWithSubMenu->actions()); 0674 serviceForName.clear(); 0675 0676 KFileItem fileItem(sourceUrl); 0677 QString mimeType(fileItem.determineMimeType().name()); 0678 0679 const KService::List services = KApplicationTrader::queryByMimeType(mimeType); 0680 0681 for (const KService::Ptr &service : services) 0682 { 0683 QString text = service->name().replace(QLatin1Char('&'), QStringLiteral("&&")); 0684 QAction* action = openWithSubMenu->addAction(text); 0685 action->setIcon(QIcon::fromTheme(service->icon())); 0686 action->setData(service->name()); 0687 0688 serviceForName[service->name()] = service; 0689 } 0690 0691 openWithSubMenu->addSeparator(); 0692 openWithSubMenu->addAction(i18n("Other Application...")); 0693 0694 QAction* action = openWithSubMenu->addAction(i18n("File Manager")); 0695 action->setIcon(QIcon::fromTheme(QStringLiteral("folder"))); 0696 action->setData(QStringLiteral("-")); 0697 } 0698 0699 //-------------------------------------------------------------------------------- 0700 0701 void Selector::doubleClickedSlot() 0702 { 0703 ListItem *item = getSelectedItem(); 0704 0705 if ( !item || item->isDir() ) 0706 return; 0707 0708 open(); 0709 } 0710 0711 //-------------------------------------------------------------------------------- 0712 0713 void Selector::open() 0714 { 0715 ListItem *item = getSelectedItem(); 0716 0717 if ( !item ) 0718 return; 0719 0720 QUrl sourceUrl = QUrl::fromLocalFile(getPath(item)); 0721 0722 auto *job = new KIO::OpenUrlJob(sourceUrl, window()); 0723 job->setRunExecutables(false); 0724 job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this)); 0725 job->start(); 0726 } 0727 0728 //-------------------------------------------------------------------------------- 0729 0730 void Selector::openWith(QAction *action) 0731 { 0732 ListItem *item = getSelectedItem(); 0733 0734 if ( !item ) 0735 return; 0736 0737 QUrl sourceUrl = QUrl::fromLocalFile(getPath(item)); 0738 0739 QString name = action->data().toString(); 0740 0741 if ( name.isEmpty() ) // Other Application... 0742 { 0743 KIO::ApplicationLauncherJob *job = new KIO::ApplicationLauncherJob(); 0744 job->setUrls(QList<QUrl>() << sourceUrl); 0745 job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this)); 0746 job->start(); 0747 return; 0748 } 0749 0750 if ( name == QLatin1String("-") ) // File Manager 0751 { 0752 KIO::OpenUrlJob *job = new KIO::OpenUrlJob(sourceUrl.adjusted(QUrl::RemoveFilename), QStringLiteral("inode/directory")); 0753 job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this)); 0754 job->start(); 0755 0756 return; 0757 } 0758 0759 KService::Ptr service = serviceForName[name]; 0760 KIO::ApplicationLauncherJob *job = new KIO::ApplicationLauncherJob(service); 0761 job->setUrls(QList<QUrl>() << sourceUrl); 0762 job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this)); 0763 job->start(); 0764 } 0765 0766 //-------------------------------------------------------------------------------- 0767 0768 void Selector::setShowHiddenFiles(bool show) 0769 { 0770 showHiddenFiles = show; 0771 0772 for (int i = 0; i < itemModel->invisibleRootItem()->rowCount(); i++) 0773 static_cast<ListItem *>(itemModel->item(i, 0))->setShowHiddenFiles(show); 0774 } 0775 0776 //-------------------------------------------------------------------------------- 0777 0778 #include "moc_Selector.cpp"