File indexing completed on 2024-05-12 05:52:08
0001 /* 0002 0003 SPDX-FileCopyrightText: 2005 Christoph Cullmann <cullmann@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "katesessionmanagedialog.h" 0009 0010 #include "kateapp.h" 0011 #include "katesessionchooseritem.h" 0012 #include "katesessionmanager.h" 0013 0014 #include <KColorScheme> 0015 #include <KConfigGroup> 0016 #include <KLocalizedString> 0017 #include <KSharedConfig> 0018 #include <KStandardGuiItem> 0019 0020 #include <QKeyEvent> 0021 #include <QTimer> 0022 0023 KateSessionManageDialog::KateSessionManageDialog(QWidget *parent) 0024 : QDialog(parent) 0025 { 0026 setupUi(this); 0027 setWindowTitle(i18n("Manage Sessions")); 0028 m_dontAskCheckBox->hide(); 0029 0030 m_sessionList->installEventFilter(this); 0031 connect(m_sessionList, &QTreeWidget::currentItemChanged, this, &KateSessionManageDialog::selectionChanged); 0032 connect(m_sessionList, &QTreeWidget::itemDoubleClicked, this, &KateSessionManageDialog::openSession); 0033 m_sessionList->header()->moveSection(0, 1); // Re-order columns to "Files, Sessions" 0034 0035 m_filterBox->installEventFilter(this); 0036 connect(m_filterBox, &QLineEdit::textChanged, this, &KateSessionManageDialog::filterChanged); 0037 0038 connect(m_newButton, &QPushButton::clicked, this, &KateSessionManageDialog::openNewSession); 0039 0040 KGuiItem::assign(m_openButton, KStandardGuiItem::open()); 0041 m_openButton->setDefault(true); 0042 connect(m_openButton, &QPushButton::clicked, this, &KateSessionManageDialog::openSession); 0043 0044 connect(m_templateButton, &QPushButton::clicked, this, &KateSessionManageDialog::openSessionAsTemplate); 0045 0046 connect(m_copyButton, &QPushButton::clicked, this, &KateSessionManageDialog::copySession); 0047 0048 connect(m_renameButton, &QPushButton::clicked, this, &KateSessionManageDialog::editBegin); 0049 0050 connect(m_deleteButton, &QPushButton::clicked, this, &KateSessionManageDialog::updateDeleteList); 0051 0052 KGuiItem::assign(m_closeButton, KStandardGuiItem::close()); 0053 connect(m_closeButton, &QPushButton::clicked, this, &KateSessionManageDialog::closeDialog); 0054 0055 connect(KateApp::self()->sessionManager(), &KateSessionManager::sessionListChanged, this, &KateSessionManageDialog::updateSessionList); 0056 0057 updateSessionList(); 0058 } 0059 0060 KateSessionManageDialog::KateSessionManageDialog(QWidget *parent, const QString &lastSession) 0061 : KateSessionManageDialog(parent) 0062 { 0063 setWindowTitle(i18n("Session Chooser")); 0064 m_dontAskCheckBox->show(); 0065 m_chooserMode = true; 0066 connect(m_dontAskCheckBox, &QCheckBox::toggled, this, &KateSessionManageDialog::dontAskToggled); 0067 0068 m_preferredSession = lastSession; 0069 updateSessionList(); 0070 } 0071 0072 void KateSessionManageDialog::dontAskToggled() 0073 { 0074 m_templateButton->setEnabled(!m_dontAskCheckBox->isChecked()); 0075 } 0076 0077 void KateSessionManageDialog::filterChanged() 0078 { 0079 static QPointer<QTimer> delay; 0080 0081 if (!delay) { 0082 delay = new QTimer(this); // Should be auto cleard by Qt when we die 0083 delay->setSingleShot(true); 0084 delay->setInterval(400); 0085 connect(delay, &QTimer::timeout, this, &KateSessionManageDialog::updateSessionList); 0086 } 0087 0088 delay->start(); 0089 } 0090 0091 void KateSessionManageDialog::done(int result) 0092 { 0093 for (const auto &session : qAsConst(m_deleteList)) { 0094 KateApp::self()->sessionManager()->deleteSession(session); 0095 KateApp::self()->stashManager()->clearStashForSession(session); 0096 } 0097 m_deleteList.clear(); // May not needed, but anyway 0098 0099 if (ResultQuit == result) { 0100 QDialog::done(0); 0101 return; 0102 } 0103 0104 if (m_chooserMode && m_dontAskCheckBox->isChecked()) { 0105 // write back our nice boolean :) 0106 KConfigGroup generalConfig(KSharedConfig::openConfig(), QStringLiteral("General")); 0107 switch (result) { 0108 case ResultOpen: 0109 generalConfig.writeEntry("Startup Session", "last"); 0110 break; 0111 case ResultNew: 0112 generalConfig.writeEntry("Startup Session", "new"); 0113 break; 0114 default: 0115 break; 0116 } 0117 generalConfig.sync(); 0118 } 0119 0120 QDialog::done(1); 0121 } 0122 0123 void KateSessionManageDialog::selectionChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) 0124 { 0125 Q_UNUSED(previous); 0126 0127 if (m_editByUser) { 0128 editDone(); // Field was left unchanged, no need to apply 0129 return; 0130 } 0131 0132 if (!current) { 0133 m_openButton->setEnabled(false); 0134 m_templateButton->setEnabled(false); 0135 m_copyButton->setEnabled(false); 0136 m_renameButton->setEnabled(false); 0137 m_deleteButton->setEnabled(false); 0138 return; 0139 } 0140 0141 const KateSession::Ptr activeSession = KateApp::self()->sessionManager()->activeSession(); 0142 const bool notActiveSession = !KateApp::self()->sessionManager()->sessionIsActive(currentSelectedSession()->name()); 0143 0144 m_deleteButton->setEnabled(notActiveSession); 0145 0146 if (m_deleteList.contains(currentSelectedSession())) { 0147 m_deleteButton->setText(i18n("Restore")); 0148 m_openButton->setEnabled(false); 0149 m_templateButton->setEnabled(false); 0150 m_copyButton->setEnabled(true); // Looks a little strange but is OK 0151 m_renameButton->setEnabled(false); 0152 } else { 0153 KGuiItem::assign(m_deleteButton, KStandardGuiItem::del()); 0154 m_openButton->setEnabled(currentSelectedSession() != activeSession); 0155 m_templateButton->setEnabled(true); 0156 m_copyButton->setEnabled(true); 0157 m_renameButton->setEnabled(true); 0158 } 0159 } 0160 0161 void KateSessionManageDialog::disableButtons() 0162 { 0163 m_openButton->setEnabled(false); 0164 m_newButton->setEnabled(false); 0165 m_templateButton->setEnabled(false); 0166 m_dontAskCheckBox->setEnabled(false); 0167 m_copyButton->setEnabled(false); 0168 m_renameButton->setEnabled(false); 0169 m_deleteButton->setEnabled(false); 0170 m_closeButton->setEnabled(false); 0171 m_filterBox->setEnabled(false); 0172 } 0173 0174 void KateSessionManageDialog::editBegin() 0175 { 0176 if (m_editByUser) { 0177 return; 0178 } 0179 0180 KateSessionChooserItem *item = currentSessionItem(); 0181 0182 if (!item) { 0183 return; 0184 } 0185 0186 disableButtons(); 0187 0188 item->setFlags(item->flags() | Qt::ItemIsEditable); 0189 m_sessionList->clearSelection(); 0190 m_sessionList->editItem(item, 0); 0191 0192 // Always apply changes user did, like Dolphin 0193 connect(m_sessionList, &QTreeWidget::itemChanged, this, &KateSessionManageDialog::editApply); 0194 connect(m_sessionList->itemWidget(item, 0), &QObject::destroyed, this, &KateSessionManageDialog::editApply); 0195 0196 m_editByUser = item; // Do it last to block eventFilter() actions until we are ready 0197 } 0198 0199 void KateSessionManageDialog::editDone() 0200 { 0201 m_editByUser = nullptr; 0202 disconnect(m_sessionList, &QTreeWidget::itemChanged, this, &KateSessionManageDialog::editApply); 0203 0204 // avoid crash, see bug 142127 0205 QTimer::singleShot(0, this, &KateSessionManageDialog::updateSessionList); 0206 m_sessionList->setFocus(); 0207 0208 m_newButton->setEnabled(true); 0209 m_dontAskCheckBox->setEnabled(true); 0210 m_closeButton->setEnabled(true); 0211 m_filterBox->setEnabled(true); 0212 } 0213 0214 void KateSessionManageDialog::editApply() 0215 { 0216 if (!m_editByUser) { 0217 return; 0218 } 0219 0220 KateApp::self()->sessionManager()->renameSession(m_editByUser->session, m_editByUser->text(0)); 0221 editDone(); 0222 } 0223 0224 void KateSessionManageDialog::copySession() 0225 { 0226 KateSessionChooserItem *item = currentSessionItem(); 0227 0228 if (!item) { 0229 return; 0230 } 0231 0232 m_preferredSession = KateApp::self()->sessionManager()->copySession(item->session); 0233 m_sessionList->setFocus(); // Only needed when user abort 0234 } 0235 0236 void KateSessionManageDialog::openSession() 0237 { 0238 KateSessionChooserItem *item = currentSessionItem(); 0239 0240 if (!item) { 0241 return; 0242 } 0243 0244 hide(); 0245 0246 // this might fail, e.g. if session is in use, then e.g. end kate, bug 390740 0247 const bool success = KateApp::self()->sessionManager()->activateSession(item->session); 0248 done(success ? ResultOpen : ResultQuit); 0249 } 0250 0251 void KateSessionManageDialog::openSessionAsTemplate() 0252 { 0253 KateSessionChooserItem *item = currentSessionItem(); 0254 0255 if (!item) { 0256 return; 0257 } 0258 0259 hide(); 0260 0261 KateSessionManager *sm = KateApp::self()->sessionManager(); 0262 KateSession::Ptr ns = KateSession::createAnonymousFrom(item->session, sm->anonymousSessionFile()); 0263 sm->activateSession(ns); 0264 0265 done(ResultOpen); 0266 } 0267 0268 void KateSessionManageDialog::openNewSession() 0269 { 0270 hide(); 0271 KateApp::self()->sessionManager()->sessionNew(); 0272 done(ResultNew); 0273 } 0274 0275 void KateSessionManageDialog::updateDeleteList() 0276 { 0277 KateSessionChooserItem *item = currentSessionItem(); 0278 0279 if (!item) { 0280 return; 0281 } 0282 0283 const KateSession::Ptr session = item->session; 0284 if (m_deleteList.contains(session)) { 0285 m_deleteList.remove(session); 0286 item->setForeground(0, QBrush(KColorScheme(QPalette::Active).foreground(KColorScheme::NormalText).color())); 0287 item->setIcon(0, QIcon()); 0288 item->setToolTip(0, QString()); 0289 } else { 0290 m_deleteList.insert(session); 0291 markItemAsToBeDeleted(item); 0292 } 0293 0294 // To ease multiple deletions, move the selection 0295 QTreeWidgetItem *newItem = m_sessionList->itemBelow(item) ? m_sessionList->itemBelow(item) : m_sessionList->topLevelItem(0); 0296 m_sessionList->setCurrentItem(newItem); 0297 m_sessionList->setFocus(); 0298 } 0299 0300 void KateSessionManageDialog::markItemAsToBeDeleted(QTreeWidgetItem *item) 0301 { 0302 item->setForeground(0, QBrush(KColorScheme(QPalette::Active).foreground(KColorScheme::InactiveText).color())); 0303 item->setIcon(0, QIcon::fromTheme(QStringLiteral("emblem-warning"))); 0304 item->setToolTip(0, i18n("Session will be deleted on dialog close")); 0305 } 0306 0307 void KateSessionManageDialog::closeDialog() 0308 { 0309 done(ResultQuit); 0310 } 0311 0312 void KateSessionManageDialog::updateSessionList() 0313 { 0314 if (m_editByUser) { 0315 // Don't crash accidentally an ongoing edit 0316 return; 0317 } 0318 0319 KateSession::Ptr currSelSession = currentSelectedSession(); 0320 KateSession::Ptr activeSession = KateApp::self()->sessionManager()->activeSession(); 0321 0322 m_sessionList->clear(); 0323 0324 KateSessionList slist = KateApp::self()->sessionManager()->sessionList(); 0325 0326 KateSessionChooserItem *preferredItem = nullptr; 0327 KateSessionChooserItem *currSessionItem = nullptr; 0328 KateSessionChooserItem *activeSessionItem = nullptr; 0329 0330 KConfigGroup generalConfig(KSharedConfig::openConfig(), QStringLiteral("General")); 0331 int col = generalConfig.readEntry("Session Manager Sort Column", 0); 0332 int order = generalConfig.readEntry("Session Manager Sort Order", (int)Qt::AscendingOrder); 0333 if (size_t(col) > 2) { 0334 col = 0; 0335 } 0336 if (order != Qt::AscendingOrder && order != Qt::DescendingOrder) { 0337 order = Qt::AscendingOrder; 0338 } 0339 0340 for (const KateSession::Ptr &session : qAsConst(slist)) { 0341 if (!m_filterBox->text().isEmpty()) { 0342 if (!session->name().contains(m_filterBox->text(), Qt::CaseInsensitive)) { 0343 continue; 0344 } 0345 } 0346 0347 KateSessionChooserItem *item = new KateSessionChooserItem(m_sessionList, session); 0348 if (session == currSelSession) { 0349 currSessionItem = item; 0350 } else if (session == activeSession) { 0351 activeSessionItem = item; 0352 } else if (session->name() == m_preferredSession) { 0353 preferredItem = item; 0354 m_preferredSession.clear(); 0355 } 0356 0357 if (m_deleteList.contains(session)) { 0358 markItemAsToBeDeleted(item); 0359 } 0360 } 0361 0362 connect(m_sessionList->header(), &QHeaderView::sortIndicatorChanged, this, [](int logIdx, Qt::SortOrder order) { 0363 KConfigGroup generalConfig(KSharedConfig::openConfig(), QStringLiteral("General")); 0364 generalConfig.writeEntry("Session Manager Sort Column", logIdx); 0365 generalConfig.writeEntry("Session Manager Sort Order", (int)order); 0366 }); 0367 0368 m_sessionList->header()->setStretchLastSection(false); 0369 m_sessionList->header()->setSectionResizeMode(0, QHeaderView::Stretch); // stretch "Session Name" column 0370 m_sessionList->resizeColumnToContents(1); // Fit "Files" column 0371 m_sessionList->resizeColumnToContents(2); // Fit "Last update" column 0372 m_sessionList->sortByColumn(col, Qt::SortOrder(order)); // sort by "Session Name" column.. don't worry, it only sorts when the model data changes. 0373 0374 if (!preferredItem) { 0375 preferredItem = currSessionItem ? currSessionItem : activeSessionItem; 0376 } 0377 0378 if (preferredItem) { 0379 m_sessionList->setCurrentItem(preferredItem); 0380 m_sessionList->scrollToItem(preferredItem); 0381 } else if (m_sessionList->topLevelItemCount() > 0) { 0382 m_sessionList->setCurrentItem(m_sessionList->topLevelItem(0)); 0383 } 0384 0385 if (m_filterBox->hasFocus()) { 0386 return; 0387 } 0388 0389 if (m_sessionList->topLevelItemCount() == 0) { 0390 m_openButton->setEnabled(false); 0391 m_templateButton->setEnabled(false); 0392 m_dontAskCheckBox->setEnabled(false); 0393 m_copyButton->setEnabled(false); 0394 m_renameButton->setEnabled(false); 0395 m_deleteButton->setEnabled(false); 0396 m_filterBox->setEnabled(false); 0397 0398 m_newButton->setFocus(); 0399 } else { 0400 m_sessionList->setFocus(); 0401 } 0402 } 0403 0404 KateSessionChooserItem *KateSessionManageDialog::currentSessionItem() const 0405 { 0406 return static_cast<KateSessionChooserItem *>(m_sessionList->currentItem()); 0407 } 0408 0409 KateSession::Ptr KateSessionManageDialog::currentSelectedSession() const 0410 { 0411 KateSessionChooserItem *item = currentSessionItem(); 0412 0413 if (!item) { 0414 return KateSession::Ptr(); 0415 } 0416 0417 return item->session; 0418 } 0419 0420 bool KateSessionManageDialog::eventFilter(QObject *object, QEvent *event) 0421 { 0422 if (object == m_sessionList) { 0423 if (!m_editByUser) { // No need for further action 0424 return false; 0425 } 0426 if (event->type() == QEvent::KeyPress) { 0427 QKeyEvent *ke = static_cast<QKeyEvent *>(event); 0428 switch (ke->key()) { 0429 // Avoid to apply changes with untypical keys/don't left edit field this way 0430 case Qt::Key_Up: 0431 case Qt::Key_Down: 0432 case Qt::Key_PageUp: 0433 case Qt::Key_PageDown: 0434 return true; 0435 default: 0436 break; 0437 } 0438 0439 } else if (event->type() == QEvent::KeyRelease) { 0440 QKeyEvent *ke = static_cast<QKeyEvent *>(event); 0441 switch (ke->key()) { 0442 case Qt::Key_Escape: 0443 editDone(); // Abort edit 0444 break; 0445 case Qt::Key_Return: 0446 editApply(); 0447 break; 0448 default: 0449 break; 0450 } 0451 } 0452 0453 } else if (object == m_filterBox && event->type() == QEvent::KeyPress) { 0454 QKeyEvent *ke = static_cast<QKeyEvent *>(event); 0455 // Catch Return key to avoid to finish the dialog 0456 if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter) { 0457 // avoid crash, see bug 142127 0458 QTimer::singleShot(0, this, &KateSessionManageDialog::updateSessionList); 0459 m_sessionList->setFocus(); 0460 return true; 0461 } 0462 } 0463 0464 return false; 0465 } 0466 0467 void KateSessionManageDialog::closeEvent(QCloseEvent *event) 0468 { 0469 Q_UNUSED(event); 0470 0471 if (m_editByUser) { 0472 // We must catch closeEvent here due to connected signal of QLineEdit::destroyed->editApply()->crash! 0473 editDone(); // editApply() don't work, m_editByUser->text(0) will not updated from QLineEdit 0474 } 0475 } 0476 0477 #include "moc_katesessionmanagedialog.cpp"