File indexing completed on 2024-04-21 05:41:03
0001 /* 0002 SPDX-FileCopyrightText: 2011 Vishesh Yadav <vishesh3y@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "syncdialogbase.h" 0008 #include "hgconfig.h" 0009 #include "pathselector.h" 0010 #include "fileviewhgpluginsettings.h" 0011 0012 #include <QApplication> 0013 #include <QGridLayout> 0014 #include <QHBoxLayout> 0015 #include <QVBoxLayout> 0016 #include <QStringList> 0017 #include <QTextCodec> 0018 #include <QHeaderView> 0019 #include <QLabel> 0020 #include <QCheckBox> 0021 #include <QGroupBox> 0022 #include <QProgressBar> 0023 #include <KTextEdit> 0024 #include <KLocalizedString> 0025 #include <KMessageBox> 0026 0027 HgSyncBaseDialog::HgSyncBaseDialog(DialogType dialogType, QWidget *parent): 0028 DialogBase(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, parent), 0029 m_haveChanges(false), 0030 m_terminated(false), 0031 m_dialogType(dialogType) 0032 { 0033 m_hgw = HgWrapper::instance(); 0034 } 0035 0036 void HgSyncBaseDialog::setup() 0037 { 0038 createChangesGroup(); 0039 readBigSize(); 0040 setupUI(); 0041 0042 connect(m_changesButton, &QAbstractButton::clicked, 0043 this, &HgSyncBaseDialog::slotGetChanges); 0044 connect(&m_process, &QProcess::stateChanged, 0045 this, &HgSyncBaseDialog::slotUpdateBusy); 0046 connect(&m_main_process, &QProcess::stateChanged, 0047 this, &HgSyncBaseDialog::slotUpdateBusy); 0048 connect(&m_main_process, &QProcess::finished, 0049 this, &HgSyncBaseDialog::slotOperationComplete); 0050 connect(&m_main_process, &QProcess::errorOccurred, 0051 this, &HgSyncBaseDialog::slotOperationError); 0052 connect(&m_process, &QProcess::errorOccurred, 0053 this, &HgSyncBaseDialog::slotOperationError); 0054 connect(&m_process, &QProcess::finished, 0055 this, &HgSyncBaseDialog::slotChangesProcessComplete); 0056 connect(this, &QDialog::finished, this, &HgSyncBaseDialog::slotWriteBigSize); 0057 } 0058 0059 void HgSyncBaseDialog::createOptionGroup() 0060 { 0061 setOptions(); 0062 QVBoxLayout *layout = new QVBoxLayout; 0063 0064 for (QCheckBox *cb : std::as_const(m_options)) { 0065 layout->addWidget(cb); 0066 } 0067 0068 m_optionGroup = new QGroupBox(this); 0069 m_optionGroup->setLayout(layout); 0070 m_optionGroup->setVisible(false); 0071 } 0072 0073 void HgSyncBaseDialog::setupUI() 0074 { 0075 // top url bar 0076 m_pathSelector = new HgPathSelector; 0077 0078 // changes button 0079 //FIXME not very good idea. Bad HACK 0080 if (m_dialogType == PullDialog) { 0081 m_changesButton = new QPushButton(i18nc("@label:button", 0082 "Show Incoming Changes")); 0083 } 0084 else { 0085 m_changesButton = new QPushButton(i18nc("@label:button", 0086 "Show Outgoing Changes")); 0087 } 0088 m_changesButton->setSizePolicy(QSizePolicy::Fixed, 0089 QSizePolicy::Fixed); 0090 m_changesButton->setCheckable(true); 0091 0092 // dialog's main widget 0093 QWidget *widget = new QWidget(this); 0094 QVBoxLayout *lay = new QVBoxLayout; 0095 lay->addWidget(m_pathSelector); 0096 0097 // changes 0098 m_changesGroup->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 0099 lay->addWidget(m_changesGroup); 0100 0101 // bottom bar 0102 QHBoxLayout *bottomLayout = new QHBoxLayout; 0103 m_statusProg = new QProgressBar; 0104 m_statusProg->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0105 bottomLayout->addWidget(m_changesButton, Qt::AlignLeft); 0106 bottomLayout->addStretch(); 0107 bottomLayout->addWidget(m_statusProg); 0108 0109 // 0110 lay->addLayout(bottomLayout); 0111 widget->setLayout(lay); 0112 0113 createOptionGroup(); 0114 0115 QVBoxLayout *mainLayout = new QVBoxLayout; 0116 mainLayout->addWidget(widget); 0117 mainLayout->addWidget(m_optionGroup); 0118 0119 // bottom button box with OK/Cancel and Options buttons 0120 okButton()->setText(m_dialogType == PullDialog ? i18nc("@action:button", "Pull") : i18nc("@action:button", "Push")); 0121 okButton()->setIcon(QIcon::fromTheme( 0122 m_dialogType == PullDialog ? QStringLiteral("vcs-pull") : QStringLiteral("vcs-push"))); 0123 m_optionsButton = new QPushButton(buttonBox()); 0124 m_optionsButton->setIcon(QIcon::fromTheme(QStringLiteral("help-about"))); 0125 switchOptionsButton(true); 0126 buttonBox()->addButton(m_optionsButton, QDialogButtonBox::ResetRole); 0127 layout()->insertLayout(0, mainLayout); 0128 0129 connect(m_optionsButton, &QAbstractButton::clicked, this, &HgSyncBaseDialog::slotOptionsButtonClick); 0130 } 0131 0132 void HgSyncBaseDialog::slotGetChanges() 0133 { 0134 if (m_haveChanges) { 0135 m_changesGroup->setVisible(!m_changesGroup->isVisible()); 0136 m_changesButton->setChecked(m_changesGroup->isVisible()); 0137 if (m_changesGroup->isVisible()) { 0138 loadBigSize(); 0139 } 0140 else { 0141 loadSmallSize(); 0142 } 0143 return; 0144 } 0145 if (m_process.state() == QProcess::Running) { 0146 return; 0147 } 0148 0149 QStringList args; 0150 getHgChangesArguments(args); 0151 m_process.setWorkingDirectory(m_hgw->getBaseDir()); 0152 m_process.start(QLatin1String("hg"), args); 0153 } 0154 0155 0156 void HgSyncBaseDialog::slotChangesProcessComplete(int exitCode, QProcess::ExitStatus status) 0157 { 0158 0159 if (exitCode != 0 || status != QProcess::NormalExit) { 0160 QString message = QTextCodec::codecForLocale()->toUnicode(m_process.readAllStandardError()); 0161 if (message.isEmpty()) { 0162 message = i18nc("@message", "No changes found!"); 0163 } 0164 KMessageBox::error(this, message); 0165 return; 0166 } 0167 0168 char buffer[512]; 0169 0170 /** 0171 * unwantedRead boolean to ensure that unwanted information messages 0172 * by mercurial are filtered out. 0173 * eg. Comparing with /path/to/repository 0174 * Searching for changes 0175 */ 0176 bool unwantedRead = false; 0177 0178 /** 0179 * hasChanges boolean checks whether there are any changes to be sent 0180 * or received and invoke noChangesMessage() if its false 0181 */ 0182 bool hasChanges = false; 0183 0184 while (m_process.readLine(buffer, sizeof(buffer)) > 0) { 0185 QString line(QTextCodec::codecForLocale()->toUnicode(buffer)); 0186 if (unwantedRead ) { 0187 line.remove(QLatin1String("Commit: ")); 0188 parseUpdateChanges(line.trimmed()); 0189 hasChanges = true;; 0190 } 0191 else if (line.startsWith(QLatin1String("Commit: "))) { 0192 unwantedRead = true; 0193 line.remove(QLatin1String("Commit: ")); 0194 parseUpdateChanges(line.trimmed()); 0195 hasChanges = true; 0196 } 0197 } 0198 0199 if (!hasChanges) { 0200 noChangesMessage(); 0201 } 0202 0203 m_changesGroup->setVisible(true); 0204 m_changesButton->setChecked(true); 0205 loadBigSize(); 0206 m_haveChanges = true; 0207 Q_EMIT changeListAvailable(); 0208 } 0209 0210 void HgSyncBaseDialog::slotChangesProcessError() 0211 { 0212 qDebug() << "Cant get changes"; 0213 KMessageBox::error(this, i18n("Error!")); 0214 } 0215 0216 void HgSyncBaseDialog::loadSmallSize() 0217 { 0218 m_bigSize = size(); 0219 resize(m_smallSize); 0220 adjustSize(); 0221 updateGeometry(); 0222 } 0223 0224 void HgSyncBaseDialog::loadBigSize() 0225 { 0226 m_smallSize = size(); 0227 resize(m_bigSize); 0228 } 0229 0230 void HgSyncBaseDialog::slotWriteBigSize() 0231 { 0232 if (m_changesGroup->isVisible()) { 0233 m_bigSize = size(); 0234 } 0235 writeBigSize(); 0236 } 0237 0238 void HgSyncBaseDialog::done(int r) 0239 { 0240 if (r == QDialog::Accepted) { 0241 if (m_main_process.state() == QProcess::Running || 0242 m_main_process.state() == QProcess::Starting) { 0243 qDebug() << "HgWrapper already busy"; 0244 return; 0245 } 0246 0247 QStringList args; 0248 QString command = (m_dialogType==PullDialog) ? QStringLiteral("pull") : QStringLiteral("push"); 0249 args << command; 0250 args << m_pathSelector->remote(); 0251 appendOptionArguments(args); 0252 0253 m_terminated = false; 0254 0255 m_main_process.setWorkingDirectory(m_hgw->getBaseDir()); 0256 m_main_process.start(QStringLiteral("hg"), args); 0257 } 0258 else { 0259 if (m_process.state() == QProcess::Running || 0260 m_process.state() == QProcess::Starting || 0261 m_main_process.state() == QProcess::Running || 0262 m_main_process.state() == QProcess::Starting) 0263 { 0264 if (m_process.state() == QProcess::Running || 0265 m_process.state() == QProcess::Starting) { 0266 m_process.terminate(); 0267 } 0268 if (m_main_process.state() == QProcess::Running || 0269 m_main_process.state() == QProcess::Starting) { 0270 qDebug() << "terminating pull/push process"; 0271 m_terminated = true; 0272 m_main_process.terminate(); 0273 } 0274 } 0275 else { 0276 QDialog::done(r); 0277 } 0278 } 0279 } 0280 0281 void HgSyncBaseDialog::slotOperationComplete(int exitCode, QProcess::ExitStatus status) 0282 { 0283 if (exitCode == 0 && status == QProcess::NormalExit) { 0284 QDialog::done(QDialog::Accepted); 0285 } 0286 else { 0287 if (!m_terminated) { 0288 KMessageBox::error(this, i18n("Error!")); 0289 } 0290 } 0291 } 0292 0293 void HgSyncBaseDialog::slotOperationError() 0294 { 0295 KMessageBox::error(this, i18n("Error!")); 0296 } 0297 0298 void HgSyncBaseDialog::slotUpdateBusy(QProcess::ProcessState state) 0299 { 0300 if (state == QProcess::Running || state == QProcess::Starting) { 0301 m_statusProg->setRange(0, 0); 0302 m_changesButton->setEnabled(false); 0303 m_changesButton->setChecked(true); 0304 okButton()->setDisabled(true); 0305 } 0306 else { 0307 m_statusProg->setRange(0, 100); 0308 m_changesButton->setEnabled(true); 0309 okButton()->setDisabled(false); 0310 } 0311 m_statusProg->repaint(); 0312 QApplication::processEvents(); 0313 } 0314 0315 void HgSyncBaseDialog::slotOptionsButtonClick() 0316 { 0317 if (m_optionsButton->text().contains(QLatin1String(">>"))) { 0318 switchOptionsButton(false); 0319 m_optionGroup->setVisible(true); 0320 } 0321 else { 0322 switchOptionsButton(true); 0323 m_optionGroup->setVisible(false); 0324 } 0325 } 0326 0327 void HgSyncBaseDialog::switchOptionsButton(bool switchOn) 0328 { 0329 m_optionsButton->setText(xi18nc("@action:button", "Options") + 0330 (switchOn ? QLatin1String(" >>") : QLatin1String(" <<"))); 0331 } 0332 0333 0334 0335 0336 #include "moc_syncdialogbase.cpp"