File indexing completed on 2024-05-05 05:57:00

0001 /*
0002   SPDX-FileCopyrightText: 2008-2014 Eike Hein <hein@kde.org>
0003   SPDX-FileCopyrightText: 2009 Juan Carlos Torres <carlosdgtorres@gmail.com>
0004 
0005   SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006 */
0007 
0008 #include "sessionstack.h"
0009 #include "settings.h"
0010 #include "terminal.h"
0011 #include "visualeventoverlay.h"
0012 
0013 #include <KLocalizedString>
0014 #include <KMessageBox>
0015 #include <KNotification>
0016 
0017 #include <QDBusConnection>
0018 
0019 #include <algorithm>
0020 
0021 static bool show_disallow_certain_dbus_methods_message = true;
0022 
0023 SessionStack::SessionStack(QWidget *parent)
0024     : QStackedWidget(parent)
0025 {
0026     QDBusConnection::sessionBus().registerObject(QStringLiteral("/yakuake/sessions"), this, QDBusConnection::ExportScriptableSlots);
0027 
0028     m_activeSessionId = -1;
0029 
0030     m_visualEventOverlay = new VisualEventOverlay(this);
0031     connect(this, SIGNAL(removeTerminalHighlight()), m_visualEventOverlay, SLOT(removeTerminalHighlight()));
0032 }
0033 
0034 SessionStack::~SessionStack()
0035 {
0036 }
0037 
0038 int SessionStack::addSessionImpl(Session::SessionType type)
0039 {
0040     Session *currentSession = m_sessions.value(activeSessionId());
0041     Terminal *currentTerminal = currentSession ? currentSession->getTerminal(currentSession->activeTerminalId()) : nullptr;
0042     QString workingDir = currentTerminal ? currentTerminal->currentWorkingDirectory() : QString();
0043 
0044     Session *session = new Session(workingDir, type, this);
0045     // clang-format off
0046     connect(session, SIGNAL(titleChanged(int,QString)), this, SIGNAL(titleChanged(int,QString)));
0047     connect(session, SIGNAL(terminalManuallyActivated(Terminal*)), this, SLOT(handleManualTerminalActivation(Terminal*)));
0048     connect(session, SIGNAL(keyboardInputBlocked(Terminal*)), m_visualEventOverlay, SLOT(indicateKeyboardInputBlocked(Terminal*)));
0049     connect(session, SIGNAL(activityDetected(Terminal*)), parentWidget(), SLOT(handleTerminalActivity(Terminal*)));
0050     connect(session, SIGNAL(silenceDetected(Terminal*)), parentWidget(), SLOT(handleTerminalSilence(Terminal*)));
0051     connect(parentWidget(), SIGNAL(windowClosed()), session, SLOT(reconnectMonitorActivitySignals()));
0052     // clang-format on
0053     connect(session, SIGNAL(destroyed(int)), this, SLOT(cleanup(int)));
0054     connect(session, &Session::wantsBlurChanged, this, &SessionStack::wantsBlurChanged);
0055 
0056     addWidget(session->widget());
0057 
0058     m_sessions.insert(session->id(), session);
0059 
0060     Q_EMIT wantsBlurChanged();
0061 
0062     if (Settings::dynamicTabTitles())
0063         Q_EMIT sessionAdded(session->id(), session->title());
0064     else
0065         Q_EMIT sessionAdded(session->id(), QString());
0066 
0067     return session->id();
0068 }
0069 
0070 int SessionStack::addSession()
0071 {
0072     return addSessionImpl(Session::Single);
0073 }
0074 
0075 int SessionStack::addSessionTwoHorizontal()
0076 {
0077     return addSessionImpl(Session::TwoHorizontal);
0078 }
0079 
0080 int SessionStack::addSessionTwoVertical()
0081 {
0082     return addSessionImpl(Session::TwoVertical);
0083 }
0084 
0085 int SessionStack::addSessionQuad()
0086 {
0087     return addSessionImpl(Session::Quad);
0088 }
0089 
0090 void SessionStack::raiseSession(int sessionId)
0091 {
0092     if (sessionId == -1 || !m_sessions.contains(sessionId))
0093         return;
0094     Session *session = m_sessions.value(sessionId);
0095 
0096     if (!m_visualEventOverlay->isHidden())
0097         m_visualEventOverlay->hide();
0098 
0099     if (m_activeSessionId != -1 && m_sessions.contains(m_activeSessionId)) {
0100         Session *oldActiveSession = m_sessions.value(m_activeSessionId);
0101 
0102         disconnect(oldActiveSession, SLOT(closeTerminal()));
0103         disconnect(oldActiveSession, SLOT(focusPreviousTerminal()));
0104         disconnect(oldActiveSession, SLOT(focusNextTerminal()));
0105         disconnect(oldActiveSession, SLOT(manageProfiles()));
0106         disconnect(oldActiveSession, SIGNAL(titleChanged(QString)), this, SIGNAL(activeTitleChanged(QString)));
0107 
0108         oldActiveSession->reconnectMonitorActivitySignals();
0109     }
0110 
0111     m_activeSessionId = sessionId;
0112 
0113     setCurrentWidget(session->widget());
0114 
0115     if (session->widget()->focusWidget())
0116         session->widget()->focusWidget()->setFocus();
0117 
0118     if (session->hasTerminalsWithKeyboardInputDisabled())
0119         m_visualEventOverlay->show();
0120 
0121     connect(this, SIGNAL(closeTerminal()), session, SLOT(closeTerminal()));
0122     connect(this, SIGNAL(previousTerminal()), session, SLOT(focusPreviousTerminal()));
0123     connect(this, SIGNAL(nextTerminal()), session, SLOT(focusNextTerminal()));
0124     connect(this, SIGNAL(manageProfiles()), session, SLOT(manageProfiles()));
0125     connect(session, SIGNAL(titleChanged(QString)), this, SIGNAL(activeTitleChanged(QString)));
0126 
0127     Q_EMIT sessionRaised(sessionId);
0128 
0129     Q_EMIT activeTitleChanged(session->title());
0130 }
0131 
0132 void SessionStack::removeSession(int sessionId)
0133 {
0134     if (sessionId == -1)
0135         sessionId = m_activeSessionId;
0136     if (sessionId == -1)
0137         return;
0138     if (!m_sessions.contains(sessionId))
0139         return;
0140 
0141     if (queryClose(sessionId, QueryCloseSession))
0142         m_sessions.value(sessionId)->deleteLater();
0143 }
0144 
0145 void SessionStack::removeTerminal(int terminalId)
0146 {
0147     int sessionId = sessionIdForTerminalId(terminalId);
0148 
0149     if (terminalId == -1) {
0150         if (m_activeSessionId == -1)
0151             return;
0152         if (!m_sessions.contains(m_activeSessionId))
0153             return;
0154 
0155         if (m_sessions.value(m_activeSessionId)->closable())
0156             m_sessions.value(m_activeSessionId)->closeTerminal();
0157     } else {
0158         if (m_sessions.value(sessionId)->closable())
0159             m_sessions.value(sessionId)->closeTerminal(terminalId);
0160     }
0161 }
0162 
0163 void SessionStack::closeActiveTerminal(int sessionId)
0164 {
0165     if (sessionId == -1)
0166         sessionId = m_activeSessionId;
0167     if (sessionId == -1)
0168         return;
0169     if (!m_sessions.contains(sessionId))
0170         return;
0171 
0172     if (queryClose(sessionId, QueryCloseTerminal))
0173         m_sessions.value(sessionId)->closeTerminal();
0174 }
0175 
0176 void SessionStack::cleanup(int sessionId)
0177 {
0178     if (sessionId == m_activeSessionId)
0179         m_activeSessionId = -1;
0180 
0181     m_sessions.remove(sessionId);
0182 
0183     Q_EMIT wantsBlurChanged();
0184     Q_EMIT sessionRemoved(sessionId);
0185 }
0186 
0187 int SessionStack::activeTerminalId()
0188 {
0189     if (!m_sessions.contains(m_activeSessionId))
0190         return -1;
0191 
0192     return m_sessions.value(m_activeSessionId)->activeTerminalId();
0193 }
0194 
0195 const QString SessionStack::sessionIdList()
0196 {
0197     QList<int> keyList = m_sessions.keys();
0198     QStringList idList;
0199 
0200     QListIterator<int> i(keyList);
0201 
0202     while (i.hasNext())
0203         idList << QString::number(i.next());
0204 
0205     return idList.join(QLatin1Char(','));
0206 }
0207 
0208 const QString SessionStack::terminalIdList()
0209 {
0210     QStringList idList;
0211 
0212     QHashIterator<int, Session *> it(m_sessions);
0213 
0214     while (it.hasNext()) {
0215         it.next();
0216 
0217         idList << it.value()->terminalIdList();
0218     }
0219 
0220     return idList.join(QLatin1Char(','));
0221 }
0222 
0223 const QString SessionStack::terminalIdsForSessionId(int sessionId)
0224 {
0225     if (!m_sessions.contains(sessionId))
0226         return QString::number(-1);
0227 
0228     return m_sessions.value(sessionId)->terminalIdList();
0229 }
0230 
0231 int SessionStack::sessionIdForTerminalId(int terminalId)
0232 {
0233     int sessionId = -1;
0234 
0235     QHashIterator<int, Session *> it(m_sessions);
0236 
0237     while (it.hasNext()) {
0238         it.next();
0239 
0240         if (it.value()->hasTerminal(terminalId)) {
0241             sessionId = it.key();
0242 
0243             break;
0244         }
0245     }
0246 
0247     return sessionId;
0248 }
0249 
0250 static void warnAboutDBus()
0251 {
0252 #if !defined(REMOVE_SENDTEXT_RUNCOMMAND_DBUS_METHODS)
0253     if (show_disallow_certain_dbus_methods_message) {
0254         KNotification::event(
0255             KNotification::Warning,
0256             QStringLiteral("Yakuake D-Bus Warning"),
0257             i18n("The D-Bus method runCommand was just used.  There are security concerns about allowing these methods to be public.  If desired, these "
0258                  "methods can be changed to internal use only by re-compiling Yakuake. <p>This warning will only show once for this Yakuake instance.</p>"));
0259         show_disallow_certain_dbus_methods_message = false;
0260     }
0261 #endif
0262 }
0263 
0264 void SessionStack::runCommand(const QString &command)
0265 {
0266     warnAboutDBus();
0267 
0268     if (m_activeSessionId == -1)
0269         return;
0270     if (!m_sessions.contains(m_activeSessionId))
0271         return;
0272 
0273     m_sessions.value(m_activeSessionId)->runCommand(command);
0274 }
0275 
0276 void SessionStack::runCommandInTerminal(int terminalId, const QString &command)
0277 {
0278     warnAboutDBus();
0279 
0280     QHashIterator<int, Session *> it(m_sessions);
0281 
0282     while (it.hasNext()) {
0283         it.next();
0284 
0285         it.value()->runCommand(command, terminalId);
0286     }
0287 }
0288 
0289 bool SessionStack::isSessionClosable(int sessionId)
0290 {
0291     if (sessionId == -1)
0292         sessionId = m_activeSessionId;
0293     if (sessionId == -1)
0294         return false;
0295     if (!m_sessions.contains(sessionId))
0296         return false;
0297 
0298     return m_sessions.value(sessionId)->closable();
0299 }
0300 
0301 void SessionStack::setSessionClosable(int sessionId, bool closable)
0302 {
0303     if (sessionId == -1)
0304         sessionId = m_activeSessionId;
0305     if (sessionId == -1)
0306         return;
0307     if (!m_sessions.contains(sessionId))
0308         return;
0309 
0310     m_sessions.value(sessionId)->setClosable(closable);
0311 }
0312 
0313 bool SessionStack::hasUnclosableSessions() const
0314 {
0315     QHashIterator<int, Session *> it(m_sessions);
0316 
0317     while (it.hasNext()) {
0318         it.next();
0319 
0320         if (!it.value()->closable())
0321             return true;
0322     }
0323 
0324     return false;
0325 }
0326 
0327 bool SessionStack::isSessionKeyboardInputEnabled(int sessionId)
0328 {
0329     if (sessionId == -1)
0330         sessionId = m_activeSessionId;
0331     if (sessionId == -1)
0332         return false;
0333     if (!m_sessions.contains(sessionId))
0334         return false;
0335 
0336     return m_sessions.value(sessionId)->keyboardInputEnabled();
0337 }
0338 
0339 void SessionStack::setSessionKeyboardInputEnabled(int sessionId, bool enabled)
0340 {
0341     if (sessionId == -1)
0342         sessionId = m_activeSessionId;
0343     if (sessionId == -1)
0344         return;
0345     if (!m_sessions.contains(sessionId))
0346         return;
0347 
0348     m_sessions.value(sessionId)->setKeyboardInputEnabled(enabled);
0349 
0350     if (sessionId == m_activeSessionId) {
0351         if (enabled)
0352             m_visualEventOverlay->hide();
0353         else
0354             m_visualEventOverlay->show();
0355     }
0356 }
0357 
0358 bool SessionStack::isTerminalKeyboardInputEnabled(int terminalId)
0359 {
0360     int sessionId = sessionIdForTerminalId(terminalId);
0361     if (sessionId == -1)
0362         return false;
0363     if (!m_sessions.contains(sessionId))
0364         return false;
0365 
0366     return m_sessions.value(sessionId)->keyboardInputEnabled(terminalId);
0367 }
0368 
0369 void SessionStack::setTerminalKeyboardInputEnabled(int terminalId, bool enabled)
0370 {
0371     int sessionId = sessionIdForTerminalId(terminalId);
0372     if (sessionId == -1)
0373         return;
0374     if (!m_sessions.contains(sessionId))
0375         return;
0376 
0377     m_sessions.value(sessionId)->setKeyboardInputEnabled(terminalId, enabled);
0378 
0379     if (sessionId == m_activeSessionId) {
0380         if (enabled)
0381             m_visualEventOverlay->hide();
0382         else
0383             m_visualEventOverlay->show();
0384     }
0385 }
0386 
0387 bool SessionStack::hasTerminalsWithKeyboardInputEnabled(int sessionId)
0388 {
0389     if (sessionId == -1)
0390         sessionId = m_activeSessionId;
0391     if (sessionId == -1)
0392         return false;
0393     if (!m_sessions.contains(sessionId))
0394         return false;
0395 
0396     return m_sessions.value(sessionId)->hasTerminalsWithKeyboardInputEnabled();
0397 }
0398 
0399 bool SessionStack::hasTerminalsWithKeyboardInputDisabled(int sessionId)
0400 {
0401     if (sessionId == -1)
0402         sessionId = m_activeSessionId;
0403     if (sessionId == -1)
0404         return false;
0405     if (!m_sessions.contains(sessionId))
0406         return false;
0407 
0408     return m_sessions.value(sessionId)->hasTerminalsWithKeyboardInputDisabled();
0409 }
0410 
0411 bool SessionStack::isSessionMonitorActivityEnabled(int sessionId)
0412 {
0413     if (sessionId == -1)
0414         sessionId = m_activeSessionId;
0415     if (sessionId == -1)
0416         return false;
0417     if (!m_sessions.contains(sessionId))
0418         return false;
0419 
0420     return m_sessions.value(sessionId)->monitorActivityEnabled();
0421 }
0422 
0423 void SessionStack::setSessionMonitorActivityEnabled(int sessionId, bool enabled)
0424 {
0425     if (sessionId == -1)
0426         sessionId = m_activeSessionId;
0427     if (sessionId == -1)
0428         return;
0429     if (!m_sessions.contains(sessionId))
0430         return;
0431 
0432     m_sessions.value(sessionId)->setMonitorActivityEnabled(enabled);
0433 }
0434 
0435 bool SessionStack::isTerminalMonitorActivityEnabled(int terminalId)
0436 {
0437     int sessionId = sessionIdForTerminalId(terminalId);
0438     if (sessionId == -1)
0439         return false;
0440     if (!m_sessions.contains(sessionId))
0441         return false;
0442 
0443     return m_sessions.value(sessionId)->monitorActivityEnabled(terminalId);
0444 }
0445 
0446 void SessionStack::setTerminalMonitorActivityEnabled(int terminalId, bool enabled)
0447 {
0448     int sessionId = sessionIdForTerminalId(terminalId);
0449     if (sessionId == -1)
0450         return;
0451     if (!m_sessions.contains(sessionId))
0452         return;
0453 
0454     m_sessions.value(sessionId)->setMonitorActivityEnabled(terminalId, enabled);
0455 }
0456 
0457 bool SessionStack::hasTerminalsWithMonitorActivityEnabled(int sessionId)
0458 {
0459     if (sessionId == -1)
0460         sessionId = m_activeSessionId;
0461     if (sessionId == -1)
0462         return false;
0463     if (!m_sessions.contains(sessionId))
0464         return false;
0465 
0466     return m_sessions.value(sessionId)->hasTerminalsWithMonitorActivityEnabled();
0467 }
0468 
0469 bool SessionStack::hasTerminalsWithMonitorActivityDisabled(int sessionId)
0470 {
0471     if (sessionId == -1)
0472         sessionId = m_activeSessionId;
0473     if (sessionId == -1)
0474         return false;
0475     if (!m_sessions.contains(sessionId))
0476         return false;
0477 
0478     return m_sessions.value(sessionId)->hasTerminalsWithMonitorActivityDisabled();
0479 }
0480 
0481 bool SessionStack::isSessionMonitorSilenceEnabled(int sessionId)
0482 {
0483     if (sessionId == -1)
0484         sessionId = m_activeSessionId;
0485     if (sessionId == -1)
0486         return false;
0487     if (!m_sessions.contains(sessionId))
0488         return false;
0489 
0490     return m_sessions.value(sessionId)->monitorSilenceEnabled();
0491 }
0492 
0493 void SessionStack::setSessionMonitorSilenceEnabled(int sessionId, bool enabled)
0494 {
0495     if (sessionId == -1)
0496         sessionId = m_activeSessionId;
0497     if (sessionId == -1)
0498         return;
0499     if (!m_sessions.contains(sessionId))
0500         return;
0501 
0502     m_sessions.value(sessionId)->setMonitorSilenceEnabled(enabled);
0503 }
0504 
0505 bool SessionStack::isTerminalMonitorSilenceEnabled(int terminalId)
0506 {
0507     int sessionId = sessionIdForTerminalId(terminalId);
0508     if (sessionId == -1)
0509         return false;
0510     if (!m_sessions.contains(sessionId))
0511         return false;
0512 
0513     return m_sessions.value(sessionId)->monitorSilenceEnabled(terminalId);
0514 }
0515 
0516 void SessionStack::setTerminalMonitorSilenceEnabled(int terminalId, bool enabled)
0517 {
0518     int sessionId = sessionIdForTerminalId(terminalId);
0519     if (sessionId == -1)
0520         return;
0521     if (!m_sessions.contains(sessionId))
0522         return;
0523 
0524     m_sessions.value(sessionId)->setMonitorSilenceEnabled(terminalId, enabled);
0525 }
0526 
0527 bool SessionStack::hasTerminalsWithMonitorSilenceEnabled(int sessionId)
0528 {
0529     if (sessionId == -1)
0530         sessionId = m_activeSessionId;
0531     if (sessionId == -1)
0532         return false;
0533     if (!m_sessions.contains(sessionId))
0534         return false;
0535 
0536     return m_sessions.value(sessionId)->hasTerminalsWithMonitorSilenceEnabled();
0537 }
0538 
0539 bool SessionStack::hasTerminalsWithMonitorSilenceDisabled(int sessionId)
0540 {
0541     if (sessionId == -1)
0542         sessionId = m_activeSessionId;
0543     if (sessionId == -1)
0544         return false;
0545     if (!m_sessions.contains(sessionId))
0546         return false;
0547 
0548     return m_sessions.value(sessionId)->hasTerminalsWithMonitorSilenceDisabled();
0549 }
0550 
0551 void SessionStack::editProfile(int sessionId)
0552 {
0553     if (sessionId == -1)
0554         sessionId = m_activeSessionId;
0555     if (sessionId == -1)
0556         return;
0557     if (!m_sessions.contains(sessionId))
0558         return;
0559 
0560     m_sessions.value(sessionId)->editProfile();
0561 }
0562 
0563 int SessionStack::splitSessionLeftRight(int sessionId)
0564 {
0565     if (sessionId == -1)
0566         return -1;
0567     if (!m_sessions.contains(sessionId))
0568         return -1;
0569 
0570     return m_sessions.value(sessionId)->splitLeftRight();
0571 }
0572 
0573 int SessionStack::splitSessionTopBottom(int sessionId)
0574 {
0575     if (sessionId == -1)
0576         return -1;
0577     if (!m_sessions.contains(sessionId))
0578         return -1;
0579 
0580     return m_sessions.value(sessionId)->splitTopBottom();
0581 }
0582 
0583 int SessionStack::splitTerminalLeftRight(int terminalId)
0584 {
0585     int sessionId = sessionIdForTerminalId(terminalId);
0586 
0587     if (sessionId == -1)
0588         return -1;
0589 
0590     return m_sessions.value(sessionId)->splitLeftRight(terminalId);
0591 }
0592 
0593 int SessionStack::splitTerminalTopBottom(int terminalId)
0594 {
0595     int sessionId = sessionIdForTerminalId(terminalId);
0596 
0597     if (sessionId == -1)
0598         return -1;
0599 
0600     return m_sessions.value(sessionId)->splitTopBottom(terminalId);
0601 }
0602 
0603 int SessionStack::tryGrowTerminalRight(int terminalId, uint pixels)
0604 {
0605     int sessionId = sessionIdForTerminalId(terminalId);
0606 
0607     if (sessionId == -1)
0608         return -1;
0609 
0610     return m_sessions.value(sessionId)->tryGrowTerminal(terminalId, Session::Right, pixels);
0611 }
0612 
0613 int SessionStack::tryGrowTerminalLeft(int terminalId, uint pixels)
0614 {
0615     int sessionId = sessionIdForTerminalId(terminalId);
0616 
0617     if (sessionId == -1)
0618         return -1;
0619 
0620     return m_sessions.value(sessionId)->tryGrowTerminal(terminalId, Session::Left, pixels);
0621 }
0622 
0623 int SessionStack::tryGrowTerminalTop(int terminalId, uint pixels)
0624 {
0625     int sessionId = sessionIdForTerminalId(terminalId);
0626 
0627     if (sessionId == -1)
0628         return -1;
0629 
0630     return m_sessions.value(sessionId)->tryGrowTerminal(terminalId, Session::Up, pixels);
0631 }
0632 
0633 int SessionStack::tryGrowTerminalBottom(int terminalId, uint pixels)
0634 {
0635     int sessionId = sessionIdForTerminalId(terminalId);
0636 
0637     if (sessionId == -1)
0638         return -1;
0639 
0640     return m_sessions.value(sessionId)->tryGrowTerminal(terminalId, Session::Down, pixels);
0641 }
0642 
0643 void SessionStack::emitTitles()
0644 {
0645     QString title;
0646 
0647     QHashIterator<int, Session *> it(m_sessions);
0648 
0649     while (it.hasNext()) {
0650         it.next();
0651 
0652         title = it.value()->title();
0653 
0654         if (!title.isEmpty())
0655             Q_EMIT titleChanged(it.value()->id(), title);
0656     }
0657 }
0658 
0659 bool SessionStack::requiresVisualEventOverlay()
0660 {
0661     if (m_activeSessionId == -1)
0662         return false;
0663     if (!m_sessions.contains(m_activeSessionId))
0664         return false;
0665 
0666     return m_sessions.value(m_activeSessionId)->hasTerminalsWithKeyboardInputDisabled();
0667 }
0668 
0669 void SessionStack::handleTerminalHighlightRequest(int terminalId)
0670 {
0671     Terminal *terminal = nullptr;
0672 
0673     QHashIterator<int, Session *> it(m_sessions);
0674 
0675     while (it.hasNext()) {
0676         it.next();
0677 
0678         terminal = it.value()->getTerminal(terminalId);
0679 
0680         if (terminal && it.value()->id() == m_activeSessionId) {
0681             m_visualEventOverlay->highlightTerminal(terminal, true);
0682 
0683             break;
0684         }
0685     }
0686 }
0687 
0688 void SessionStack::showEvent(QShowEvent *event)
0689 {
0690     Q_UNUSED(event)
0691 
0692     if (m_activeSessionId == -1)
0693         return;
0694     if (!m_sessions.contains(m_activeSessionId))
0695         return;
0696 
0697     Terminal *terminal = m_sessions.value(m_activeSessionId)->getTerminal(activeTerminalId());
0698 
0699     if (terminal) {
0700         QWidget *terminalWidget = terminal->terminalWidget();
0701         if (terminalWidget)
0702             terminalWidget->setFocus();
0703     }
0704 }
0705 
0706 void SessionStack::handleManualTerminalActivation(Terminal *terminal)
0707 {
0708     if (!Settings::terminalHighlightOnManualActivation())
0709         return;
0710 
0711     Session *session = qobject_cast<Session *>(QObject::sender());
0712 
0713     if (session->terminalCount() > 1)
0714         m_visualEventOverlay->highlightTerminal(terminal, false);
0715 }
0716 
0717 bool SessionStack::queryClose(int sessionId, QueryCloseType type)
0718 {
0719     if (!m_sessions.contains(sessionId))
0720         return false;
0721 
0722     if (!m_sessions.value(sessionId)->closable()) {
0723         QString closeQuestionIntro = xi18nc("@info", "<warning>You have locked this session to prevent accidental closing of terminals.</warning>");
0724         QString closeQuestion;
0725 
0726         if (type == QueryCloseSession)
0727             closeQuestion = xi18nc("@info", "Are you sure you want to close this session?");
0728         else if (type == QueryCloseTerminal)
0729             closeQuestion = xi18nc("@info", "Are you sure you want to close this terminal?");
0730 
0731         int result = KMessageBox::warningContinueCancel(this,
0732                                                         closeQuestionIntro + QStringLiteral("<br/><br/>") + closeQuestion,
0733                                                         xi18nc("@title:window", "Really Close?"),
0734                                                         KStandardGuiItem::close(),
0735                                                         KStandardGuiItem::cancel());
0736 
0737         if (result != KMessageBox::Continue)
0738             return false;
0739     }
0740 
0741     return true;
0742 }
0743 
0744 QList<KActionCollection *> SessionStack::getPartActionCollections()
0745 {
0746     QList<KActionCollection *> actionCollections;
0747 
0748     const auto sessions = m_sessions.values();
0749     for (auto *session : sessions) {
0750         const auto terminalIds = session->terminalIdList().split(QStringLiteral(","));
0751 
0752         for (const auto &terminalID : terminalIds) {
0753             auto *terminal = session->getTerminal(terminalID.toInt());
0754             if (terminal) {
0755                 auto *collection = terminal->actionCollection();
0756                 if (collection) {
0757                     actionCollections.append(collection);
0758                 }
0759             }
0760         }
0761     }
0762 
0763     return actionCollections;
0764 }
0765 
0766 bool SessionStack::wantsBlur() const
0767 {
0768     return std::any_of(m_sessions.cbegin(), m_sessions.cend(), [](Session *session) {
0769         return session->wantsBlur();
0770     });
0771 }
0772 
0773 #include "moc_sessionstack.cpp"