Warning, file /sdk/cervisia/progressdialog.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 <bernd@mail.berlios.de> 0003 * Copyright (c) 2002-2004 Christian Loose <christian.loose@kdemail.net> 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 "progressdialog.h" 0021 0022 #include <QApplication> 0023 #include <QDialogButtonBox> 0024 #include <QEventLoop> 0025 #include <QHBoxLayout> 0026 #include <QLabel> 0027 #include <QPlainTextEdit> 0028 #include <QProgressBar> 0029 #include <QString> 0030 #include <QStringList> 0031 #include <QTimer> 0032 #include <QVBoxLayout> 0033 0034 #include "cervisiasettings.h" 0035 #include "debug.h" 0036 #include <cvsjobinterface.h> 0037 0038 //--------------------------------------------------------------------- 0039 0040 struct ProgressDialog::Private { 0041 bool isCancelled; 0042 bool isShown; 0043 bool hasError; 0044 bool isDiff; 0045 0046 OrgKdeCervisia5CvsserviceCvsjobInterface *cvsJob; 0047 QString jobPath; 0048 QString buffer; 0049 QString errorId1, errorId2; 0050 QStringList output; 0051 QEventLoop eventLoop; 0052 0053 QTimer *timer; 0054 QProgressBar *busy; 0055 QPlainTextEdit *resultbox; 0056 }; 0057 0058 //--------------------------------------------------------------------- 0059 0060 ProgressDialog::ProgressDialog(QWidget *parent, 0061 const QString &heading, 0062 const QString &cvsServiceNameService, 0063 const QDBusReply<QDBusObjectPath> &jobPath, 0064 const QString &errorIndicator, 0065 const QString &caption) 0066 : QDialog(parent) 0067 , d(new Private) 0068 { 0069 setWindowTitle(caption); 0070 setModal(true); 0071 0072 setupGui(heading); 0073 0074 d->isCancelled = false; 0075 d->isShown = false; 0076 d->hasError = false; 0077 d->isDiff = heading == QLatin1String("Diff"); // cvs returns error status when there is a difference 0078 0079 QDBusObjectPath path = jobPath; 0080 d->jobPath = path.path(); 0081 d->cvsJob = new OrgKdeCervisia5CvsserviceCvsjobInterface(cvsServiceNameService, path.path(), QDBusConnection::sessionBus(), this); 0082 0083 qCDebug(log_cervisia) << "cvsServiceNameService:" << cvsServiceNameService << "CvsjobInterface" << path.path() << "valid:" << d->cvsJob->isValid(); 0084 0085 d->errorId1 = "cvs " + errorIndicator + ':'; 0086 d->errorId2 = "cvs [" + errorIndicator + " aborted]:"; 0087 } 0088 0089 //--------------------------------------------------------------------- 0090 0091 ProgressDialog::~ProgressDialog() 0092 { 0093 delete d->cvsJob; 0094 delete d; 0095 } 0096 0097 //--------------------------------------------------------------------- 0098 0099 void ProgressDialog::setupGui(const QString &heading) 0100 { 0101 auto mainLayout = new QVBoxLayout(this); 0102 0103 auto textLabel = new QLabel(heading); 0104 mainLayout->addWidget(textLabel); 0105 0106 d->resultbox = new QPlainTextEdit; 0107 d->resultbox->setReadOnly(true); 0108 QFontMetrics fm(d->resultbox->fontMetrics()); 0109 d->resultbox->setMinimumSize(fm.width("0") * 70, fm.lineSpacing() * 8); 0110 mainLayout->addWidget(d->resultbox); 0111 0112 auto hbox = new QHBoxLayout; 0113 0114 d->busy = new QProgressBar; 0115 d->busy->setMinimum(0); 0116 d->busy->setMaximum(0); // min == max => busy indicator 0117 hbox->addWidget(d->busy); 0118 d->busy->hide(); 0119 0120 auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel); 0121 connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); 0122 hbox->addWidget(buttonBox); 0123 0124 mainLayout->addLayout(hbox); 0125 } 0126 0127 //--------------------------------------------------------------------- 0128 0129 bool ProgressDialog::execute() 0130 { 0131 // get command line and display it 0132 QString cmdLine = d->cvsJob->cvsCommand(); 0133 d->resultbox->insertPlainText(cmdLine); 0134 qCDebug(log_cervisia) << "cmdLine:" << cmdLine; 0135 0136 QDBusConnection::sessionBus().connect(QString(), d->jobPath, "org.kde.cervisia5.cvsservice.cvsjob", "jobExited", this, SLOT(slotJobExited(bool, int))); 0137 0138 QDBusConnection::sessionBus() 0139 .connect(QString(), d->jobPath, "org.kde.cervisia5.cvsservice.cvsjob", "receivedStdout", this, SLOT(slotReceivedOutputNonGui(QString))); 0140 0141 QDBusConnection::sessionBus() 0142 .connect(QString(), d->jobPath, "org.kde.cervisia5.cvsservice.cvsjob", "receivedStderr", this, SLOT(slotReceivedOutputNonGui(QString))); 0143 0144 // we wait for 4 seconds (or the timeout set by the user) before we 0145 // force the dialog to show up 0146 d->timer = new QTimer(this); 0147 connect(d->timer, SIGNAL(timeout()), this, SLOT(slotTimeoutOccurred())); 0148 d->timer->setSingleShot(true); 0149 d->timer->start(CervisiaSettings::timeout()); 0150 0151 bool started = d->cvsJob->execute(); 0152 if (!started) 0153 return false; 0154 0155 QApplication::setOverrideCursor(Qt::WaitCursor); 0156 0157 d->eventLoop.exec(); 0158 0159 if (QApplication::overrideCursor()) 0160 QApplication::restoreOverrideCursor(); 0161 0162 return !d->isCancelled; 0163 } 0164 0165 //--------------------------------------------------------------------- 0166 0167 bool ProgressDialog::getLine(QString &line) 0168 { 0169 if (d->output.isEmpty()) 0170 return false; 0171 0172 line = d->output.first(); 0173 d->output.removeFirst(); 0174 0175 return true; 0176 } 0177 0178 //--------------------------------------------------------------------- 0179 0180 QStringList ProgressDialog::getOutput() const 0181 { 0182 return d->output; 0183 } 0184 0185 //--------------------------------------------------------------------- 0186 0187 void ProgressDialog::slotReceivedOutputNonGui(QString buffer) 0188 { 0189 qCDebug(log_cervisia) << buffer; 0190 0191 d->buffer += buffer; 0192 0193 processOutput(); 0194 if (d->hasError) { 0195 stopNonGuiPart(); 0196 startGuiPart(); 0197 } 0198 } 0199 0200 //--------------------------------------------------------------------- 0201 0202 void ProgressDialog::slotReceivedOutput(QString buffer) 0203 { 0204 qCDebug(log_cervisia) << buffer; 0205 d->buffer += buffer; 0206 processOutput(); 0207 } 0208 0209 //--------------------------------------------------------------------- 0210 0211 void ProgressDialog::slotJobExited(bool normalExit, int status) 0212 { 0213 Q_UNUSED(normalExit) 0214 0215 if (!d->isShown) 0216 stopNonGuiPart(); 0217 0218 d->busy->hide(); 0219 0220 if (!d->buffer.isEmpty()) { 0221 d->buffer += '\n'; 0222 processOutput(); 0223 } 0224 0225 if ((status != 0) && !d->isDiff) // cvs command exited with error -> show error text 0226 { 0227 QString line; 0228 while (getLine(line)) { 0229 d->resultbox->insertPlainText(QLatin1String("\n")); 0230 d->resultbox->insertPlainText(line); 0231 } 0232 startGuiPart(); 0233 d->busy->hide(); 0234 return; 0235 } 0236 0237 // Close the dialog automatically if there are no 0238 // error messages or the process has been aborted 0239 // 'by hand' (e.g. by clicking the cancel button) 0240 if (!d->hasError || d->isCancelled) 0241 d->eventLoop.exit(); 0242 } 0243 0244 //--------------------------------------------------------------------- 0245 0246 void ProgressDialog::reject() 0247 { 0248 d->isCancelled = true; 0249 0250 bool isRunning = d->cvsJob->isRunning(); 0251 if (isRunning) 0252 d->cvsJob->cancel(); 0253 else 0254 d->eventLoop.exit(); 0255 0256 QDialog::reject(); 0257 } 0258 0259 //--------------------------------------------------------------------- 0260 0261 void ProgressDialog::slotTimeoutOccurred() 0262 { 0263 stopNonGuiPart(); 0264 startGuiPart(); 0265 } 0266 0267 //--------------------------------------------------------------------- 0268 0269 void ProgressDialog::stopNonGuiPart() 0270 { 0271 d->timer->stop(); 0272 0273 QDBusConnection::sessionBus() 0274 .disconnect(QString(), d->jobPath, "org.kde.cervisia5.cvsservice.cvsjob", "receivedStdout", this, SLOT(slotReceivedOutputNonGui(QString))); 0275 0276 QDBusConnection::sessionBus() 0277 .disconnect(QString(), d->jobPath, "org.kde.cervisia5.cvsservice.cvsjob", "receivedStderr", this, SLOT(slotReceivedOutputNonGui(QString))); 0278 } 0279 0280 //--------------------------------------------------------------------- 0281 0282 void ProgressDialog::startGuiPart() 0283 { 0284 QDBusConnection::sessionBus() 0285 .connect(QString(), d->jobPath, "org.kde.cervisia5.cvsservice.cvsjob", "receivedStdout", this, SLOT(slotReceivedOutput(QString))); 0286 0287 QDBusConnection::sessionBus() 0288 .connect(QString(), d->jobPath, "org.kde.cervisia5.cvsservice.cvsjob", "receivedStderr", this, SLOT(slotReceivedOutput(QString))); 0289 0290 show(); 0291 d->isShown = true; 0292 0293 d->busy->show(); 0294 QApplication::restoreOverrideCursor(); 0295 } 0296 0297 //--------------------------------------------------------------------- 0298 0299 void ProgressDialog::processOutput() 0300 { 0301 int pos; 0302 while ((pos = d->buffer.indexOf('\n')) != -1) { 0303 QString item = d->buffer.left(pos); 0304 if (item.startsWith(d->errorId1) || item.startsWith(d->errorId2) || item.startsWith(QLatin1String("cvs [server aborted]:"))) { 0305 d->hasError = true; 0306 d->resultbox->insertPlainText(QLatin1String("\n")); 0307 d->resultbox->insertPlainText(item); 0308 } else if (item.startsWith(QLatin1String("cvs server:"))) { 0309 d->resultbox->insertPlainText(QLatin1String("\n")); 0310 d->resultbox->insertPlainText(item); 0311 } else 0312 d->output.append(item); 0313 0314 // remove item from buffer 0315 d->buffer.remove(0, pos + 1); 0316 } 0317 } 0318 0319 //---------------------------------------------------------------------