Warning, file /sdk/cervisia/historydialog.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * Copyright (C) 1999-2002 Bernd Gehrmann 0003 * bernd@mail.berlios.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 Free Software 0017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "historydialog.h" 0021 0022 #include <QCheckBox> 0023 #include <QDateTime> 0024 #include <QDialogButtonBox> 0025 #include <QHeaderView> 0026 #include <QLineEdit> 0027 #include <QPushButton> 0028 #include <QRegExp> 0029 #include <QTreeWidget> 0030 #include <QVBoxLayout> 0031 0032 #include <KConfig> 0033 #include <KConfigGroup> 0034 #include <KHelpClient> 0035 #include <KLocalizedString> 0036 0037 #include "cvsserviceinterface.h" 0038 #include "misc.h" 0039 #include "progressdialog.h" 0040 0041 static QDateTime parseDate(const QString &date, const QString &time, const QString &_offset) 0042 { 0043 // cvs history only prints hhmm but fromString() needs hh:mm 0044 QString offset(_offset); 0045 if (!offset.contains(':') && offset.size() == 5) 0046 offset.insert(3, ':'); 0047 0048 const QDateTime dt(QDateTime::fromString(date + 'T' + time + offset, Qt::ISODate)); 0049 if (!dt.isValid()) 0050 return {}; 0051 0052 QDateTime dateTime; 0053 dateTime.setTime_t(dt.toTime_t()); 0054 0055 return dateTime; 0056 } 0057 0058 class HistoryItem : public QTreeWidgetItem 0059 { 0060 public: 0061 enum { Date, Event, Author, Revision, File, Path }; 0062 0063 HistoryItem(QTreeWidget *parent, const QDateTime &date) 0064 : QTreeWidgetItem(parent) 0065 , m_date(date) 0066 { 0067 } 0068 0069 bool operator<(const QTreeWidgetItem &other) const override; 0070 0071 QVariant data(int column, int role) const override; 0072 0073 bool isCommit(); 0074 bool isCheckout(); 0075 bool isTag(); 0076 bool isOther(); 0077 0078 private: 0079 const QDateTime m_date; 0080 }; 0081 0082 bool HistoryItem::operator<(const QTreeWidgetItem &other) const 0083 { 0084 const auto &item = static_cast<const HistoryItem &>(other); 0085 0086 switch (treeWidget()->sortColumn()) { 0087 case Date: 0088 return ::compare(m_date, item.m_date) == -1; 0089 case Revision: 0090 return ::compareRevisions(text(Revision), item.text(Revision)) == -1; 0091 } 0092 0093 return QTreeWidgetItem::operator<(other); 0094 } 0095 0096 QVariant HistoryItem::data(int column, int role) const 0097 { 0098 if ((role == Qt::DisplayRole) && (column == Date)) 0099 return QLocale().toString(m_date); 0100 0101 return QTreeWidgetItem::data(column, role); 0102 } 0103 0104 bool HistoryItem::isCommit() 0105 { 0106 return text(1) == i18n("Commit, Modified ") || text(1) == i18n("Commit, Added ") || text(1) == i18n("Commit, Removed "); 0107 } 0108 0109 bool HistoryItem::isCheckout() 0110 { 0111 return text(1) == i18n("Checkout "); 0112 } 0113 0114 bool HistoryItem::isTag() 0115 { 0116 return text(1) == i18n("Tag"); 0117 } 0118 0119 bool HistoryItem::isOther() 0120 { 0121 return !isCommit() && !isCheckout() && !isTag(); 0122 } 0123 0124 HistoryDialog::HistoryDialog(KConfig &cfg, QWidget *parent) 0125 : QDialog(parent) 0126 , partConfig(cfg) 0127 { 0128 auto mainLayout = new QVBoxLayout; 0129 setLayout(mainLayout); 0130 0131 listview = new QTreeWidget; 0132 listview->setSelectionMode(QAbstractItemView::NoSelection); 0133 listview->setAllColumnsShowFocus(true); 0134 listview->setRootIsDecorated(false); 0135 listview->header()->setSortIndicatorShown(true); 0136 listview->setSortingEnabled(true); 0137 listview->sortByColumn(HistoryItem::Date, Qt::DescendingOrder); 0138 listview->setHeaderLabels(QStringList() << i18n("Date") << i18n("Event") << i18n("Author") << i18n("Revision") << i18n("File") << i18n("Repo Path")); 0139 listview->setFocus(); 0140 mainLayout->addWidget(listview); 0141 0142 commit_box = new QCheckBox(i18n("Show c&ommit events")); 0143 commit_box->setChecked(true); 0144 0145 checkout_box = new QCheckBox(i18n("Show ch&eckout events")); 0146 checkout_box->setChecked(true); 0147 0148 tag_box = new QCheckBox(i18n("Show &tag events")); 0149 tag_box->setChecked(true); 0150 0151 other_box = new QCheckBox(i18n("Show &other events")); 0152 other_box->setChecked(true); 0153 0154 onlyuser_box = new QCheckBox(i18n("Only &user:")); 0155 0156 onlyfilenames_box = new QCheckBox(i18n("Only &filenames matching:")); 0157 0158 onlydirnames_box = new QCheckBox(i18n("Only &folders matching:")); 0159 0160 user_edit = new QLineEdit; 0161 user_edit->setEnabled(false); 0162 0163 filename_edit = new QLineEdit; 0164 filename_edit->setEnabled(false); 0165 0166 dirname_edit = new QLineEdit; 0167 dirname_edit->setEnabled(false); 0168 0169 auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Close); 0170 connect(buttonBox, &QDialogButtonBox::helpRequested, this, &HistoryDialog::slotHelp); 0171 connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); 0172 0173 connect(onlyuser_box, SIGNAL(toggled(bool)), this, SLOT(toggled(bool))); 0174 connect(onlyfilenames_box, SIGNAL(toggled(bool)), this, SLOT(toggled(bool))); 0175 connect(onlydirnames_box, SIGNAL(toggled(bool)), this, SLOT(toggled(bool))); 0176 connect(commit_box, SIGNAL(toggled(bool)), this, SLOT(choiceChanged())); 0177 connect(checkout_box, SIGNAL(toggled(bool)), this, SLOT(choiceChanged())); 0178 connect(tag_box, SIGNAL(toggled(bool)), this, SLOT(choiceChanged())); 0179 connect(other_box, SIGNAL(toggled(bool)), this, SLOT(choiceChanged())); 0180 connect(onlyuser_box, SIGNAL(toggled(bool)), this, SLOT(choiceChanged())); 0181 connect(onlyfilenames_box, SIGNAL(toggled(bool)), this, SLOT(choiceChanged())); 0182 connect(onlydirnames_box, SIGNAL(toggled(bool)), this, SLOT(choiceChanged())); 0183 connect(user_edit, SIGNAL(returnPressed()), this, SLOT(choiceChanged())); 0184 connect(filename_edit, SIGNAL(returnPressed()), this, SLOT(choiceChanged())); 0185 connect(dirname_edit, SIGNAL(returnPressed()), this, SLOT(choiceChanged())); 0186 0187 auto grid = new QGridLayout; 0188 mainLayout->addLayout(grid); 0189 grid->setColumnStretch(0, 1); 0190 grid->setColumnStretch(1, 0); 0191 grid->setColumnStretch(2, 4); 0192 grid->setColumnStretch(3, 1); 0193 grid->addWidget(commit_box, 0, 0); 0194 grid->addWidget(checkout_box, 1, 0); 0195 grid->addWidget(tag_box, 2, 0); 0196 grid->addWidget(other_box, 3, 0); 0197 grid->addWidget(onlyuser_box, 0, 1); 0198 grid->addWidget(user_edit, 0, 2); 0199 grid->addWidget(onlyfilenames_box, 1, 1); 0200 grid->addWidget(filename_edit, 1, 2); 0201 grid->addWidget(onlydirnames_box, 2, 1); 0202 grid->addWidget(dirname_edit, 2, 2); 0203 0204 // no default button because "return" is needed to activate the filters (line edits) 0205 buttonBox->button(QDialogButtonBox::Help)->setAutoDefault(false); 0206 buttonBox->button(QDialogButtonBox::Close)->setAutoDefault(false); 0207 0208 mainLayout->addWidget(buttonBox); 0209 0210 setAttribute(Qt::WA_DeleteOnClose, true); 0211 0212 KConfigGroup cg(&partConfig, "HistoryDialog"); 0213 restoreGeometry(cg.readEntry<QByteArray>("geometry", QByteArray())); 0214 0215 QByteArray state = cg.readEntry<QByteArray>("HistoryListView", QByteArray()); 0216 listview->header()->restoreState(state); 0217 } 0218 0219 HistoryDialog::~HistoryDialog() 0220 { 0221 KConfigGroup cg(&partConfig, "HistoryDialog"); 0222 cg.writeEntry("geometry", saveGeometry()); 0223 0224 cg.writeEntry("HistoryListView", listview->header()->saveState()); 0225 } 0226 0227 void HistoryDialog::slotHelp() 0228 { 0229 KHelpClient::invokeHelp(QLatin1String("browsinghistory")); 0230 } 0231 0232 void HistoryDialog::choiceChanged() 0233 { 0234 const QString author(user_edit->text()); 0235 const QRegExp fileMatcher(filename_edit->text(), Qt::CaseSensitive, QRegExp::Wildcard); 0236 const QRegExp pathMatcher(dirname_edit->text(), Qt::CaseSensitive, QRegExp::Wildcard); 0237 0238 const bool showCommitEvents(commit_box->isChecked()); 0239 const bool showCheckoutEvents(checkout_box->isChecked()); 0240 const bool showTagEvents(tag_box->isChecked()); 0241 const bool showOtherEvents(other_box->isChecked()); 0242 const bool filterByAuthor(onlyuser_box->isChecked() && !author.isEmpty()); 0243 const bool filterByFile(onlyfilenames_box->isChecked() && !fileMatcher.isEmpty()); 0244 const bool filterByPath(onlydirnames_box->isChecked() && !pathMatcher.isEmpty()); 0245 0246 for (int i = 0; i < listview->topLevelItemCount(); i++) { 0247 auto item = static_cast<HistoryItem *>(listview->topLevelItem(i)); 0248 0249 bool visible((showCommitEvents && item->isCommit()) || (showCheckoutEvents && item->isCheckout()) || (showTagEvents && item->isTag()) 0250 || (showOtherEvents && item->isOther())); 0251 visible = visible && (!filterByAuthor || author == item->text(HistoryItem::Author)) 0252 && (!filterByFile || item->text(HistoryItem::File).contains(fileMatcher)) && (!filterByPath || item->text(HistoryItem::Path).contains(pathMatcher)); 0253 0254 item->setHidden(!visible); 0255 } 0256 } 0257 0258 void HistoryDialog::toggled(bool b) 0259 { 0260 QLineEdit *edit = 0; 0261 0262 if (sender() == onlyuser_box) 0263 edit = user_edit; 0264 else if (sender() == onlyfilenames_box) 0265 edit = filename_edit; 0266 else if (sender() == onlydirnames_box) 0267 edit = dirname_edit; 0268 0269 if (!edit) 0270 return; 0271 0272 edit->setEnabled(b); 0273 if (b) 0274 edit->setFocus(); 0275 } 0276 0277 bool HistoryDialog::parseHistory(OrgKdeCervisia5CvsserviceCvsserviceInterface *cvsService) 0278 { 0279 setWindowTitle(i18n("CVS History")); 0280 0281 QDBusReply<QDBusObjectPath> job = cvsService->history(); 0282 if (!job.isValid()) 0283 return false; 0284 0285 ProgressDialog dlg(this, "History", cvsService->service(), job, "history", i18n("CVS History")); 0286 if (!dlg.execute()) 0287 return false; 0288 0289 QString line; 0290 while (dlg.getLine(line)) { 0291 const QStringList list(splitLine(line)); 0292 const int listSize(list.size()); 0293 if (listSize < 6) 0294 continue; 0295 0296 QString cmd = list[0]; 0297 if (cmd.length() != 1) 0298 continue; 0299 0300 int ncol; 0301 int cmd_code = cmd[0].toLatin1(); 0302 switch (cmd_code) { 0303 case 'O': 0304 case 'F': 0305 case 'E': 0306 ncol = 8; 0307 break; 0308 default: 0309 ncol = 10; 0310 break; 0311 } 0312 0313 if (ncol != (int)list.count()) 0314 continue; 0315 0316 QString event; 0317 switch (cmd_code) { 0318 case 'O': 0319 event = i18n("Checkout "); 0320 break; 0321 case 'T': 0322 event = i18n("Tag "); 0323 break; 0324 case 'F': 0325 event = i18n("Release "); 0326 break; 0327 case 'W': 0328 event = i18n("Update, Deleted "); 0329 break; 0330 case 'U': 0331 event = i18n("Update, Copied "); 0332 break; 0333 case 'G': 0334 event = i18n("Update, Merged "); 0335 break; 0336 case 'C': 0337 event = i18n("Update, Conflict "); 0338 break; 0339 case 'P': 0340 event = i18n("Update, Patched "); 0341 break; 0342 case 'M': 0343 event = i18n("Commit, Modified "); 0344 break; 0345 case 'A': 0346 event = i18n("Commit, Added "); 0347 break; 0348 case 'R': 0349 event = i18n("Commit, Removed "); 0350 break; 0351 default: 0352 event = i18n("Unknown "); 0353 } 0354 0355 const QDateTime date(parseDate(list[1], list[2], list[3])); 0356 0357 auto item = new HistoryItem(listview, date); 0358 item->setText(HistoryItem::Event, event); 0359 item->setText(HistoryItem::Author, list[4]); 0360 if (ncol == 10) { 0361 item->setText(HistoryItem::Revision, list[5]); 0362 if (listSize >= 8) { 0363 item->setText(HistoryItem::File, list[6]); 0364 item->setText(HistoryItem::Path, list[7]); 0365 } 0366 } else { 0367 item->setText(HistoryItem::Path, list[5]); 0368 } 0369 } 0370 0371 return true; 0372 } 0373 0374 // Local Variables: 0375 // c-basic-offset: 4 0376 // End: