File indexing completed on 2024-05-12 17:16:02
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 "models/commitmodelhelper.h" 0022 #include "models/commitmodel.h" 0023 #include "settings/kdesvnsettings.h" 0024 #include "depthselector.h" 0025 #include "ksvnwidgets/ksvndialog.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 <QStringList> 0037 #include <QTemporaryFile> 0038 #include <QFile> 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), CommitMessage() 0049 { 0050 setupUi(this); 0051 m_CurrentModel = nullptr; 0052 m_SortModel = nullptr; 0053 m_LogEdit->setFocus(); 0054 m_Reviewlabel->hide(); 0055 m_hidden = true; 0056 hideButtons(true); 0057 m_MainSplitter->insertWidget(0, m_EditFrame); 0058 delete m_ReviewFrame; 0059 m_Reviewlabel = nullptr; 0060 m_MarkUnversioned = nullptr; 0061 m_UnmarkUnversioned = nullptr; 0062 m_DiffItem = nullptr; 0063 } 0064 0065 Commitmsg_impl::Commitmsg_impl(const svn::CommitItemList &_items, QWidget *parent) 0066 : QWidget(parent), CommitMessage() 0067 { 0068 setupUi(this); 0069 m_CurrentModel = nullptr; 0070 m_SortModel = nullptr; 0071 m_LogEdit->setFocus(); 0072 hideButtons(true); 0073 if (!_items.isEmpty()) { 0074 m_CurrentModel = new CommitModel(_items); 0075 setupModel(); 0076 m_hidden = false; 0077 } else { 0078 m_Reviewlabel->hide(); 0079 m_CommitItemTree->hide(); 0080 m_hidden = true; 0081 } 0082 checkSplitterSize(); 0083 } 0084 0085 Commitmsg_impl::Commitmsg_impl(const CommitActionEntries &_activatedList, 0086 const CommitActionEntries &_notActivatedList, 0087 QWidget *parent) 0088 : QWidget(parent), CommitMessage() 0089 { 0090 setupUi(this); 0091 m_CurrentModel = nullptr; 0092 m_SortModel = nullptr; 0093 m_LogEdit->setFocus(); 0094 m_hidden = false; 0095 0096 m_CurrentModel = new CommitModelCheckitem(_activatedList, _notActivatedList); 0097 setupModel(); 0098 0099 m_HideNewItems->setChecked(Kdesvnsettings::commit_hide_new()); 0100 checkSplitterSize(); 0101 } 0102 0103 Commitmsg_impl::~Commitmsg_impl() 0104 { 0105 QList<int> list = m_MainSplitter->sizes(); 0106 if (!m_hidden && list.count() == 2) { 0107 Kdesvnsettings::setCommit_splitter_height(list); 0108 Kdesvnsettings::self()->save(); 0109 } 0110 delete m_CurrentModel; 0111 delete m_SortModel; 0112 } 0113 0114 void Commitmsg_impl::setupModel() 0115 { 0116 m_SortModel = new CommitFilterModel(m_CommitItemTree); 0117 m_CommitItemTree->setModel(m_SortModel); 0118 m_SortModel->setSourceModel(m_CurrentModel); 0119 0120 m_CommitItemTree->resizeColumnToContents(m_CurrentModel->ItemColumn()); 0121 m_CommitItemTree->resizeColumnToContents(m_CurrentModel->ActionColumn()); 0122 0123 m_SortModel->setSortCaseSensitivity(Kdesvnsettings::case_sensitive_sort() ? Qt::CaseSensitive : Qt::CaseInsensitive); 0124 connect(m_CommitItemTree->selectionModel(), &QItemSelectionModel::currentChanged, 0125 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 (it = sLogHistory.constBegin(); it != sLogHistory.constEnd(); ++it) { 0211 if ((*it).length() <= 40) { 0212 m_LogHistory->addItem((*it)); 0213 } else { 0214 m_LogHistory->addItem((*it).left(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, bool *keep_locks, QWidget *parent) 0267 { 0268 Commitmsg_impl *ptr = new Commitmsg_impl(_on, _off); 0269 if (callback) { 0270 connect(ptr, SIGNAL(makeDiff(QString,svn::Revision,QString,svn::Revision,QWidget*)), 0271 callback, SLOT(makeDiff(QString,svn::Revision,QString,svn::Revision,QWidget*))); 0272 connect(ptr, SIGNAL(sigRevertItem(QStringList)), 0273 callback, SLOT(slotRevertItems(QStringList))); 0274 connect(callback, SIGNAL(sigItemsReverted(QStringList)), 0275 ptr, SLOT(slotItemReverted(QStringList))); 0276 } 0277 return getLogmessageInternal(ptr, ok, nullptr, keep_locks, &_result, parent); 0278 } 0279 0280 QString Commitmsg_impl::getLogmessageInternal(Commitmsg_impl *ptr, bool *ok, svn::Depth *rec, bool *keep_locks, CommitActionEntries *result, QWidget *parent) 0281 { 0282 bool _ok, _keep_locks; 0283 svn::Depth _depth = svn::DepthUnknown; 0284 QString msg; 0285 0286 QPointer<KSvnSimpleOkDialog> dlg(new KSvnSimpleOkDialog(QStringLiteral("logmsg_dlg_size"), parent)); 0287 dlg->setWindowTitle(i18nc("@title:window", "Commit Log")); 0288 dlg->setWithCancelButton(); 0289 dlg->addWidget(ptr); 0290 0291 if (!rec) { 0292 ptr->m_DepthSelector->hide(); 0293 } 0294 if (!keep_locks) { 0295 ptr->m_keepLocksButton->hide(); 0296 } 0297 0298 ptr->initHistory(); 0299 if (dlg->exec() != QDialog::Accepted) { 0300 _ok = false; 0301 /* avoid compiler warnings */ 0302 _keep_locks = false; 0303 } else { 0304 _ok = true; 0305 _depth = ptr->getDepth(); 0306 _keep_locks = ptr->isKeeplocks(); 0307 msg = ptr->getMessage(); 0308 } 0309 if (dlg) { 0310 ptr->saveHistory(!_ok); 0311 } 0312 0313 if (ok) { 0314 *ok = _ok; 0315 } 0316 if (rec) { 0317 *rec = _depth; 0318 } 0319 if (keep_locks) { 0320 *keep_locks = _keep_locks; 0321 } 0322 if (result) { 0323 *result = ptr->checkedEntries(); 0324 } 0325 delete dlg; 0326 return msg; 0327 } 0328 0329 /*! 0330 \fn Commitmsg_impl::setRecCheckboxtext(const QString&what) 0331 */ 0332 void Commitmsg_impl::addItemWidget(QWidget *aWidget) 0333 { 0334 m_DepthSelector->addItemWidget(aWidget); 0335 } 0336 0337 CommitActionEntries Commitmsg_impl::checkedEntries() const 0338 { 0339 if (m_CurrentModel) { 0340 return m_CurrentModel->checkedEntries(); 0341 } 0342 return CommitActionEntries(); 0343 } 0344 0345 void Commitmsg_impl::slotUnmarkUnversioned() 0346 { 0347 markUnversioned(false); 0348 } 0349 0350 void Commitmsg_impl::slotMarkUnversioned() 0351 { 0352 markUnversioned(true); 0353 } 0354 0355 void Commitmsg_impl::slotDiffSelected() 0356 { 0357 CommitModelNodePtr ptr = currentCommitItem(); 0358 if (!ptr) { 0359 return; 0360 } 0361 QString what = ptr->actionEntry().name(); 0362 emit makeDiff(what, svn::Revision::BASE, what, svn::Revision::WORKING, parentWidget()); 0363 } 0364 0365 void Commitmsg_impl::slotRevertSelected() 0366 { 0367 CommitModelNodePtr ptr = currentCommitItem(); 0368 if (!ptr) { 0369 return; 0370 } 0371 QStringList what(ptr->actionEntry().name()); 0372 emit sigRevertItem(what); 0373 } 0374 0375 CommitModelNodePtr Commitmsg_impl::currentCommitItem(int column) 0376 { 0377 CommitModelNodePtr res; 0378 if (!m_CurrentModel) { 0379 return res; 0380 } 0381 QModelIndexList _mi = m_CommitItemTree->selectionModel()->selectedRows(column); 0382 if (_mi.isEmpty()) { 0383 return res; 0384 } 0385 QModelIndex ind = m_SortModel->mapToSource(_mi[0]); 0386 if (ind.isValid()) { 0387 res = m_CurrentModel->node(ind); 0388 } 0389 return res; 0390 } 0391 0392 void Commitmsg_impl::hideKeepsLock(bool how) 0393 { 0394 m_keepLocksButton->setVisible(!how); 0395 } 0396 0397 void Commitmsg_impl::hideButtons(bool how) 0398 { 0399 if (!m_MarkUnversioned) { 0400 return; 0401 } 0402 if (how) { 0403 m_MarkUnversioned->hide(); 0404 m_UnmarkUnversioned->hide(); 0405 m_DiffItem->hide(); 0406 m_HideNewItems->hide(); 0407 m_SelectAllButton->hide(); 0408 m_UnselectAllButton->hide(); 0409 } else { 0410 m_MarkUnversioned->show(); 0411 m_UnmarkUnversioned->show(); 0412 m_DiffItem->show(); 0413 m_HideNewItems->show(); 0414 m_SelectAllButton->show(); 0415 m_UnselectAllButton->show(); 0416 } 0417 } 0418 0419 /*! 0420 \fn Commitmsg_impl::markUnversioned(bool mark) 0421 */ 0422 void Commitmsg_impl::markUnversioned(bool mark) 0423 { 0424 if (!m_CurrentModel) { 0425 return; 0426 } 0427 m_CurrentModel->markItems(mark, CommitActionEntry::ADD_COMMIT); 0428 } 0429 0430 void Commitmsg_impl::slotSelectAll() 0431 { 0432 if (!m_CurrentModel) { 0433 return; 0434 } 0435 m_CurrentModel->markItems(true, CommitActionEntry::ALL); 0436 } 0437 0438 void Commitmsg_impl::slotUnselectAll() 0439 { 0440 if (!m_CurrentModel) { 0441 return; 0442 } 0443 m_CurrentModel->markItems(false, CommitActionEntry::ALL); 0444 } 0445 0446 void Commitmsg_impl::hideNewItems(bool hide) 0447 { 0448 if (!m_CurrentModel) { 0449 return; 0450 } 0451 Kdesvnsettings::setCommit_hide_new(hide); 0452 m_SortModel->hideItems(hide, CommitActionEntry::ADD_COMMIT); 0453 m_HideNewItems->setText(hide ? i18n("Show new items") : i18n("Hide new items")); 0454 } 0455 0456 /*! 0457 \fn Commitmsg_impl::hideDepth(bool hide) 0458 */ 0459 void Commitmsg_impl::hideDepth(bool ahide) 0460 { 0461 m_DepthSelector->hideDepth(ahide); 0462 } 0463 0464 void Commitmsg_impl::insertFile(const QString &fname) 0465 { 0466 QFile ifs(fname); 0467 if (ifs.open(QIODevice::ReadOnly)) { 0468 QTextStream ts(&ifs); 0469 QString _content = ts.readAll(); 0470 m_LogEdit->textCursor().insertText(_content); 0471 } 0472 } 0473 0474 void Commitmsg_impl::insertFile() 0475 { 0476 QString windowTitle = i18nc("@title:window", "Select Text File to Insert"); 0477 QPointer<KUrlRequesterDialog> dlg(new KUrlRequesterDialog(QUrl(), i18n("Select text file to insert:"), this)); 0478 dlg->setWindowTitle(windowTitle); 0479 KFile::Mode mode = static_cast<KFile::Mode>(KFile::File); 0480 dlg->urlRequester()->setMode(mode); 0481 dlg->urlRequester()->setWindowTitle(windowTitle); 0482 0483 if (dlg->exec() != QDialog::Accepted) { 0484 delete dlg; 0485 return; 0486 } 0487 QUrl _url = dlg->selectedUrl(); 0488 delete dlg; 0489 if (_url.isEmpty() || !_url.isValid()) { 0490 return; 0491 } 0492 if (_url.isLocalFile()) { 0493 insertFile(_url.path()); 0494 } else { 0495 QTemporaryFile tf; 0496 tf.open(); 0497 KIO::FileCopyJob *job = KIO::file_copy(_url, QUrl::fromLocalFile(tf.fileName())); 0498 KJobWidgets::setWindow(job, this); 0499 if (job->exec()) { 0500 insertFile(tf.fileName()); 0501 } else { 0502 KMessageBox::error(this, job->errorString()); 0503 } 0504 } 0505 } 0506 0507 /*! 0508 \fn Commitmsg_impl::slotItemReverted(const QStringList&) 0509 */ 0510 void Commitmsg_impl::slotItemReverted(const QStringList &items) 0511 { 0512 if (!m_CurrentModel) { 0513 return; 0514 } 0515 m_CurrentModel->removeEntries(items); 0516 } 0517 0518 void Commitmsg_impl::slotItemDoubleClicked(const QModelIndex &index) 0519 { 0520 Q_UNUSED(index); 0521 slotDiffSelected(); 0522 } 0523 0524 void Commitmsg_impl::slotCurrentItemChanged(const QModelIndex ¤t) 0525 { 0526 bool bDiffRevertEnabled = false; 0527 0528 const CommitModelNodePtr node = m_CurrentModel->dataForRow(m_SortModel->mapToSource(current).row()); 0529 if (!node.isNull()) { 0530 bDiffRevertEnabled = (node->actionEntry().type() == CommitActionEntry::COMMIT); 0531 } 0532 m_RevertItemButton->setEnabled(bDiffRevertEnabled); 0533 m_DiffItem->setEnabled(bDiffRevertEnabled); 0534 }