Warning, file /sdk/cervisia/checkoutdialog.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  *  Copyright (c) 2003-2007 Christian Loose <christian.loose@hamburg.de>
0005  *
0006  * This program is free software; you can redistribute it and/or modify
0007  * it under the terms of the GNU General Public License as published by
0008  * the Free Software Foundation; either version 2 of the License, or
0009  * (at your option) any later version.
0010  *
0011  * This program is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014  * GNU General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU General Public License
0017  * along with this program; if not, write to the Free Software
0018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
0019  */
0020 
0021 #include "checkoutdialog.h"
0022 
0023 // Qt
0024 #include <KComboBox>
0025 #include <QBoxLayout>
0026 #include <QCheckBox>
0027 #include <QDialogButtonBox>
0028 #include <QDir>
0029 #include <QFileDialog>
0030 #include <QGridLayout>
0031 #include <QHBoxLayout>
0032 #include <QLabel>
0033 #include <QLineEdit>
0034 #include <QPushButton>
0035 #include <QVBoxLayout>
0036 
0037 // KDE
0038 #include <KConfigGroup>
0039 #include <KHelpClient>
0040 #include <KLineEdit>
0041 #include <KLocalizedString>
0042 #include <kmessagebox.h>
0043 #include <kurlcompletion.h>
0044 
0045 #include "cervisiasettings.h"
0046 #include "cvsserviceinterface.h"
0047 #include "misc.h"
0048 #include "progressdialog.h"
0049 #include "repositories.h"
0050 
0051 using Cervisia::IsValidTag;
0052 
0053 CheckoutDialog::CheckoutDialog(KConfig &cfg, OrgKdeCervisia5CvsserviceCvsserviceInterface *service, ActionType action, QWidget *parent)
0054     : QDialog(parent)
0055     , act(action)
0056     , partConfig(cfg)
0057     , cvsService(service)
0058 {
0059     setWindowTitle((action == Checkout) ? i18n("CVS Checkout") : i18n("CVS Import"));
0060     setModal(true);
0061 
0062     auto mainLayout = new QVBoxLayout;
0063     setLayout(mainLayout);
0064 
0065     auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help);
0066     QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
0067     okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
0068     connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
0069     connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
0070     connect(buttonBox, &QDialogButtonBox::helpRequested, this, &CheckoutDialog::slotHelp);
0071 
0072     auto grid = new QGridLayout;
0073     mainLayout->addLayout(grid);
0074     grid->setColumnStretch(0, 1);
0075     grid->setColumnStretch(1, 20);
0076     for (int i = 0; i < ((action == Checkout) ? 4 : 10); ++i)
0077         grid->setRowStretch(i, 0);
0078 
0079     repo_combo = new KComboBox;
0080     repo_combo->setEditable(true);
0081     repo_combo->setFocus();
0082     // make sure combobox is smaller than the screen
0083     repo_combo->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
0084     grid->addWidget(repo_combo, 0, 1);
0085 
0086     auto repo_label = new QLabel(i18n("&Repository:"));
0087     repo_label->setBuddy(repo_combo);
0088     grid->addWidget(repo_label, 0, 0, Qt::AlignLeft | Qt::AlignVCenter);
0089 
0090     if (action == Import) {
0091         module_edit = new QLineEdit;
0092         module_edit->setClearButtonEnabled(true);
0093         grid->addWidget(module_edit, 1, 1);
0094         auto module_label = new QLabel(i18n("&Module:"));
0095         module_label->setBuddy(module_edit);
0096         grid->addWidget(module_label, 1, 0, Qt::AlignLeft | Qt::AlignVCenter);
0097     } else {
0098         module_combo = new KComboBox;
0099         module_combo->setEditable(true);
0100 
0101         auto module_button = new QPushButton(i18n("Fetch &List"));
0102         connect(module_button, SIGNAL(clicked()), this, SLOT(moduleButtonClicked()));
0103 
0104         QBoxLayout *module_layout = new QHBoxLayout();
0105         grid->addLayout(module_layout, 1, 1);
0106         module_layout->addWidget(module_combo, 10);
0107         module_layout->addWidget(module_button, 0, Qt::AlignVCenter);
0108 
0109         auto module_label = new QLabel(i18n("&Module:"));
0110         module_label->setBuddy(module_combo);
0111         grid->addWidget(module_label, 1, 0, Qt::AlignLeft | Qt::AlignVCenter);
0112 
0113         branchCombo = new KComboBox;
0114         branchCombo->setEditable(true);
0115 
0116         auto branchButton = new QPushButton(i18n("Fetch &List"));
0117         connect(branchButton, SIGNAL(clicked()), this, SLOT(branchButtonClicked()));
0118 
0119         QBoxLayout *branchLayout = new QHBoxLayout();
0120         grid->addLayout(branchLayout, 2, 1);
0121         branchLayout->addWidget(branchCombo, 10);
0122         branchLayout->addWidget(branchButton, 0, Qt::AlignVCenter);
0123 
0124         auto branch_label = new QLabel(i18n("&Branch tag:"));
0125         branch_label->setBuddy(branchCombo);
0126         grid->addWidget(branch_label, 2, 0, Qt::AlignLeft | Qt::AlignVCenter);
0127 
0128         connect(branchCombo, SIGNAL(editTextChanged(QString)), this, SLOT(branchTextChanged()));
0129 
0130         recursive_box = new QCheckBox(i18n("Re&cursive checkout"));
0131         grid->addWidget(recursive_box, 6, 0, 1, 2);
0132     }
0133 
0134     workdir_edit = new KLineEdit;
0135     workdir_edit->setClearButtonEnabled(true);
0136     workdir_edit->setText(QDir::homePath());
0137     workdir_edit->setMinimumWidth(fontMetrics().width('X') * 40);
0138 
0139     auto comp = new KUrlCompletion();
0140     workdir_edit->setCompletionObject(comp);
0141     workdir_edit->setAutoDeleteCompletionObject(true);
0142     connect(workdir_edit, SIGNAL(returnPressed(QString)), comp, SLOT(addItem(QString)));
0143 
0144     auto dir_button = new QPushButton("...");
0145     connect(dir_button, SIGNAL(clicked()), this, SLOT(dirButtonClicked()));
0146     dir_button->setFixedWidth(30);
0147 
0148     QBoxLayout *workdir_layout = new QHBoxLayout();
0149     grid->addLayout(workdir_layout, (action == Import) ? 2 : 3, 1);
0150     workdir_layout->addWidget(workdir_edit, 10);
0151     workdir_layout->addWidget(dir_button, 0, Qt::AlignVCenter);
0152 
0153     auto workdir_label = new QLabel(i18n("Working &folder:"));
0154     workdir_label->setBuddy(workdir_edit);
0155     grid->addWidget(workdir_label, (action == Import) ? 2 : 3, 0, Qt::AlignLeft | Qt::AlignVCenter);
0156 
0157     if (action == Import) {
0158         vendortag_edit = new QLineEdit;
0159         vendortag_edit->setClearButtonEnabled(true);
0160         grid->addWidget(vendortag_edit, 3, 1);
0161 
0162         auto vendortag_label = new QLabel(i18n("&Vendor tag:"));
0163         vendortag_label->setBuddy(vendortag_edit);
0164         grid->addWidget(vendortag_label, 3, 0, Qt::AlignLeft | Qt::AlignVCenter);
0165 
0166         releasetag_edit = new QLineEdit;
0167         releasetag_edit->setClearButtonEnabled(true);
0168         grid->addWidget(releasetag_edit, 4, 1);
0169 
0170         auto releasetag_label = new QLabel(i18n("&Release tag:"));
0171         releasetag_label->setBuddy(releasetag_edit);
0172         grid->addWidget(releasetag_label, 4, 0, Qt::AlignLeft | Qt::AlignVCenter);
0173 
0174         ignore_edit = new QLineEdit;
0175         ignore_edit->setClearButtonEnabled(true);
0176         grid->addWidget(ignore_edit, 5, 1);
0177 
0178         auto ignore_label = new QLabel(i18n("&Ignore files:"));
0179         ignore_label->setBuddy(ignore_edit);
0180         grid->addWidget(ignore_label, 5, 0, Qt::AlignLeft | Qt::AlignVCenter);
0181 
0182         comment_edit = new QLineEdit;
0183         comment_edit->setClearButtonEnabled(true);
0184         grid->addWidget(comment_edit, 6, 1);
0185 
0186         auto comment_label = new QLabel(i18n("&Comment:"));
0187         comment_label->setBuddy(comment_edit);
0188         grid->addWidget(comment_label, 6, 0, Qt::AlignLeft | Qt::AlignVCenter);
0189 
0190         binary_box = new QCheckBox(i18n("Import as &binaries"));
0191         grid->addWidget(binary_box, 7, 0, 1, 2);
0192 
0193         m_useModificationTimeBox = new QCheckBox(i18n("Use file's modification time as time of import"));
0194         grid->addWidget(m_useModificationTimeBox, 8, 0, 1, 2);
0195     } else {
0196         alias_edit = new QLineEdit;
0197         alias_edit->setClearButtonEnabled(true);
0198         grid->addWidget(alias_edit, 4, 1);
0199 
0200         auto alias_label = new QLabel(i18n("Chec&k out as:"));
0201         alias_label->setBuddy(alias_edit);
0202         grid->addWidget(alias_label, 4, 0, Qt::AlignLeft | Qt::AlignVCenter);
0203 
0204         export_box = new QCheckBox(i18n("Ex&port only"));
0205         grid->addWidget(export_box, 5, 0, 1, 2);
0206     }
0207 
0208     mainLayout->addWidget(buttonBox);
0209 
0210     QStringList list1 = Repositories::readCvsPassFile();
0211     QStringList::ConstIterator it1;
0212     for (it1 = list1.constBegin(); it1 != list1.constEnd(); ++it1)
0213         repo_combo->addItem(*it1);
0214 
0215     QStringList list2 = Repositories::readConfigFile();
0216     QStringList::ConstIterator it2;
0217     for (it2 = list2.constBegin(); it2 != list2.constEnd(); ++it2)
0218         if (!list1.contains(*it2))
0219             repo_combo->addItem(*it2);
0220 
0221     helpTopic = (act == Import) ? "importing" : "checkingout";
0222 
0223     restoreUserInput();
0224     connect(okButton, SIGNAL(clicked()), this, SLOT(slotOk()));
0225 }
0226 
0227 void CheckoutDialog::slotHelp()
0228 {
0229     KHelpClient::invokeHelp(helpTopic);
0230 }
0231 
0232 QString CheckoutDialog::workingDirectory() const
0233 {
0234     return workdir_edit->text();
0235 }
0236 
0237 QString CheckoutDialog::repository() const
0238 {
0239     return repo_combo->currentText();
0240 }
0241 
0242 QString CheckoutDialog::module() const
0243 {
0244     return act == Import ? module_edit->text() : module_combo->currentText();
0245 }
0246 
0247 QString CheckoutDialog::branch() const
0248 {
0249     return branchCombo->currentText();
0250 }
0251 
0252 QString CheckoutDialog::vendorTag() const
0253 {
0254     return vendortag_edit->text();
0255 }
0256 
0257 QString CheckoutDialog::releaseTag() const
0258 {
0259     return releasetag_edit->text();
0260 }
0261 
0262 QString CheckoutDialog::ignoreFiles() const
0263 {
0264     return ignore_edit->text();
0265 }
0266 
0267 QString CheckoutDialog::comment() const
0268 {
0269     return comment_edit->text();
0270 }
0271 
0272 QString CheckoutDialog::alias() const
0273 {
0274     return alias_edit->text();
0275 }
0276 
0277 bool CheckoutDialog::importBinary() const
0278 {
0279     return binary_box->isChecked();
0280 }
0281 
0282 bool CheckoutDialog::useModificationTime() const
0283 {
0284     return m_useModificationTimeBox->isChecked();
0285 }
0286 
0287 bool CheckoutDialog::exportOnly() const
0288 {
0289     if (export_box->isEnabled())
0290         return export_box->isChecked();
0291 
0292     return false;
0293 }
0294 
0295 bool CheckoutDialog::recursive() const
0296 {
0297     return recursive_box->isChecked();
0298 }
0299 
0300 void CheckoutDialog::slotOk()
0301 {
0302     QFileInfo fi(workingDirectory());
0303     if (!fi.exists() || !fi.isDir()) {
0304         KMessageBox::information(this, i18n("Please choose an existing working folder."));
0305         return;
0306     }
0307     if (module().isEmpty()) {
0308         KMessageBox::information(this, i18n("Please specify a module name."));
0309         return;
0310     }
0311 
0312     if (act == Import) {
0313         if (vendorTag().isEmpty() || releaseTag().isEmpty()) {
0314             KMessageBox::information(this, i18n("Please specify a vendor tag and a release tag."));
0315             return;
0316         }
0317         if (!IsValidTag(vendorTag()) || !IsValidTag(releaseTag())) {
0318             KMessageBox::information(this,
0319                                      i18n("Tags must start with a letter and may contain\n"
0320                                           "letters, digits and the characters '-' and '_'."));
0321             return;
0322         }
0323     } else {
0324         if (branch().isEmpty() && exportOnly()) {
0325             KMessageBox::information(this, i18n("A branch must be specified for export."));
0326             return;
0327         }
0328     }
0329 
0330     saveUserInput();
0331 
0332     QDialog::accept();
0333 }
0334 
0335 void CheckoutDialog::dirButtonClicked()
0336 {
0337     QString dir = QFileDialog::getExistingDirectory(0, QString(), workdir_edit->text());
0338     if (!dir.isEmpty())
0339         workdir_edit->setText(dir);
0340 }
0341 
0342 void CheckoutDialog::moduleButtonClicked()
0343 {
0344     QDBusReply<QDBusObjectPath> cvsJob = cvsService->moduleList(repository());
0345     if (!cvsJob.isValid())
0346         return;
0347 
0348     ProgressDialog dlg(this, "Checkout", cvsService->service(), cvsJob, "checkout", i18n("CVS Checkout"));
0349     if (!dlg.execute())
0350         return;
0351 
0352     module_combo->clear();
0353     QString str;
0354     while (dlg.getLine(str)) {
0355         if (str.left(12) == "Unknown host")
0356             continue;
0357 
0358         int pos = str.indexOf(' ');
0359         if (pos == -1)
0360             pos = str.indexOf('\t');
0361         if (pos == -1)
0362             pos = str.length();
0363         QString module(str.left(pos).trimmed());
0364         if (!module.isEmpty())
0365             module_combo->addItem(module);
0366     }
0367 }
0368 
0369 void CheckoutDialog::branchButtonClicked()
0370 {
0371     QStringList branchTagList;
0372 
0373     if (repository().isEmpty()) {
0374         KMessageBox::information(this, i18n("Please specify a repository."));
0375         return;
0376     }
0377 
0378     if (module().isEmpty()) {
0379         KMessageBox::information(this, i18n("Please specify a module name."));
0380         return;
0381     }
0382 
0383     QDBusReply<QDBusObjectPath> cvsJob = cvsService->rlog(repository(), module(), false /*recursive*/);
0384     if (!cvsJob.isValid())
0385         return;
0386 
0387     ProgressDialog dlg(this, "Remote Log", cvsService->service(), cvsJob, QString(), i18n("CVS Remote Log"));
0388     if (!dlg.execute())
0389         return;
0390 
0391     QString line;
0392     while (dlg.getLine(line)) {
0393         int colonPos;
0394 
0395         if (line.isEmpty() || line[0] != '\t')
0396             continue;
0397         if ((colonPos = line.indexOf(':', 1)) < 0)
0398             continue;
0399 
0400         const QString tag = line.mid(1, colonPos - 1);
0401         if (!branchTagList.contains(tag))
0402             branchTagList.push_back(tag);
0403     }
0404 
0405     branchTagList.sort();
0406 
0407     branchCombo->clear();
0408     branchCombo->addItems(branchTagList);
0409 }
0410 
0411 void CheckoutDialog::restoreUserInput()
0412 {
0413     KConfigGroup cs(&partConfig, "CheckoutDialog");
0414 
0415     repo_combo->setEditText(CervisiaSettings::repository());
0416     workdir_edit->setText(CervisiaSettings::workingFolder());
0417 
0418     if (act == Import) {
0419         module_edit->setText(CervisiaSettings::module());
0420         vendortag_edit->setText(cs.readEntry("Vendor tag"));
0421         releasetag_edit->setText(cs.readEntry("Release tag"));
0422         ignore_edit->setText(cs.readEntry("Ignore files"));
0423         binary_box->setChecked(cs.readEntry("Import binary", false));
0424     } else {
0425         module_combo->setEditText(CervisiaSettings::module());
0426         branchCombo->setEditText(cs.readEntry("Branch"));
0427         alias_edit->setText(cs.readEntry("Alias"));
0428         export_box->setChecked(cs.readEntry("ExportOnly", false));
0429         recursive_box->setChecked(true);
0430     }
0431 }
0432 
0433 void CheckoutDialog::saveUserInput()
0434 {
0435     KConfigGroup cs(&partConfig, "CheckoutDialog");
0436 
0437     CervisiaSettings::setRepository(repository());
0438     CervisiaSettings::setModule(module());
0439     CervisiaSettings::setWorkingFolder(workingDirectory());
0440 
0441     CervisiaSettings::self()->save();
0442 
0443     if (act == Import) {
0444         cs.writeEntry("Vendor tag", vendorTag());
0445         cs.writeEntry("Release tag", releaseTag());
0446         cs.writeEntry("Ignore files", ignoreFiles());
0447         cs.writeEntry("Import binary", importBinary());
0448     } else {
0449         cs.writeEntry("Branch", branch());
0450         cs.writeEntry("Alias", alias());
0451         cs.writeEntry("ExportOnly", exportOnly());
0452     }
0453 }
0454 
0455 void CheckoutDialog::branchTextChanged()
0456 {
0457     if (branch().isEmpty()) {
0458         export_box->setEnabled(false);
0459         export_box->setChecked(false);
0460     } else {
0461         export_box->setEnabled(true);
0462     }
0463 }
0464 
0465 // Local Variables:
0466 // c-basic-offset: 4
0467 // End: