File indexing completed on 2024-04-21 16:33:18
0001 /* 0002 SPDX-FileCopyrightText: 2001 Shie Erlich <krusader@users.sourceforge.net> 0003 SPDX-FileCopyrightText: 2001 Rafi Yanai <krusader@users.sourceforge.net> 0004 SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "krslots.h" 0010 0011 // QtCore 0012 #include <QDir> 0013 #include <QEvent> 0014 #include <QList> 0015 #include <QPoint> 0016 #include <QStringList> 0017 #include <QTemporaryFile> 0018 // QtGui 0019 #include <QKeyEvent> 0020 #include <QPixmapCache> 0021 // QtWidgets 0022 #include <QApplication> 0023 0024 #include <KConfigCore/KSharedConfig> 0025 #include <KCoreAddons/KShell> 0026 #include <KI18n/KLocalizedString> 0027 #include <KWidgetsAddons/KMessageBox> 0028 #include <KWidgetsAddons/KToggleAction> 0029 #include <utility> 0030 0031 #include "defaults.h" 0032 #include "icon.h" 0033 #include "kractions.h" 0034 #include "krservices.h" 0035 #include "krtrashhandler.h" 0036 #include "krusader.h" 0037 #include "krusaderview.h" 0038 #include "panelmanager.h" 0039 0040 #include "ActionMan/actionman.h" 0041 #include "BookMan/krbookmarkbutton.h" 0042 #include "BookMan/krbookmarkhandler.h" 0043 #include "Dialogs/krdialogs.h" 0044 #include "Dialogs/krspecialwidgets.h" 0045 #include "Dialogs/krspwidgets.h" 0046 #include "DiskUsage/diskusagegui.h" 0047 #include "FileSystem/fileitem.h" 0048 #include "FileSystem/filesystem.h" 0049 #include "FileSystem/krquery.h" 0050 #include "GUI/dirhistorybutton.h" 0051 #include "GUI/kcmdline.h" 0052 #include "GUI/kfnkeys.h" 0053 #include "GUI/krusaderstatus.h" 0054 #include "GUI/mediabutton.h" 0055 #include "GUI/terminaldock.h" 0056 #include "KViewer/krviewer.h" 0057 #include "Konfigurator/konfigurator.h" 0058 #include "Locate/locate.h" 0059 #include "MountMan/kmountman.h" 0060 #include "Panel/PanelView/krselectionmode.h" 0061 #include "Panel/PanelView/krview.h" 0062 #include "Panel/PanelView/krviewfactory.h" 0063 #include "Panel/PanelView/krviewitem.h" 0064 #include "Panel/listpanel.h" 0065 #include "Panel/panelfunc.h" 0066 #include "Panel/sidebar.h" 0067 #include "Search/krsearchdialog.h" 0068 #include "Search/krsearchmod.h" 0069 #include "Splitter/combiner.h" 0070 #include "Splitter/splitter.h" 0071 #include "Splitter/splittergui.h" 0072 0073 #ifdef SYNCHRONIZER_ENABLED 0074 #include "Synchronizer/synchronizergui.h" 0075 #endif 0076 0077 #define ACTIVE_VIEW _mainWindow->activeView() 0078 0079 static const QStringList kKioSupportCompareApps = {"kdiff3", "kompare"}; 0080 0081 KrSlots::KrSlots(QObject *parent) 0082 : QObject(parent) 0083 , _mainWindow(krApp) 0084 { 0085 } 0086 0087 void KrSlots::sendFileByEmail(const QList<QUrl> &urls) 0088 { 0089 if (urls.count() == 0) { 0090 KMessageBox::error(nullptr, i18n("No selected files to send.")); 0091 return; 0092 } 0093 0094 QString mailProg; 0095 QStringList lst = KrServices::supportedTools(); 0096 if (lst.contains("MAIL")) 0097 mailProg = lst[lst.indexOf("MAIL") + 1]; 0098 else { 0099 KMessageBox::error(nullptr, i18n("Krusader cannot find a supported mail client. Please install one to your path. Hint: Krusader supports KMail.")); 0100 return; 0101 } 0102 0103 QString subject, separator; 0104 foreach (const QUrl &url, urls) { 0105 subject += separator + url.fileName(); 0106 separator = ','; 0107 } 0108 subject = i18np("Sending file: %2", "Sending files: %2", urls.count(), subject); 0109 0110 KProcess proc; 0111 0112 QString executable = QUrl::fromLocalFile(mailProg).fileName(); 0113 if (executable == QStringLiteral("kmail")) { 0114 proc << mailProg << "--subject" << subject; 0115 foreach (const QUrl &url2, urls) 0116 proc << "--attach" << url2.toDisplayString(); 0117 } else if (executable == QStringLiteral("thunderbird")) { 0118 QString param = "attachment=\'"; 0119 separator = ""; 0120 foreach (const QUrl &url2, urls) { 0121 param += separator + url2.toDisplayString(); 0122 separator = ','; 0123 } 0124 param += "\',subject=\'" + subject + "\'"; 0125 proc << mailProg << "--compose" << param; 0126 } else if (executable == QStringLiteral("evolution")) { 0127 QString param = "mailto:?cc=&subject=" + subject + "&attach="; 0128 separator = ""; 0129 foreach (const QUrl &url2, urls) { 0130 param += separator + url2.toDisplayString(); 0131 separator = "&attach="; 0132 } 0133 proc << mailProg << param + ""; 0134 } 0135 0136 if (!proc.startDetached()) 0137 KMessageBox::error(nullptr, i18n("Error executing %1.", mailProg)); 0138 } 0139 0140 void KrSlots::compareContent() 0141 { 0142 const QStringList lstLeft = LEFT_PANEL->getSelectedNames(); 0143 const QStringList lstRight = RIGHT_PANEL->getSelectedNames(); 0144 const QStringList lstActive = ACTIVE_PANEL->gui->isLeft() ? lstLeft : lstRight; 0145 QUrl name1, name2; 0146 0147 if (lstLeft.count() == 1 && lstRight.count() == 1) { 0148 // first, see if we've got exactly 1 selected file in each panel: 0149 name1 = LEFT_PANEL->func->files()->getUrl(lstLeft[0]); 0150 name2 = RIGHT_PANEL->func->files()->getUrl(lstRight[0]); 0151 } else if (lstActive.count() == 2) { 0152 // next try: are in the current panel exactly 2 files selected? 0153 name1 = ACTIVE_PANEL->func->files()->getUrl(lstActive[0]); 0154 name2 = ACTIVE_PANEL->func->files()->getUrl(lstActive[1]); 0155 } else if (ACTIVE_PANEL->otherPanel()->func->files()->getFileItem(ACTIVE_VIEW->getCurrentItem())) { 0156 // next try: is in the other panel a file with the same name? 0157 name1 = ACTIVE_PANEL->func->files()->getUrl(ACTIVE_VIEW->getCurrentItem()); 0158 name2 = ACTIVE_PANEL->otherPanel()->func->files()->getUrl(ACTIVE_VIEW->getCurrentItem()); 0159 } else { 0160 // if we got here, then we can't be sure what file to diff 0161 KMessageBox::error(nullptr, 0162 "<qt>" + i18n("Do not know which files to compare.") + "<br/><br/>" 0163 + i18n("To compare two files by content, you can either:<ul><li>Select one file in the left panel, and one in the right " 0164 "panel.</li><li>Select exactly two files in the active panel.</li><li>Make sure there is a file in the other panel, with " 0165 "the same name as the current file in the active panel.</li></ul>") 0166 + "</qt>"); 0167 0168 return; 0169 } 0170 0171 // else implied: all ok, let's call an external program to compare files 0172 // but if any of the files isn't local, download it first 0173 compareContent(name1, name2); 0174 } 0175 0176 bool downloadToTemp(const QUrl &url, QString &dest) 0177 { 0178 QTemporaryFile tmpFile; 0179 tmpFile.setAutoRemove(false); 0180 if (tmpFile.open()) { 0181 dest = tmpFile.fileName(); 0182 KIO::Job *job = KIO::file_copy(url, QUrl::fromLocalFile(dest), -1, KIO::Overwrite | KIO::HideProgressInfo); 0183 if (!job->exec()) { 0184 KMessageBox::error(krApp, i18n("Krusader is unable to download %1", url.fileName())); 0185 return false; 0186 } 0187 return true; 0188 } 0189 return false; 0190 } 0191 0192 void KrSlots::compareContent(const QUrl &url1, const QUrl &url2) 0193 { 0194 QString diffProg; 0195 QStringList lst = KrServices::supportedTools(); 0196 if (lst.contains("DIFF")) 0197 diffProg = lst[lst.indexOf("DIFF") + 1]; 0198 else { 0199 KMessageBox::error(nullptr, 0200 i18n("Krusader cannot find any of the supported diff-frontends. Please install one to your path. Hint: Krusader supports Kompare, " 0201 "KDiff3 and Xxdiff.")); 0202 return; 0203 } 0204 0205 QString tmp1; 0206 QString tmp2; 0207 if (kKioSupportCompareApps.contains(QUrl::fromLocalFile(diffProg).fileName())) { 0208 tmp1 = url1.toDisplayString(); 0209 tmp2 = url2.toDisplayString(); 0210 } else { 0211 if (!url1.isLocalFile()) { 0212 if (!downloadToTemp(url1, tmp1)) { 0213 return; 0214 } 0215 } else 0216 tmp1 = url1.path(); 0217 if (!url2.isLocalFile()) { 0218 if (!downloadToTemp(url2, tmp2)) { 0219 if (tmp1 != url1.path()) { 0220 QFile::remove(tmp1); 0221 } 0222 return; 0223 } 0224 } else 0225 tmp2 = url2.path(); 0226 } 0227 0228 KrProcess *p = new KrProcess(tmp1 != url1.path() ? tmp1 : QString(), tmp2 != url2.path() ? tmp2 : QString()); 0229 *p << diffProg << tmp1 << tmp2; 0230 p->start(); 0231 if (!p->waitForStarted()) { 0232 KMessageBox::error(nullptr, i18n("Error executing %1.", diffProg)); 0233 } 0234 } 0235 0236 // GUI toggle slots 0237 void KrSlots::toggleFnkeys() 0238 { 0239 if (MAIN_VIEW->fnKeys()->isVisible()) 0240 MAIN_VIEW->fnKeys()->hide(); 0241 else 0242 MAIN_VIEW->fnKeys()->show(); 0243 } 0244 0245 void KrSlots::toggleCmdline() 0246 { 0247 if (MAIN_VIEW->cmdLine()->isVisible()) 0248 MAIN_VIEW->cmdLine()->hide(); 0249 else 0250 MAIN_VIEW->cmdLine()->show(); 0251 } 0252 0253 void KrSlots::updateStatusbarVisibility() 0254 { 0255 krApp->statusBar()->setVisible(KrActions::actShowStatusBar->isChecked()); 0256 } 0257 0258 void KrSlots::toggleTerminal() 0259 { 0260 MAIN_VIEW->setTerminalEmulator(KrActions::actToggleTerminal->isChecked()); 0261 } 0262 0263 void KrSlots::insertFileName(bool fullPath) 0264 { 0265 QString filename = ACTIVE_VIEW->getCurrentItem(); 0266 if (filename.isEmpty()) { 0267 return; 0268 } 0269 0270 if (fullPath) { 0271 const QString path = FileSystem::ensureTrailingSlash(ACTIVE_PANEL->virtualPath()).toDisplayString(QUrl::PreferLocalFile); 0272 filename = path + filename; 0273 } 0274 0275 filename = KrServices::quote(filename); 0276 0277 if (MAIN_VIEW->cmdLine()->isVisible() || !MAIN_VIEW->terminalDock()->isTerminalVisible()) { 0278 QString current = MAIN_VIEW->cmdLine()->text(); 0279 if (current.length() != 0 && !current.endsWith(' ')) 0280 current += ' '; 0281 MAIN_VIEW->cmdLine()->setText(current + filename); 0282 MAIN_VIEW->cmdLine()->setFocus(); 0283 } else if (MAIN_VIEW->terminalDock()->isTerminalVisible()) { 0284 filename = ' ' + filename + ' '; 0285 MAIN_VIEW->terminalDock()->sendInput(filename, false); 0286 MAIN_VIEW->terminalDock()->setFocus(); 0287 } 0288 } 0289 0290 void KrSlots::refresh(const QUrl &u) 0291 { 0292 ACTIVE_FUNC->openUrl(u); 0293 } 0294 0295 void KrSlots::runKonfigurator(bool firstTime) 0296 { 0297 auto *konfigurator = new Konfigurator(firstTime); 0298 connect(konfigurator, &Konfigurator::configChanged, this, &KrSlots::configChanged); 0299 0300 // FIXME - no need to exec 0301 konfigurator->exec(); 0302 0303 delete konfigurator; 0304 } 0305 0306 void KrSlots::configChanged(bool isGUIRestartNeeded) 0307 { 0308 krConfig->sync(); 0309 0310 if (isGUIRestartNeeded) { 0311 krApp->setUpdatesEnabled(false); 0312 KConfigGroup group(krConfig, "Look&Feel"); 0313 FileItem::loadUserDefinedFolderIcons(group.readEntry("Load User Defined Folder Icons", _UserDefinedFolderIcons)); 0314 0315 bool leftActive = ACTIVE_PANEL->gui->isLeft(); 0316 MAIN_VIEW->leftManager()->slotRecreatePanels(); 0317 MAIN_VIEW->rightManager()->slotRecreatePanels(); 0318 if (leftActive) 0319 LEFT_PANEL->slotFocusOnMe(); 0320 else 0321 RIGHT_PANEL->slotFocusOnMe(); 0322 MAIN_VIEW->fnKeys()->updateShortcuts(); 0323 KrSelectionMode::resetSelectionHandler(); 0324 krApp->setUpdatesEnabled(true); 0325 } 0326 0327 krApp->setTray(); 0328 0329 // really ugly, but reload the Fn keys just in case - csaba: any better idea? 0330 MAIN_VIEW->fnKeys()->updateShortcuts(); 0331 0332 const bool showHidden = KConfigGroup(krConfig, "Look&Feel").readEntry("Show Hidden", KrActions::actToggleHidden->isChecked()); 0333 0334 if (showHidden != KrActions::actToggleHidden->isChecked()) { 0335 KrActions::actToggleHidden->setChecked(showHidden); 0336 MAIN_VIEW->leftManager()->reloadConfig(); 0337 MAIN_VIEW->rightManager()->reloadConfig(); 0338 } 0339 } 0340 0341 void KrSlots::showHiddenFiles(bool show) 0342 { 0343 KConfigGroup group(krConfig, "Look&Feel"); 0344 group.writeEntry("Show Hidden", show); 0345 0346 MAIN_VIEW->leftManager()->reloadConfig(); 0347 MAIN_VIEW->rightManager()->reloadConfig(); 0348 } 0349 0350 void KrSlots::swapPanels() 0351 { 0352 QUrl leftURL = LEFT_PANEL->virtualPath(); 0353 QUrl rightURL = RIGHT_PANEL->virtualPath(); 0354 0355 LEFT_PANEL->func->openUrl(rightURL); 0356 RIGHT_PANEL->func->openUrl(leftURL); 0357 } 0358 0359 void KrSlots::toggleSwapSides() 0360 { 0361 MAIN_VIEW->swapSides(); 0362 } 0363 0364 void KrSlots::search() 0365 { 0366 if (KrSearchDialog::SearchDialog != nullptr) { 0367 KConfigGroup group(krConfig, "Search"); 0368 if (group.readEntry("Window Maximized", false)) 0369 KrSearchDialog::SearchDialog->showMaximized(); 0370 else 0371 KrSearchDialog::SearchDialog->showNormal(); 0372 0373 KrSearchDialog::SearchDialog->raise(); 0374 KrSearchDialog::SearchDialog->activateWindow(); 0375 } else 0376 KrSearchDialog::SearchDialog = new KrSearchDialog(); 0377 } 0378 0379 void KrSlots::locate() 0380 { 0381 if (!KrServices::cmdExist("locate")) { 0382 KMessageBox::error(krApp, 0383 i18n("Cannot find the 'locate' command. Please install the " 0384 "findutils-locate package of GNU, or set its dependencies in " 0385 "Konfigurator")); 0386 return; 0387 } 0388 0389 if (LocateDlg::LocateDialog != nullptr) { 0390 LocateDlg::LocateDialog->showNormal(); 0391 LocateDlg::LocateDialog->raise(); 0392 LocateDlg::LocateDialog->activateWindow(); 0393 LocateDlg::LocateDialog->reset(); 0394 } else 0395 LocateDlg::LocateDialog = new LocateDlg(krApp); 0396 } 0397 0398 void KrSlots::runTerminal(const QString &dir) 0399 { 0400 KProcess proc; 0401 proc.setWorkingDirectory(dir); 0402 KConfigGroup group(krConfig, "General"); 0403 QString term = group.readEntry("Terminal", _Terminal); 0404 QStringList sepdArgs = KShell::splitArgs(term, KShell::TildeExpand); 0405 if (sepdArgs.isEmpty()) { 0406 KMessageBox::error(krMainWindow, i18nc("Arg is a string containing the bad quoting.", "Bad quoting in terminal command:\n%1", term)); 0407 return; 0408 } 0409 for (int i = 0; i < sepdArgs.size(); i++) { 0410 if (sepdArgs[i] == "%d") { 0411 sepdArgs[i] = dir; 0412 } 0413 } 0414 proc << sepdArgs; 0415 if (!proc.startDetached()) 0416 KMessageBox::error(krApp, i18n("Error executing %1.", term)); 0417 } 0418 0419 void KrSlots::homeTerminal() 0420 { 0421 runTerminal(QDir::homePath()); 0422 } 0423 0424 void KrSlots::multiRename() 0425 { 0426 QStringList lst = KrServices::supportedTools(); 0427 int i = lst.indexOf("RENAME"); 0428 if (i == -1) { 0429 KMessageBox::error( 0430 krApp, 0431 i18n("Cannot find a batch rename tool.\nYou can get KRename at %1", QLatin1String("https://www.kde.org/applications/utilities/krename/"))); 0432 return; 0433 } 0434 QString pathToRename = lst[i + 1]; 0435 0436 const QStringList names = ACTIVE_PANEL->gui->getSelectedNames(); 0437 if (names.isEmpty()) { 0438 return; 0439 } 0440 0441 KProcess proc; 0442 proc << pathToRename; 0443 0444 for (const QString &name : names) { 0445 FileItem *file = ACTIVE_FUNC->files()->getFileItem(name); 0446 if (!file) 0447 continue; 0448 const QUrl url = file->getUrl(); 0449 // KRename only supports the recursive option combined with a local directory path 0450 if (file->isDir() && url.scheme() == "file") { 0451 proc << "-r" << url.path(); 0452 } else { 0453 proc << url.toString(); 0454 } 0455 } 0456 0457 if (!proc.startDetached()) 0458 KMessageBox::error(nullptr, i18n("Error executing '%1'.", proc.program().join(" "))); 0459 } 0460 0461 void KrSlots::rootKrusader() 0462 { 0463 if (KMessageBox::warningContinueCancel(krApp, 0464 i18n("Improper operations in root mode can damage your operating system. " 0465 "<p>Furthermore, running UI applications as root is insecure and can " 0466 "allow attackers to gain root access."), 0467 QString(), 0468 KStandardGuiItem::cont(), 0469 KStandardGuiItem::cancel(), 0470 "Confirm Root Mode", 0471 KMessageBox::Notify | KMessageBox::Dangerous) 0472 != KMessageBox::Continue) 0473 return; 0474 0475 if (!KrServices::isExecutable(KDESU_PATH)) { 0476 KMessageBox::error(krApp, 0477 i18n("Cannot start root mode Krusader, %1 not found or not executable. " 0478 "Please verify that kde-cli-tools are installed.", 0479 QString(KDESU_PATH))); 0480 return; 0481 } 0482 0483 KProcess proc; 0484 proc << KDESU_PATH << "-c" 0485 << QApplication::instance()->applicationFilePath() + " --left=" + KrServices::quote(LEFT_PANEL->virtualPath().toDisplayString(QUrl::PreferLocalFile)) 0486 + " --right=" + KrServices::quote(RIGHT_PANEL->virtualPath().toDisplayString(QUrl::PreferLocalFile)); 0487 0488 if (!proc.startDetached()) 0489 KMessageBox::error(nullptr, i18n("Error executing %1.", proc.program()[0])); 0490 } 0491 0492 void KrSlots::slotSplit() 0493 { 0494 const QStringList list = ACTIVE_PANEL->gui->getSelectedNames(); 0495 QString name; 0496 0497 // first, see if we've got exactly 1 selected file, if not, try the current one 0498 if (list.count() == 1) 0499 name = list[0]; 0500 0501 if (name.isEmpty()) { 0502 // if we got here, then one of the panel can't be sure what file to diff 0503 KMessageBox::error(nullptr, i18n("Do not know which file to split.")); 0504 return; 0505 } 0506 0507 QUrl fileURL = ACTIVE_FUNC->files()->getUrl(name); 0508 if (fileURL.isEmpty()) 0509 return; 0510 0511 if (ACTIVE_FUNC->files()->getFileItem(name)->isDir()) { 0512 KMessageBox::error(krApp, i18n("You cannot split a folder.")); 0513 return; 0514 } 0515 0516 const QUrl destDir = ACTIVE_PANEL->otherPanel()->virtualPath(); 0517 0518 SplitterGUI splitterGUI(MAIN_VIEW, fileURL, destDir); 0519 0520 if (splitterGUI.exec() == QDialog::Accepted) { 0521 bool splitToOtherPanel = splitterGUI.getDestinationDir().matches(ACTIVE_PANEL->otherPanel()->virtualPath(), QUrl::StripTrailingSlash); 0522 0523 Splitter split(MAIN_VIEW, fileURL, splitterGUI.getDestinationDir(), splitterGUI.overWriteFiles()); 0524 split.split(splitterGUI.getSplitSize()); 0525 0526 if (splitToOtherPanel) 0527 ACTIVE_PANEL->otherPanel()->func->refresh(); 0528 } 0529 } 0530 0531 void KrSlots::slotCombine() 0532 { 0533 const QStringList list = ACTIVE_PANEL->gui->getSelectedNames(); 0534 if (list.isEmpty()) { 0535 KMessageBox::error(nullptr, i18n("Do not know which files to combine.")); 0536 return; 0537 } 0538 0539 QUrl baseURL; 0540 bool unixStyle = false; 0541 bool windowsStyle = false; 0542 QString commonName; 0543 int commonLength = 0; 0544 0545 /* checking splitter names */ 0546 for (const auto &it : list) { 0547 QUrl url = ACTIVE_FUNC->files()->getUrl(it); 0548 if (url.isEmpty()) 0549 return; 0550 0551 if (ACTIVE_FUNC->files()->getFileItem(it)->isDir()) { 0552 KMessageBox::error(krApp, i18n("You cannot combine a folder.")); 0553 return; 0554 } 0555 0556 if (!unixStyle) { 0557 QString name = url.fileName(); 0558 int extPos = name.lastIndexOf('.'); 0559 QString ext = name.mid(extPos + 1); 0560 name.truncate(extPos); 0561 url = url.adjusted(QUrl::RemoveFilename); 0562 url.setPath(url.path() + name); 0563 0564 bool isExtInt; 0565 ext.toInt(&isExtInt, 10); 0566 0567 if (extPos < 1 || ext.isEmpty() || (ext != "crc" && !isExtInt)) { 0568 if (windowsStyle) { 0569 KMessageBox::error(nullptr, i18n("Not a split file: %1.", url.toDisplayString(QUrl::PreferLocalFile))); 0570 return; 0571 } 0572 unixStyle = true; 0573 } else { 0574 if (ext != "crc") 0575 windowsStyle = true; 0576 0577 if (baseURL.isEmpty()) 0578 baseURL = url; 0579 else if (baseURL != url) { 0580 KMessageBox::error(nullptr, i18n("Select only one split file.")); 0581 return; 0582 } 0583 } 0584 } 0585 0586 if (unixStyle) { 0587 bool error = true; 0588 0589 do { 0590 const QString &shortName = it; 0591 QChar lastChar = shortName.at(shortName.length() - 1); 0592 0593 if (lastChar.isLetter()) { 0594 char fillLetter = (lastChar.toUpper() == lastChar) ? 'A' : 'a'; 0595 0596 if (commonName.isNull()) { 0597 commonLength = shortName.length(); 0598 commonName = shortName; 0599 0600 while (commonName.length()) { 0601 QString shorter = commonName.left(commonName.length() - 1); 0602 QString testFile = shorter.leftJustified(commonLength, fillLetter); 0603 0604 if (ACTIVE_FUNC->files()->getFileItem(testFile) == nullptr) 0605 break; 0606 else { 0607 commonName = shorter; 0608 baseURL = ACTIVE_PANEL->virtualPath().adjusted(QUrl::StripTrailingSlash); 0609 baseURL.setPath(baseURL.path() + '/' + (testFile)); 0610 } 0611 } 0612 0613 error = (commonName == shortName); 0614 } else if (commonLength == shortName.length() && shortName.startsWith(commonName)) 0615 error = false; 0616 } 0617 } while (false); 0618 0619 if (error) { 0620 KMessageBox::error(nullptr, i18n("Not a split file: %1.", url.toDisplayString(QUrl::PreferLocalFile))); 0621 return; 0622 } 0623 } 0624 } 0625 0626 // ask the user for the copy dest 0627 QUrl dest = KChooseDir::getDir(i18n("Combining %1.* to folder:", baseURL.toDisplayString(QUrl::PreferLocalFile)), 0628 ACTIVE_PANEL->otherPanel()->virtualPath(), 0629 ACTIVE_PANEL->virtualPath()); 0630 if (dest.isEmpty()) 0631 return; // the user canceled 0632 0633 bool combineToOtherPanel = (dest.matches(ACTIVE_PANEL->otherPanel()->virtualPath(), QUrl::StripTrailingSlash)); 0634 0635 Combiner combine(MAIN_VIEW, baseURL, dest, unixStyle); 0636 combine.combine(); 0637 0638 if (combineToOtherPanel) 0639 ACTIVE_PANEL->otherPanel()->func->refresh(); 0640 } 0641 0642 void KrSlots::manageUseractions() 0643 { 0644 ActionMan actionMan(MAIN_VIEW); 0645 } 0646 0647 #ifdef SYNCHRONIZER_ENABLED 0648 void KrSlots::slotSynchronizeDirs(QStringList selected) 0649 { 0650 SynchronizerGUI *synchronizerDialog = new SynchronizerGUI(MAIN_VIEW, LEFT_PANEL->virtualPath(), RIGHT_PANEL->virtualPath(), std::move(selected)); 0651 synchronizerDialog->show(); // destroyed on close 0652 } 0653 #endif 0654 0655 void KrSlots::compareSetup() 0656 { 0657 for (int i = 0; KrActions::compareArray[i] != nullptr; i++) 0658 if ((*KrActions::compareArray[i])->isChecked()) { 0659 KConfigGroup group(krConfig, "Private"); 0660 group.writeEntry("Compare Mode", i); 0661 break; 0662 } 0663 } 0664 0665 /** called by actions actExec* to choose the built-in command line mode */ 0666 void KrSlots::execTypeSetup() 0667 { 0668 for (int i = 0; KrActions::execTypeArray[i] != nullptr; i++) 0669 if ((*KrActions::execTypeArray[i])->isChecked()) { 0670 if (*KrActions::execTypeArray[i] == KrActions::actExecTerminalEmbedded) { 0671 // if commands are to be executed in the TE, it must be loaded 0672 MAIN_VIEW->terminalDock()->initialise(); 0673 } 0674 KConfigGroup grp(krConfig, "Private"); 0675 grp.writeEntry("Command Execution Mode", i); 0676 break; 0677 } 0678 } 0679 0680 void KrSlots::slotDiskUsage() 0681 { 0682 DiskUsageGUI *diskUsageDialog = new DiskUsageGUI(ACTIVE_PANEL->virtualPath()); 0683 diskUsageDialog->askDirAndShow(); 0684 } 0685 0686 void KrSlots::applicationStateChanged() 0687 { 0688 if (MAIN_VIEW == nullptr) { /* CRASH FIX: it's possible that the method is called after destroying the main view */ 0689 return; 0690 } 0691 if (qApp->applicationState() == Qt::ApplicationActive || qApp->applicationState() == Qt::ApplicationInactive) { 0692 LEFT_PANEL->panelVisible(); 0693 RIGHT_PANEL->panelVisible(); 0694 } else { 0695 LEFT_PANEL->panelHidden(); 0696 RIGHT_PANEL->panelHidden(); 0697 } 0698 } 0699 0700 void KrSlots::emptyTrash() 0701 { 0702 KrTrashHandler::emptyTrash(); 0703 } 0704 0705 #define OPEN_ID 100001 0706 #define EMPTY_TRASH_ID 100002 0707 0708 void KrSlots::trashPopupMenu() 0709 { 0710 QMenu trashMenu(krApp); 0711 QAction *act = trashMenu.addAction(Icon("document-open"), i18n("Open trash bin")); 0712 act->setData(QVariant(OPEN_ID)); 0713 act = trashMenu.addAction(Icon("trash-empty"), i18n("Empty trash bin")); 0714 act->setData(QVariant(EMPTY_TRASH_ID)); 0715 0716 int result = -1; 0717 QAction *res = trashMenu.exec(QCursor::pos()); 0718 if (res && res->data().canConvert<int>()) 0719 result = res->data().toInt(); 0720 0721 if (result == OPEN_ID) { 0722 ACTIVE_FUNC->openUrl(QUrl(QStringLiteral("trash:/"))); 0723 } else if (result == EMPTY_TRASH_ID) { 0724 KrTrashHandler::emptyTrash(); 0725 } 0726 } 0727 0728 void KrSlots::addBookmark() 0729 { 0730 krBookMan->bookmarkCurrent(ACTIVE_PANEL->virtualPath()); 0731 } 0732 0733 void KrSlots::cmdlinePopup() 0734 { 0735 MAIN_VIEW->cmdLine()->popup(); 0736 }