Warning, file /sdk/cervisia/repositorydialog.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) 2002-2004 Christian Loose <christian.loose@kdemail.net>
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 "repositorydialog.h"
0022 #include "debug.h"
0023 
0024 #include <QDialogButtonBox>
0025 #include <QHBoxLayout>
0026 #include <QHeaderView>
0027 #include <QPushButton>
0028 #include <QTreeWidget>
0029 #include <QVBoxLayout>
0030 
0031 #include <KConfigGroup>
0032 #include <KHelpClient>
0033 #include <KLocalizedString>
0034 #include <kconfig.h>
0035 #include <kconfiggroup.h>
0036 #include <kmessagebox.h>
0037 
0038 #include "addrepositorydialog.h"
0039 #include "cvsloginjobinterface.h"
0040 #include "cvsserviceinterface.h"
0041 #include "misc.h"
0042 #include "progressdialog.h"
0043 #include "repositories.h"
0044 
0045 class RepositoryListItem : public QTreeWidgetItem
0046 {
0047 public:
0048     RepositoryListItem(QTreeWidget *parent, const QString &repo, bool loggedin);
0049 
0050     void setRsh(const QString &rsh);
0051     void setServer(const QString &server)
0052     {
0053         m_server = server;
0054     }
0055     void setCompression(int compression);
0056     void setIsLoggedIn(bool isLoggedIn);
0057     void setRetrieveCvsignore(bool retrieve)
0058     {
0059         m_retrieveCvsignore = retrieve;
0060     }
0061 
0062     QString repository() const
0063     {
0064         return text(0);
0065     }
0066     QString rsh() const
0067     {
0068         QString str = text(1);
0069         return (str.startsWith(QLatin1String("ext (")) ? str.mid(5, str.length() - 6) : QString());
0070     }
0071     QString server() const
0072     {
0073         return m_server;
0074     }
0075     int compression() const
0076     {
0077         bool ok;
0078         int n = text(2).toInt(&ok);
0079         return ok ? n : -1;
0080     }
0081     bool isLoggedIn() const
0082     {
0083         return m_isLoggedIn;
0084     }
0085     bool retrieveCvsignore() const
0086     {
0087         return m_retrieveCvsignore;
0088     }
0089 
0090 private:
0091     void changeLoginStatusColumn();
0092 
0093 private:
0094     QString m_server;
0095     bool m_isLoggedIn;
0096     bool m_retrieveCvsignore;
0097 };
0098 
0099 static bool LoginNeeded(const QString &repository)
0100 {
0101     return repository.startsWith(QLatin1String(":pserver:")) || repository.startsWith(QLatin1String(":sspi:"));
0102 }
0103 
0104 RepositoryListItem::RepositoryListItem(QTreeWidget *parent, const QString &repo, bool loggedin)
0105     : QTreeWidgetItem(parent)
0106     , m_isLoggedIn(loggedin)
0107 {
0108     qCDebug(log_cervisia) << "repo=" << repo;
0109     setText(0, repo);
0110 
0111     changeLoginStatusColumn();
0112 }
0113 
0114 void RepositoryListItem::setRsh(const QString &rsh)
0115 {
0116     QString repo = repository();
0117     QString method;
0118 
0119     if (repo.startsWith(QLatin1String(":pserver:")))
0120         method = "pserver";
0121     else if (repo.startsWith(QLatin1String(":sspi:")))
0122         method = "sspi";
0123     else if (repo.contains(':')) {
0124         method = "ext";
0125         if (!rsh.isEmpty()) {
0126             method += " (";
0127             method += rsh;
0128             method += ')';
0129         }
0130     } else
0131         method = "local";
0132 
0133     setText(1, method);
0134 }
0135 
0136 void RepositoryListItem::setCompression(int compression)
0137 {
0138     QString compressionStr = (compression >= 0) ? QString::number(compression) : i18n("Default");
0139 
0140     setText(2, compressionStr);
0141 }
0142 
0143 void RepositoryListItem::setIsLoggedIn(bool isLoggedIn)
0144 {
0145     m_isLoggedIn = isLoggedIn;
0146 
0147     changeLoginStatusColumn();
0148 }
0149 
0150 void RepositoryListItem::changeLoginStatusColumn()
0151 {
0152     QString loginStatus;
0153 
0154     if (LoginNeeded(repository()))
0155         loginStatus = m_isLoggedIn ? i18n("Logged in") : i18n("Not logged in");
0156     else
0157         loginStatus = i18n("No login required");
0158 
0159     setText(3, loginStatus);
0160 }
0161 
0162 RepositoryDialog::RepositoryDialog(KConfig &cfg,
0163                                    OrgKdeCervisia5CvsserviceCvsserviceInterface *cvsService,
0164                                    const QString &cvsServiceInterfaceName,
0165                                    QWidget *parent)
0166     : QDialog(parent)
0167     , m_partConfig(cfg)
0168     , m_cvsService(cvsService)
0169     , m_cvsServiceInterfaceName(cvsServiceInterfaceName)
0170 {
0171     setWindowTitle(i18n("Configure Access to Repositories"));
0172     setModal(true);
0173 
0174     auto mainLayout = new QVBoxLayout;
0175     setLayout(mainLayout);
0176 
0177     auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help);
0178     QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
0179     okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
0180     connect(okButton, SIGNAL(clicked()), this, SLOT(slotOk()));
0181     connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
0182 
0183     QBoxLayout *hbox = new QHBoxLayout;
0184     hbox->setContentsMargins(0, 0, 0, 0);
0185     mainLayout->addLayout(hbox);
0186 
0187     m_repoList = new QTreeWidget;
0188     hbox->addWidget(m_repoList, 10);
0189     m_repoList->setMinimumWidth(fontMetrics().width('0') * 60);
0190     m_repoList->setAllColumnsShowFocus(true);
0191     m_repoList->setRootIsDecorated(false);
0192     m_repoList->setHeaderLabels(QStringList() << i18n("Repository") << i18n("Method") << i18n("Compression") << i18n("Status"));
0193     m_repoList->setFocus();
0194 
0195     connect(m_repoList, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(slotDoubleClicked(QTreeWidgetItem *, int)));
0196     connect(m_repoList, SIGNAL(itemSelectionChanged()), this, SLOT(slotSelectionChanged()));
0197 
0198     auto actionbox = new QDialogButtonBox(Qt::Vertical);
0199     QPushButton *addbutton = actionbox->addButton(i18n("Add..."), QDialogButtonBox::ActionRole);
0200     m_modifyButton = actionbox->addButton(i18n("Modify..."), QDialogButtonBox::ActionRole);
0201     m_removeButton = actionbox->addButton(i18n("Remove"), QDialogButtonBox::ActionRole);
0202     m_loginButton = actionbox->addButton(i18n("Login..."), QDialogButtonBox::ActionRole);
0203     m_logoutButton = actionbox->addButton(i18n("Logout"), QDialogButtonBox::ActionRole);
0204     hbox->addWidget(actionbox, 0);
0205 
0206     m_loginButton->setEnabled(false);
0207     m_logoutButton->setEnabled(false);
0208 
0209     connect(addbutton, SIGNAL(clicked()), this, SLOT(slotAddClicked()));
0210     connect(m_modifyButton, SIGNAL(clicked()), this, SLOT(slotModifyClicked()));
0211     connect(m_removeButton, SIGNAL(clicked()), this, SLOT(slotRemoveClicked()));
0212     connect(m_loginButton, SIGNAL(clicked()), this, SLOT(slotLoginClicked()));
0213     connect(m_logoutButton, SIGNAL(clicked()), this, SLOT(slotLogoutClicked()));
0214 
0215     // open cvs DBUS service configuration file
0216     m_serviceConfig = new KConfig("cvsservicerc");
0217 
0218     readCvsPassFile();
0219     readConfigFile();
0220 
0221     if (QTreeWidgetItem *item = m_repoList->topLevelItem(0)) {
0222         m_repoList->setCurrentItem(item);
0223         item->setSelected(true);
0224     } else {
0225         // we have no item so disable modify and remove button
0226         slotSelectionChanged();
0227     }
0228 
0229     connect(buttonBox, &QDialogButtonBox::helpRequested, this, &RepositoryDialog::slotHelp);
0230 
0231     setAttribute(Qt::WA_DeleteOnClose, true);
0232 
0233     KConfigGroup cg(&m_partConfig, "RepositoryDialog");
0234     restoreGeometry(cg.readEntry<QByteArray>("geometry", QByteArray()));
0235 
0236     QByteArray state = cg.readEntry<QByteArray>("RepositoryListView", QByteArray());
0237     m_repoList->header()->restoreState(state);
0238 
0239     mainLayout->addWidget(buttonBox);
0240 }
0241 
0242 RepositoryDialog::~RepositoryDialog()
0243 {
0244     KConfigGroup cg(&m_partConfig, "RepositoryDialog");
0245     cg.writeEntry("geometry", saveGeometry());
0246 
0247     cg.writeEntry("RepositoryListView", m_repoList->header()->saveState());
0248 
0249     delete m_serviceConfig;
0250 }
0251 
0252 void RepositoryDialog::readCvsPassFile()
0253 {
0254     QStringList list = Repositories::readCvsPassFile();
0255     Q_FOREACH (const QString &it, list)
0256         (void)new RepositoryListItem(m_repoList, it, true);
0257 }
0258 
0259 void RepositoryDialog::readConfigFile()
0260 {
0261     QStringList list = Repositories::readConfigFile();
0262 
0263     // Sort out all list elements which are already in the list view
0264     for (int i = 0; i < m_repoList->topLevelItemCount(); i++)
0265         list.removeAll(m_repoList->topLevelItem(i)->text(0));
0266 
0267     Q_FOREACH (const QString &it, list)
0268         new RepositoryListItem(m_repoList, it, false);
0269 
0270     // Now look for the used methods
0271     for (int i = 0; i < m_repoList->topLevelItemCount(); i++) {
0272         auto ritem = static_cast<RepositoryListItem *>(m_repoList->topLevelItem(i));
0273 
0274         // read entries from cvs DBUS service configuration
0275         const KConfigGroup repoGroup = m_serviceConfig->group(QLatin1String("Repository-") + ritem->repository());
0276 
0277         qCDebug(log_cervisia) << "repository=" << ritem->repository();
0278 
0279         QString rsh = repoGroup.readEntry("rsh", QString());
0280         QString server = repoGroup.readEntry("cvs_server", QString());
0281         int compression = repoGroup.readEntry("Compression", -1);
0282         bool retrieveFile = repoGroup.readEntry("RetrieveCvsignore", false);
0283 
0284         ritem->setRsh(rsh);
0285         ritem->setServer(server);
0286         ritem->setCompression(compression);
0287         ritem->setRetrieveCvsignore(retrieveFile);
0288     }
0289 
0290     m_repoList->header()->resizeSections(QHeaderView::ResizeToContents);
0291 }
0292 
0293 void RepositoryDialog::slotHelp()
0294 {
0295     KHelpClient::invokeHelp(QLatin1String("accessing-repository"));
0296 }
0297 
0298 void RepositoryDialog::slotOk()
0299 {
0300     // Make list of repositories
0301     QStringList list;
0302     for (int i = 0; i < m_repoList->topLevelItemCount(); i++)
0303         list.append(m_repoList->topLevelItem(i)->text(0));
0304 
0305     KConfigGroup reposGroup = m_partConfig.group("Repositories");
0306     reposGroup.writeEntry("Repos", list);
0307 
0308     for (int i = 0; i < m_repoList->topLevelItemCount(); i++) {
0309         auto ritem = static_cast<RepositoryListItem *>(m_repoList->topLevelItem(i));
0310 
0311         // write entries to cvs DBUS service configuration
0312         writeRepositoryData(ritem);
0313     }
0314 
0315     // write to disk so other services can reparse the configuration
0316     m_serviceConfig->sync();
0317 
0318     QDialog::accept();
0319 }
0320 
0321 void RepositoryDialog::slotAddClicked()
0322 {
0323     AddRepositoryDialog dlg(m_partConfig, QString(), this);
0324     // default compression level
0325     dlg.setCompression(-1);
0326     if (dlg.exec()) {
0327         QString repo = Cervisia::NormalizeRepository(dlg.repository());
0328         QString rsh = dlg.rsh();
0329         QString server = dlg.server();
0330         int compression = dlg.compression();
0331         bool retrieveFile = dlg.retrieveCvsignoreFile();
0332 
0333         for (int i = 0; i < m_repoList->topLevelItemCount(); i++)
0334             if (m_repoList->topLevelItem(i)->text(0) == repo) {
0335                 KMessageBox::information(this, i18n("This repository is already known."));
0336                 return;
0337             }
0338 
0339         auto ritem = new RepositoryListItem(m_repoList, repo, false);
0340         ritem->setRsh(rsh);
0341         ritem->setCompression(compression);
0342         ritem->setRetrieveCvsignore(retrieveFile);
0343 
0344         // write entries to cvs DBUS service configuration
0345         writeRepositoryData(ritem);
0346 
0347         // write to disk so other services can reparse the configuration
0348         m_serviceConfig->sync();
0349     }
0350 }
0351 
0352 void RepositoryDialog::slotModifyClicked()
0353 {
0354     slotDoubleClicked(m_repoList->currentItem(), 0);
0355 }
0356 
0357 void RepositoryDialog::slotRemoveClicked()
0358 {
0359     // logout from pserver accounts so that they don't
0360     // get re-added because of the .cvspass file. (BR #51129)
0361     if (m_logoutButton->isEnabled())
0362         slotLogoutClicked();
0363 
0364     delete m_repoList->currentItem();
0365 }
0366 
0367 void RepositoryDialog::slotDoubleClicked(QTreeWidgetItem *item, int column)
0368 {
0369     Q_UNUSED(column)
0370 
0371     if (!item)
0372         return;
0373 
0374     auto ritem = static_cast<RepositoryListItem *>(item);
0375     QString repo = ritem->repository();
0376     QString rsh = ritem->rsh();
0377     QString server = ritem->server();
0378     int compression = ritem->compression();
0379     bool retrieveFile = ritem->retrieveCvsignore();
0380 
0381     AddRepositoryDialog dlg(m_partConfig, repo, this);
0382     dlg.setRepository(repo);
0383     dlg.setRsh(rsh);
0384     dlg.setServer(server);
0385     dlg.setCompression(compression);
0386     dlg.setRetrieveCvsignoreFile(retrieveFile);
0387     if (dlg.exec()) {
0388         ritem->setRsh(dlg.rsh());
0389         ritem->setServer(dlg.server());
0390         ritem->setCompression(dlg.compression());
0391         ritem->setRetrieveCvsignore(dlg.retrieveCvsignoreFile());
0392 
0393         // write entries to cvs DBUS service configuration
0394         writeRepositoryData(ritem);
0395 
0396         // write to disk so other services can reparse the configuration
0397         m_serviceConfig->sync();
0398     }
0399 }
0400 
0401 void RepositoryDialog::slotLoginClicked()
0402 {
0403     auto item = (RepositoryListItem *)m_repoList->currentItem();
0404     if (!item)
0405         return;
0406 
0407     qCDebug(log_cervisia) << "repo=" << item->repository();
0408 
0409     QDBusReply<QDBusObjectPath> job = m_cvsService->login(item->repository());
0410     if (!job.isValid())
0411         // TODO: error handling
0412         return;
0413     QDBusObjectPath jobPath = job;
0414     OrgKdeCervisia5CvsserviceCvsloginjobInterface cvsloginjobinterface(m_cvsServiceInterfaceName, jobPath.path(), QDBusConnection::sessionBus(), this);
0415     QDBusReply<bool> reply = cvsloginjobinterface.execute();
0416     bool success = false;
0417     if (reply.isValid())
0418         success = reply;
0419     if (!success) {
0420         QDBusReply<QStringList> ret = cvsloginjobinterface.output();
0421 
0422         QStringList output = ret;
0423         KMessageBox::detailedError(this, i18n("Login failed."), output.join("\n"));
0424         return;
0425     }
0426 
0427     item->setIsLoggedIn(true);
0428     slotSelectionChanged();
0429 }
0430 
0431 void RepositoryDialog::slotLogoutClicked()
0432 {
0433     auto item = (RepositoryListItem *)m_repoList->currentItem();
0434     if (!item)
0435         return;
0436 
0437     QDBusReply<QDBusObjectPath> job = m_cvsService->logout(item->repository());
0438     if (!job.isValid())
0439         // TODO: error handling
0440         return;
0441 
0442     ProgressDialog dlg(this, "Logout", m_cvsService->service(), job, "logout", i18n("CVS Logout"));
0443     if (!dlg.execute())
0444         return;
0445 
0446     item->setIsLoggedIn(false);
0447     slotSelectionChanged();
0448 }
0449 
0450 void RepositoryDialog::slotSelectionChanged()
0451 {
0452     // retrieve the selected item
0453     auto item = (RepositoryListItem *)m_repoList->currentItem();
0454 
0455     // is an item in the list view selected?
0456     bool isItemSelected = (item != 0);
0457     m_modifyButton->setEnabled(isItemSelected);
0458     m_removeButton->setEnabled(isItemSelected);
0459     m_loginButton->setEnabled(isItemSelected);
0460     m_logoutButton->setEnabled(isItemSelected);
0461 
0462     if (!isItemSelected)
0463         return;
0464 
0465     // is this a pserver repository?
0466     if (!LoginNeeded(item->repository())) {
0467         m_loginButton->setEnabled(false);
0468         m_logoutButton->setEnabled(false);
0469         return;
0470     }
0471 
0472     // are we logged in?
0473     bool isLoggedIn = item->isLoggedIn();
0474     m_loginButton->setEnabled(!isLoggedIn);
0475     m_logoutButton->setEnabled(isLoggedIn);
0476 }
0477 
0478 void RepositoryDialog::writeRepositoryData(RepositoryListItem *item)
0479 {
0480     // write entries to cvs DBUS service configuration
0481     KConfigGroup repoGroup = m_serviceConfig->group(QLatin1String("Repository-") + item->repository());
0482 
0483     qCDebug(log_cervisia) << "repository=" << item->repository();
0484 
0485     repoGroup.writeEntry("rsh", item->rsh());
0486     repoGroup.writeEntry("cvs_server", item->server());
0487     repoGroup.writeEntry("Compression", item->compression());
0488     repoGroup.writeEntry("RetrieveCvsignore", item->retrieveCvsignore());
0489 }
0490 
0491 // kate: space-indent on; indent-width 4; replace-tabs on;