File indexing completed on 2024-05-05 05:44:49
0001 /*************************************************************************** 0002 * Copyright (C) 2005-2009 by Rajko Albrecht * 0003 * ral@alwins-world.de * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program; if not, write to the * 0017 * Free Software Foundation, Inc., * 0018 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 0019 ***************************************************************************/ 0020 #include "commitmsg_impl.h" 0021 #include "depthselector.h" 0022 #include "ksvnwidgets/ksvndialog.h" 0023 #include "models/commitmodel.h" 0024 #include "models/commitmodelhelper.h" 0025 #include "settings/kdesvnsettings.h" 0026 0027 #include <KConfig> 0028 #include <KFile> 0029 #include <KIO/FileCopyJob> 0030 #include <KJobWidgets> 0031 #include <KLocalizedString> 0032 #include <KMessageBox> 0033 #include <KUrlRequester> 0034 #include <KUrlRequesterDialog> 0035 0036 #include <QFile> 0037 #include <QStringList> 0038 #include <QTemporaryFile> 0039 0040 #define MAX_MESSAGE_HISTORY 10 0041 0042 QStringList Commitmsg_impl::sLogHistory = QStringList(); 0043 QString Commitmsg_impl::sLastMessage; 0044 0045 int Commitmsg_impl::smax_message_history = 0xFFFF; 0046 0047 Commitmsg_impl::Commitmsg_impl(QWidget *parent) 0048 : QWidget(parent) 0049 , CommitMessage() 0050 { 0051 setupUi(this); 0052 m_CurrentModel = nullptr; 0053 m_SortModel = nullptr; 0054 m_LogEdit->setFocus(); 0055 m_Reviewlabel->hide(); 0056 m_hidden = true; 0057 hideButtons(true); 0058 m_MainSplitter->insertWidget(0, m_EditFrame); 0059 delete m_ReviewFrame; 0060 m_Reviewlabel = nullptr; 0061 m_MarkUnversioned = nullptr; 0062 m_UnmarkUnversioned = nullptr; 0063 m_DiffItem = nullptr; 0064 } 0065 0066 Commitmsg_impl::Commitmsg_impl(const svn::CommitItemList &_items, QWidget *parent) 0067 : QWidget(parent) 0068 , CommitMessage() 0069 { 0070 setupUi(this); 0071 m_CurrentModel = nullptr; 0072 m_SortModel = nullptr; 0073 m_LogEdit->setFocus(); 0074 hideButtons(true); 0075 if (!_items.isEmpty()) { 0076 m_CurrentModel = new CommitModel(_items); 0077 setupModel(); 0078 m_hidden = false; 0079 } else { 0080 m_Reviewlabel->hide(); 0081 m_CommitItemTree->hide(); 0082 m_hidden = true; 0083 } 0084 checkSplitterSize(); 0085 } 0086 0087 Commitmsg_impl::Commitmsg_impl(const CommitActionEntries &_activatedList, const CommitActionEntries &_notActivatedList, QWidget *parent) 0088 : QWidget(parent) 0089 , CommitMessage() 0090 { 0091 setupUi(this); 0092 m_CurrentModel = nullptr; 0093 m_SortModel = nullptr; 0094 m_LogEdit->setFocus(); 0095 m_hidden = false; 0096 0097 m_CurrentModel = new CommitModelCheckitem(_activatedList, _notActivatedList); 0098 setupModel(); 0099 0100 m_HideNewItems->setChecked(Kdesvnsettings::commit_hide_new()); 0101 checkSplitterSize(); 0102 } 0103 0104 Commitmsg_impl::~Commitmsg_impl() 0105 { 0106 QList<int> list = m_MainSplitter->sizes(); 0107 if (!m_hidden && list.count() == 2) { 0108 Kdesvnsettings::setCommit_splitter_height(list); 0109 Kdesvnsettings::self()->save(); 0110 } 0111 delete m_CurrentModel; 0112 delete m_SortModel; 0113 } 0114 0115 void Commitmsg_impl::setupModel() 0116 { 0117 m_SortModel = new CommitFilterModel(m_CommitItemTree); 0118 m_CommitItemTree->setModel(m_SortModel); 0119 m_SortModel->setSourceModel(m_CurrentModel); 0120 0121 m_CommitItemTree->resizeColumnToContents(m_CurrentModel->ItemColumn()); 0122 m_CommitItemTree->resizeColumnToContents(m_CurrentModel->ActionColumn()); 0123 0124 m_SortModel->setSortCaseSensitivity(Kdesvnsettings::case_sensitive_sort() ? Qt::CaseSensitive : Qt::CaseInsensitive); 0125 connect(m_CommitItemTree->selectionModel(), &QItemSelectionModel::currentChanged, this, &Commitmsg_impl::slotCurrentItemChanged); 0126 slotCurrentItemChanged(QModelIndex()); // update pushbuttons 0127 } 0128 0129 void Commitmsg_impl::checkSplitterSize() 0130 { 0131 QList<int> list = Kdesvnsettings::commit_splitter_height(); 0132 if (list.count() != 2) { 0133 return; 0134 } 0135 if (m_hidden) { 0136 list[1] = list[0] + list[1]; 0137 list[0] = 0; 0138 } 0139 if (m_hidden || (list[0] > 0 || list[1] > 0)) { 0140 m_MainSplitter->setSizes(list); 0141 } 0142 } 0143 0144 void Commitmsg_impl::slotHistoryActivated(int number) 0145 { 0146 if (number < 1 || number > sLogHistory.size()) { 0147 m_LogEdit->clear(); 0148 } else { 0149 m_LogEdit->setText(sLogHistory[number - 1]); 0150 } 0151 } 0152 0153 /*! 0154 \fn Commitmsg_impl::getMessage()const 0155 */ 0156 QString Commitmsg_impl::getMessage() const 0157 { 0158 return m_LogEdit->toPlainText(); 0159 } 0160 0161 /*! 0162 \fn Commitmsg_impl::isRecursive()const 0163 */ 0164 svn::Depth Commitmsg_impl::getDepth() const 0165 { 0166 return m_DepthSelector->getDepth(); 0167 } 0168 0169 void Commitmsg_impl::keepsLocks(bool keeps_lock) 0170 { 0171 if (keeps_lock) { 0172 m_keepLocksButton->show(); 0173 } else { 0174 m_keepLocksButton->hide(); 0175 } 0176 } 0177 0178 /*! 0179 \fn Commitmsg_impl::isRecursive()const 0180 */ 0181 bool Commitmsg_impl::isKeeplocks() const 0182 { 0183 return m_keepLocksButton->isChecked(); 0184 } 0185 0186 /*! 0187 \fn Commitmsg_impl::initHistory() 0188 */ 0189 void Commitmsg_impl::initHistory() 0190 { 0191 if (smax_message_history == 0xFFFF) { 0192 smax_message_history = Kdesvnsettings::max_log_messages(); 0193 KConfigGroup cs(Kdesvnsettings::self()->config(), "log_messages"); 0194 QString s; 0195 int current = 0; 0196 QString key = QStringLiteral("log_%0").arg(current); 0197 s = cs.readEntry(key, QString()); 0198 while (!s.isNull()) { 0199 if (current < smax_message_history) { 0200 sLogHistory.push_back(s); 0201 } else { 0202 cs.deleteEntry(key); 0203 } 0204 ++current; 0205 key = QStringLiteral("log_%0").arg(current); 0206 s = cs.readEntry(key, QString()); 0207 } 0208 } 0209 QStringList::const_iterator it; 0210 for (const QString &historyEntry : qAsConst(sLogHistory)) { 0211 if (historyEntry.length() <= 40) { 0212 m_LogHistory->addItem(historyEntry); 0213 } else { 0214 m_LogHistory->addItem(historyEntry.leftRef(37) + QStringLiteral("...")); 0215 } 0216 } 0217 if (!sLastMessage.isEmpty()) { 0218 m_LogEdit->setText(sLastMessage); 0219 sLastMessage.clear(); 0220 } 0221 } 0222 0223 /*! 0224 \fn Commitmsg_impl::saveHistory() 0225 */ 0226 void Commitmsg_impl::saveHistory(bool canceld) 0227 { 0228 QString _text = m_LogEdit->toPlainText(); 0229 if (_text.isEmpty() || _text.length() > 512) { 0230 return; 0231 } 0232 /// @todo make static threadsafe 0233 if (!canceld) { 0234 int it; 0235 if ((it = sLogHistory.indexOf(_text)) != -1) { 0236 sLogHistory.removeAt(it); 0237 } 0238 sLogHistory.push_front(_text); 0239 if (sLogHistory.size() > smax_message_history) { 0240 sLogHistory.removeLast(); 0241 } 0242 KConfigGroup cs(Kdesvnsettings::self()->config(), "log_messages"); 0243 for (int i = 0; i < sLogHistory.size(); ++i) { 0244 cs.writeEntry(QStringLiteral("log_%0").arg(i), sLogHistory[i]); 0245 } 0246 cs.sync(); 0247 } else { 0248 sLastMessage = _text; 0249 } 0250 } 0251 0252 QString Commitmsg_impl::getLogmessage(bool *ok, svn::Depth *rec, bool *keep_locks, QWidget *parent) 0253 { 0254 return getLogmessageInternal(new Commitmsg_impl, ok, rec, keep_locks, nullptr, parent); 0255 } 0256 0257 QString Commitmsg_impl::getLogmessage(const svn::CommitItemList &items, bool *ok, svn::Depth *rec, bool *keep_locks, QWidget *parent) 0258 { 0259 return getLogmessageInternal(new Commitmsg_impl(items), ok, rec, keep_locks, nullptr, parent); 0260 } 0261 0262 QString Commitmsg_impl::getLogmessage(const CommitActionEntries &_on, 0263 const CommitActionEntries &_off, 0264 QObject *callback, 0265 CommitActionEntries &_result, 0266 bool *ok, 0267 bool *keep_locks, 0268 QWidget *parent) 0269 { 0270 Commitmsg_impl *ptr = new Commitmsg_impl(_on, _off); 0271 if (callback) { 0272 connect(ptr, 0273 SIGNAL(makeDiff(QString, svn::Revision, QString, svn::Revision, QWidget *)), 0274 callback, 0275 SLOT(makeDiff(QString, svn::Revision, QString, svn::Revision, QWidget *))); 0276 connect(ptr, SIGNAL(sigRevertItem(QStringList)), callback, SLOT(slotRevertItems(QStringList))); 0277 connect(callback, SIGNAL(sigItemsReverted(QStringList)), ptr, SLOT(slotItemReverted(QStringList))); 0278 } 0279 return getLogmessageInternal(ptr, ok, nullptr, keep_locks, &_result, parent); 0280 } 0281 0282 QString Commitmsg_impl::getLogmessageInternal(Commitmsg_impl *ptr, bool *ok, svn::Depth *rec, bool *keep_locks, CommitActionEntries *result, QWidget *parent) 0283 { 0284 bool _ok, _keep_locks; 0285 svn::Depth _depth = svn::DepthUnknown; 0286 QString msg; 0287 0288 QPointer<KSvnSimpleOkDialog> dlg(new KSvnSimpleOkDialog(QStringLiteral("logmsg_dlg_size"), parent)); 0289 dlg->setWindowTitle(i18nc("@title:window", "Commit Log")); 0290 dlg->setWithCancelButton(); 0291 dlg->addWidget(ptr); 0292 0293 if (!rec) { 0294 ptr->m_DepthSelector->hide(); 0295 } 0296 if (!keep_locks) { 0297 ptr->m_keepLocksButton->hide(); 0298 } 0299 0300 ptr->initHistory(); 0301 if (dlg->exec() != QDialog::Accepted) { 0302 _ok = false; 0303 /* avoid compiler warnings */ 0304 _keep_locks = false; 0305 } else { 0306 _ok = true; 0307 _depth = ptr->getDepth(); 0308 _keep_locks = ptr->isKeeplocks(); 0309 msg = ptr->getMessage(); 0310 } 0311 if (dlg) { 0312 ptr->saveHistory(!_ok); 0313 } 0314 0315 if (ok) { 0316 *ok = _ok; 0317 } 0318 if (rec) { 0319 *rec = _depth; 0320 } 0321 if (keep_locks) { 0322 *keep_locks = _keep_locks; 0323 } 0324 if (result) { 0325 *result = ptr->checkedEntries(); 0326 } 0327 delete dlg; 0328 return msg; 0329 } 0330 0331 /*! 0332 \fn Commitmsg_impl::setRecCheckboxtext(const QString&what) 0333 */ 0334 void Commitmsg_impl::addItemWidget(QWidget *aWidget) 0335 { 0336 m_DepthSelector->addItemWidget(aWidget); 0337 } 0338 0339 CommitActionEntries Commitmsg_impl::checkedEntries() const 0340 { 0341 if (m_CurrentModel) { 0342 return m_CurrentModel->checkedEntries(); 0343 } 0344 return CommitActionEntries(); 0345 } 0346 0347 void Commitmsg_impl::slotUnmarkUnversioned() 0348 { 0349 markUnversioned(false); 0350 } 0351 0352 void Commitmsg_impl::slotMarkUnversioned() 0353 { 0354 markUnversioned(true); 0355 } 0356 0357 void Commitmsg_impl::slotDiffSelected() 0358 { 0359 CommitModelNodePtr ptr = currentCommitItem(); 0360 if (!ptr) { 0361 return; 0362 } 0363 QString what = ptr->actionEntry().name(); 0364 emit makeDiff(what, svn::Revision::BASE, what, svn::Revision::WORKING, parentWidget()); 0365 } 0366 0367 void Commitmsg_impl::slotRevertSelected() 0368 { 0369 CommitModelNodePtr ptr = currentCommitItem(); 0370 if (!ptr) { 0371 return; 0372 } 0373 QStringList what(ptr->actionEntry().name()); 0374 emit sigRevertItem(what); 0375 } 0376 0377 CommitModelNodePtr Commitmsg_impl::currentCommitItem(int column) 0378 { 0379 CommitModelNodePtr res; 0380 if (!m_CurrentModel) { 0381 return res; 0382 } 0383 QModelIndexList _mi = m_CommitItemTree->selectionModel()->selectedRows(column); 0384 if (_mi.isEmpty()) { 0385 return res; 0386 } 0387 QModelIndex ind = m_SortModel->mapToSource(_mi[0]); 0388 if (ind.isValid()) { 0389 res = m_CurrentModel->node(ind); 0390 } 0391 return res; 0392 } 0393 0394 void Commitmsg_impl::hideKeepsLock(bool how) 0395 { 0396 m_keepLocksButton->setVisible(!how); 0397 } 0398 0399 void Commitmsg_impl::hideButtons(bool how) 0400 { 0401 if (!m_MarkUnversioned) { 0402 return; 0403 } 0404 if (how) { 0405 m_MarkUnversioned->hide(); 0406 m_UnmarkUnversioned->hide(); 0407 m_DiffItem->hide(); 0408 m_HideNewItems->hide(); 0409 m_SelectAllButton->hide(); 0410 m_UnselectAllButton->hide(); 0411 } else { 0412 m_MarkUnversioned->show(); 0413 m_UnmarkUnversioned->show(); 0414 m_DiffItem->show(); 0415 m_HideNewItems->show(); 0416 m_SelectAllButton->show(); 0417 m_UnselectAllButton->show(); 0418 } 0419 } 0420 0421 /*! 0422 \fn Commitmsg_impl::markUnversioned(bool mark) 0423 */ 0424 void Commitmsg_impl::markUnversioned(bool mark) 0425 { 0426 if (!m_CurrentModel) { 0427 return; 0428 } 0429 m_CurrentModel->markItems(mark, CommitActionEntry::ADD_COMMIT); 0430 } 0431 0432 void Commitmsg_impl::slotSelectAll() 0433 { 0434 if (!m_CurrentModel) { 0435 return; 0436 } 0437 m_CurrentModel->markItems(true, CommitActionEntry::ALL); 0438 } 0439 0440 void Commitmsg_impl::slotUnselectAll() 0441 { 0442 if (!m_CurrentModel) { 0443 return; 0444 } 0445 m_CurrentModel->markItems(false, CommitActionEntry::ALL); 0446 } 0447 0448 void Commitmsg_impl::hideNewItems(bool hide) 0449 { 0450 if (!m_CurrentModel) { 0451 return; 0452 } 0453 Kdesvnsettings::setCommit_hide_new(hide); 0454 m_SortModel->hideItems(hide, CommitActionEntry::ADD_COMMIT); 0455 m_HideNewItems->setText(hide ? i18n("Show new items") : i18n("Hide new items")); 0456 } 0457 0458 /*! 0459 \fn Commitmsg_impl::hideDepth(bool hide) 0460 */ 0461 void Commitmsg_impl::hideDepth(bool ahide) 0462 { 0463 m_DepthSelector->hideDepth(ahide); 0464 } 0465 0466 void Commitmsg_impl::insertFile(const QString &fname) 0467 { 0468 QFile ifs(fname); 0469 if (ifs.open(QIODevice::ReadOnly)) { 0470 QTextStream ts(&ifs); 0471 QString _content = ts.readAll(); 0472 m_LogEdit->textCursor().insertText(_content); 0473 } 0474 } 0475 0476 void Commitmsg_impl::insertFile() 0477 { 0478 QString windowTitle = i18nc("@title:window", "Select Text File to Insert"); 0479 QPointer<KUrlRequesterDialog> dlg(new KUrlRequesterDialog(QUrl(), i18n("Select text file to insert:"), this)); 0480 dlg->setWindowTitle(windowTitle); 0481 KFile::Mode mode = static_cast<KFile::Mode>(KFile::File); 0482 dlg->urlRequester()->setMode(mode); 0483 dlg->urlRequester()->setWindowTitle(windowTitle); 0484 0485 if (dlg->exec() != QDialog::Accepted) { 0486 delete dlg; 0487 return; 0488 } 0489 QUrl _url = dlg->selectedUrl(); 0490 delete dlg; 0491 if (_url.isEmpty() || !_url.isValid()) { 0492 return; 0493 } 0494 if (_url.isLocalFile()) { 0495 insertFile(_url.path()); 0496 } else { 0497 QTemporaryFile tf; 0498 tf.open(); 0499 KIO::FileCopyJob *job = KIO::file_copy(_url, QUrl::fromLocalFile(tf.fileName())); 0500 KJobWidgets::setWindow(job, this); 0501 if (job->exec()) { 0502 insertFile(tf.fileName()); 0503 } else { 0504 KMessageBox::error(this, job->errorString()); 0505 } 0506 } 0507 } 0508 0509 /*! 0510 \fn Commitmsg_impl::slotItemReverted(const QStringList&) 0511 */ 0512 void Commitmsg_impl::slotItemReverted(const QStringList &items) 0513 { 0514 if (!m_CurrentModel) { 0515 return; 0516 } 0517 m_CurrentModel->removeEntries(items); 0518 } 0519 0520 void Commitmsg_impl::slotItemDoubleClicked(const QModelIndex &index) 0521 { 0522 Q_UNUSED(index); 0523 slotDiffSelected(); 0524 } 0525 0526 void Commitmsg_impl::slotCurrentItemChanged(const QModelIndex ¤t) 0527 { 0528 bool bDiffRevertEnabled = false; 0529 0530 const CommitModelNodePtr node = m_CurrentModel->dataForRow(m_SortModel->mapToSource(current).row()); 0531 if (!node.isNull()) { 0532 bDiffRevertEnabled = (node->actionEntry().type() == CommitActionEntry::COMMIT); 0533 } 0534 m_RevertItemButton->setEnabled(bDiffRevertEnabled); 0535 m_DiffItem->setEnabled(bDiffRevertEnabled); 0536 } 0537 0538 #include "moc_commitmsg_impl.cpp"