File indexing completed on 2024-04-28 04:37:24
0001 /* 0002 SPDX-FileCopyrightText: 2008 Andreas Pakulat <apaku@gmx.de> 0003 SPDX-FileCopyrightText: 2010 David Nolden <david.nolden.kdevelop@art-master.de> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "sessionchooserdialog.h" 0009 #include "sessioncontroller.h" 0010 #include "core.h" 0011 0012 #include <QDialogButtonBox> 0013 #include <QKeyEvent> 0014 #include <QLineEdit> 0015 #include <QListView> 0016 #include <QPushButton> 0017 #include <QVBoxLayout> 0018 0019 #include <KLocalizedString> 0020 #include <KMessageBox> 0021 #include <KMessageBox_KDevCompat> 0022 0023 using namespace KDevelop; 0024 0025 SessionChooserDialog::SessionChooserDialog(QListView* view, QAbstractItemModel* model, QLineEdit* filter) 0026 : m_view(view), m_model(model), m_filter(filter), m_deleteCandidateRow(-1) 0027 { 0028 m_updateStateTimer.setInterval(5000); 0029 m_updateStateTimer.setSingleShot(false); 0030 m_updateStateTimer.start(); 0031 connect(&m_updateStateTimer, &QTimer::timeout, this, &SessionChooserDialog::updateState); 0032 connect(view, &QListView::doubleClicked, this, &SessionChooserDialog::doubleClicked); 0033 connect(view, &QListView::entered, this, &SessionChooserDialog::itemEntered); 0034 0035 m_deleteButton = new QPushButton(view->viewport()); 0036 m_deleteButton->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete"))); 0037 m_deleteButton->setToolTip(i18nc("@info:tooltip", "Delete session")); 0038 m_deleteButton->hide(); 0039 connect(m_deleteButton, &QPushButton::clicked, this, &SessionChooserDialog::deleteButtonPressed); 0040 0041 m_deleteButtonTimer.setInterval(500); 0042 m_deleteButtonTimer.setSingleShot(true); 0043 connect(&m_deleteButtonTimer, &QTimer::timeout, this, &SessionChooserDialog::showDeleteButton); 0044 0045 view->setMouseTracking(true); 0046 view->installEventFilter(this); 0047 filter->installEventFilter(this); 0048 connect(filter, &QLineEdit::textChanged, this, &SessionChooserDialog::filterTextChanged); 0049 0050 setWindowTitle(i18nc("@title:window", "Pick a Session")); 0051 0052 m_buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Close); 0053 auto mainLayout = new QVBoxLayout(this); 0054 m_mainWidget = new QWidget(this); 0055 mainLayout->addWidget(m_mainWidget); 0056 0057 QPushButton *okButton = m_buttonBox->button(QDialogButtonBox::Ok); 0058 okButton->setDefault(true); 0059 okButton->setShortcut(Qt::Key_Return); 0060 connect(m_buttonBox, &QDialogButtonBox::accepted, this, &SessionChooserDialog::accept); 0061 connect(m_buttonBox, &QDialogButtonBox::rejected, this, &SessionChooserDialog::reject); 0062 mainLayout->addWidget(m_buttonBox); 0063 okButton->setText(i18nc("@action:button", "Run")); 0064 okButton->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start"))); 0065 } 0066 0067 void SessionChooserDialog::filterTextChanged() 0068 { 0069 m_view->selectionModel()->setCurrentIndex(m_model->index(0, 0), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); 0070 bool enabled = m_view->model()->rowCount(QModelIndex())>0; 0071 m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(enabled); 0072 m_deleteButton->setVisible(false); 0073 } 0074 0075 void SessionChooserDialog::doubleClicked(const QModelIndex& index) 0076 { 0077 if(m_model->flags(index) & Qt::ItemIsEnabled) 0078 accept(); 0079 } 0080 0081 void SessionChooserDialog::updateState() { 0082 // Sometimes locking may take some time, so we stop the timer, to prevent an 'avalanche' of events 0083 m_updateStateTimer.stop(); 0084 for(int row = 0; row < m_model->rowCount(); ++row) 0085 { 0086 QString session = m_model->index(row, 0).data().toString(); 0087 0088 if(session.isEmpty()) //create new session 0089 continue; 0090 0091 QString state, tooltip; 0092 SessionRunInfo info = SessionController::sessionRunInfo(session); 0093 if(info.isRunning) 0094 { 0095 tooltip = i18nc("@info:tooltip", "Active session.\npid %1, app %2, host %3", 0096 info.holderPid, info.holderApp, info.holderHostname); 0097 state = i18n("Running"); 0098 } 0099 0100 m_model->setData(m_model->index(row, 1), 0101 !info.isRunning ? QIcon() : QIcon::fromTheme(QStringLiteral("media-playback-start")), 0102 Qt::DecorationRole); 0103 m_model->setData(m_model->index(row, 1), tooltip, Qt::ToolTipRole); 0104 m_model->setData(m_model->index(row, 2), state, Qt::DisplayRole); 0105 } 0106 0107 m_updateStateTimer.start(); 0108 } 0109 0110 void SessionChooserDialog::itemEntered(const QModelIndex& index) 0111 { 0112 // The last row says "Create new session", we don't want to delete that 0113 if(index.row() == m_model->rowCount()-1) { 0114 m_deleteButton->hide(); 0115 m_deleteButtonTimer.stop(); 0116 return; 0117 } 0118 0119 // align the delete-button to stay on the right border of the item 0120 // we need the right most column's index 0121 QModelIndex in = m_model->index( index.row(), 1 ); 0122 const QRect rect = m_view->visualRect(in); 0123 m_deleteButton->resize(rect.height(), rect.height()); 0124 0125 QPoint p(rect.right() - m_deleteButton->size().width(), rect.top()+rect.height()/2-m_deleteButton->height()/2); 0126 m_deleteButton->move(p); 0127 0128 m_deleteCandidateRow = index.row(); 0129 m_deleteButtonTimer.start(); 0130 } 0131 0132 void SessionChooserDialog::showDeleteButton() 0133 { 0134 m_deleteButton->show(); 0135 } 0136 0137 bool SessionChooserDialog::eventFilter(QObject* object, QEvent* event) 0138 { 0139 if(object == m_view && event->type() == QEvent::Leave ) { 0140 m_deleteButtonTimer.stop(); 0141 m_deleteButton->hide(); 0142 // don't eat the event, pass on 0143 } else if (object == m_filter && event->type() == QEvent::KeyPress) { 0144 auto *keyEvent = static_cast<QKeyEvent*>(event); 0145 if (keyEvent->key() == Qt::Key_Return) { 0146 accept(); 0147 // don't eat the event, pass on 0148 } else if (keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down) { 0149 QModelIndex currentIndex = m_view->selectionModel()->currentIndex(); 0150 int selectRow = -1; 0151 if (keyEvent->key() == Qt::Key_Up) { 0152 if(!currentIndex.isValid()) { 0153 selectRow = m_model->rowCount()-1; 0154 } else if(currentIndex.row()-1 >= 0) { 0155 selectRow = currentIndex.row()-1; 0156 } 0157 } else { 0158 if(!currentIndex.isValid()) { 0159 selectRow = 0; 0160 } else if(currentIndex.row()+1 < m_model->rowCount()) { 0161 selectRow = currentIndex.row()+1; 0162 } 0163 } 0164 0165 if (selectRow != -1) { 0166 m_view->selectionModel()->setCurrentIndex(m_model->index(selectRow, 0), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); 0167 } 0168 return true; // eat event 0169 } 0170 } 0171 0172 return QDialog::eventFilter(object, event); 0173 } 0174 0175 QWidget* SessionChooserDialog::mainWidget() const 0176 { 0177 return m_mainWidget; 0178 } 0179 0180 void SessionChooserDialog::deleteButtonPressed() 0181 { 0182 if(m_deleteCandidateRow == -1) 0183 return; 0184 0185 QModelIndex uuidIndex = m_model->index(m_deleteCandidateRow, 0); 0186 QModelIndex sessionNameIndex = m_model->index(m_deleteCandidateRow, 3); 0187 const QString uuid = m_model->data(uuidIndex, Qt::DisplayRole).toString(); 0188 const QString sessionName = m_model->data(sessionNameIndex, Qt::DisplayRole).toString(); 0189 0190 TryLockSessionResult result = SessionController::tryLockSession( uuid ); 0191 if( !result.lock ) { 0192 const QString errCaption = i18nc("@title:window", "Cannot Delete Session"); 0193 QString errText = i18nc("@info", "<p>Cannot delete a locked session."); 0194 0195 if( result.runInfo.holderPid != -1 ) { 0196 errText += i18nc("@info", "<p>The session <b>%1</b> is locked by %2 on %3 (PID %4).", 0197 sessionName, result.runInfo.holderApp, result.runInfo.holderHostname, result.runInfo.holderPid); 0198 } 0199 0200 KMessageBox::error( this, errText, errCaption ); 0201 return; 0202 } 0203 0204 const QString text = i18nc("@info", "The session <b>%1</b> and all contained settings will be deleted. The projects will stay unaffected. Do you really want to continue?", sessionName); 0205 const QString caption = i18nc("@title:window", "Delete Session"); 0206 const KGuiItem deleteItem = KStandardGuiItem::del(); 0207 const KGuiItem cancelItem = KStandardGuiItem::cancel(); 0208 0209 if (KMessageBox::warningTwoActions(this, text, caption, deleteItem, cancelItem) == KMessageBox::PrimaryAction) { 0210 SessionController::deleteSessionFromDisk(result.lock); 0211 0212 m_model->removeRows( m_deleteCandidateRow, 1 ); 0213 m_deleteCandidateRow = -1; 0214 } 0215 } 0216 0217 #include "moc_sessionchooserdialog.cpp"