File indexing completed on 2024-04-28 17:00:48

0001 /***************************************************************************
0002  *   Copyright (C) 2005-2009 by Rajko Albrecht                             *
0003  *   ral@alwins-world.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                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
0019  ***************************************************************************/
0020 
0021 #include "kdesvnview.h"
0022 #include "svnfrontend/maintreewidget.h"
0023 #include "svnfrontend/createrepodlg.h"
0024 #include "svnfrontend/dumprepo_impl.h"
0025 #include "svnfrontend/hotcopydlg_impl.h"
0026 #include "svnfrontend/loaddmpdlg_impl.h"
0027 #include "svnfrontend/stopdlg.h"
0028 #include "svnfrontend/fronthelpers/propertylist.h"
0029 #include "settings/kdesvnsettings.h"
0030 #include "svnqt/url.h"
0031 #include "svnqt/repository.h"
0032 #include "svnqt/version_check.h"
0033 #include "svnqt/svnqttypes.h"
0034 
0035 #include <QFileInfo>
0036 #include <QMenu>
0037 #include <QProgressBar>
0038 #include <QSplitter>
0039 #include <QTemporaryFile>
0040 #include <QTextBrowser>
0041 
0042 #include <KActionCollection>
0043 #include <KIO/FileCopyJob>
0044 #include <KJobWidgets>
0045 #include <KLocalizedString>
0046 #include <KMessageBox>
0047 
0048 kdesvnView::kdesvnView(KActionCollection *aCollection, QWidget *parent, bool full)
0049     : QWidget(parent), svn::repository::RepositoryListener()
0050     , m_Collection(aCollection)
0051     , m_currentUrl()
0052     , m_CacheProgressBar(nullptr)
0053     , m_ReposCancel(false)
0054 {
0055     Q_UNUSED(full);
0056     setFocusPolicy(Qt::StrongFocus);
0057     setupActions();
0058 
0059     m_topLayout = new QVBoxLayout(this);
0060 
0061     m_Splitter = new QSplitter(this);
0062     m_Splitter->setOrientation(Qt::Vertical);
0063 
0064     //m_TreeWidget=new kdesvnfilelist(m_Collection,m_Splitter);
0065     m_TreeWidget = new MainTreeWidget(m_Collection, m_Splitter);
0066 
0067     m_infoSplitter = new QSplitter(m_Splitter);
0068     m_infoSplitter->setOrientation(Qt::Horizontal);
0069     m_infoSplitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
0070     m_LogWindow = new QTextBrowser(m_infoSplitter);
0071     m_LogWindow->setContextMenuPolicy(Qt::CustomContextMenu);
0072     connect(m_LogWindow, &QWidget::customContextMenuRequested,
0073             this, &kdesvnView::onCustomLogWindowContextMenuRequested);
0074     Propertylist *pl = new Propertylist(m_infoSplitter);
0075     pl->setCommitchanges(true);
0076     connect(pl, &Propertylist::sigSetProperty,
0077             m_TreeWidget, &MainTreeWidget::slotChangeProperties);
0078     connect(m_TreeWidget, &MainTreeWidget::sigProplist,
0079             pl, &Propertylist::displayList);
0080     connect(m_TreeWidget, &MainTreeWidget::sigProplist,
0081             pl, &Propertylist::displayList);
0082 
0083     m_TreeWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
0084 
0085     m_topLayout->addWidget(m_Splitter);
0086     connect(m_TreeWidget, &MainTreeWidget::sigLogMessage, this, &kdesvnView::slotAppendLog);
0087     connect(m_TreeWidget, &MainTreeWidget::changeCaption, this, &kdesvnView::slotSetTitle);
0088     connect(m_TreeWidget, &MainTreeWidget::sigShowPopup, this, &kdesvnView::slotDispPopup);
0089     connect(m_TreeWidget, &MainTreeWidget::sigUrlOpened, this, &kdesvnView::sigUrlOpened);
0090     connect(m_TreeWidget, &MainTreeWidget::sigSwitchUrl, this, &kdesvnView::sigSwitchUrl);
0091     connect(m_TreeWidget, &MainTreeWidget::sigUrlChanged, this, &kdesvnView::slotUrlChanged);
0092     connect(m_TreeWidget, &MainTreeWidget::sigCacheStatus, this, &kdesvnView::fillCacheStatus);
0093     connect(m_TreeWidget, &MainTreeWidget::sigExtraStatusMessage, this, &kdesvnView::sigExtraStatusMessage);
0094 
0095     connect(this, &kdesvnView::sigMakeBaseDirs, m_TreeWidget, &MainTreeWidget::slotMkBaseDirs);
0096 
0097     KConfigGroup cs(Kdesvnsettings::self()->config(), "kdesvn-mainlayout");
0098     QByteArray t1 = cs.readEntry("split1", QByteArray());
0099     if (!t1.isEmpty()) {
0100         m_Splitter->restoreState(t1);
0101     }
0102     if (m_infoSplitter) {
0103         t1 = cs.readEntry("infosplit", QByteArray());
0104         if (!t1.isEmpty()) {
0105             m_infoSplitter->restoreState(t1);
0106         }
0107     }
0108 }
0109 
0110 void kdesvnView::slotAppendLog(const QString &text)
0111 {
0112     m_LogWindow->append(text);
0113 }
0114 
0115 kdesvnView::~kdesvnView()
0116 {
0117 }
0118 
0119 void kdesvnView::slotSavestate()
0120 {
0121     KConfigGroup cs(Kdesvnsettings::self()->config(), "kdesvn-mainlayout");
0122     cs.writeEntry("split1", m_Splitter->saveState());
0123     if (m_infoSplitter) {
0124         cs.writeEntry("infosplit", m_infoSplitter->saveState());
0125     }
0126 }
0127 
0128 void kdesvnView::slotUrlChanged(const QUrl &url)
0129 {
0130     m_currentUrl = url;
0131     slotSetTitle(url.toString());
0132     emit sigUrlChanged(url);
0133     slotOnURL(i18n("Repository opened"));
0134 }
0135 
0136 QUrl kdesvnView::currentUrl() const
0137 {
0138     return m_currentUrl;
0139 }
0140 
0141 bool kdesvnView::openUrl(const QUrl &url)
0142 {
0143     /* transform of url must be done in part! otherwise we will run into different troubles! */
0144     m_currentUrl.clear();
0145     QUrl _url(url);
0146     bool open = false;
0147     if (_url.isLocalFile()) {
0148         QString query = _url.query();
0149         _url.setQuery(QString());
0150         QString _f = _url.path();
0151         QFileInfo f(_f);
0152         if (!f.isDir()) {
0153             m_currentUrl.clear();
0154             return open;
0155         }
0156         if (query.length() > 1) {
0157             _url.setQuery(query);
0158         }
0159     } else {
0160         if (!svn::Url::isValid(url.scheme())) {
0161             return open;
0162         }
0163     }
0164     m_LogWindow->clear();
0165     slotSetTitle(url.toString());
0166     if (m_TreeWidget->openUrl(url)) {
0167         slotOnURL(i18n("Repository opened"));
0168         m_currentUrl = url;
0169         open = true;
0170     } else {
0171         QString t = m_TreeWidget->lastError();
0172         if (t.isEmpty()) {
0173             t = i18n("Could not open repository");
0174         }
0175         slotOnURL(t);
0176     }
0177     return open;
0178 }
0179 
0180 void kdesvnView::slotOnURL(const QString &url)
0181 {
0182     emit signalChangeStatusbar(url);
0183 }
0184 
0185 void kdesvnView::slotSetTitle(const QString &title)
0186 {
0187     //emit signalChangeCaption(title);
0188     emit setWindowCaption(title);
0189 }
0190 
0191 /*!
0192     \fn kdesvnView::closeMe()
0193  */
0194 void kdesvnView::closeMe()
0195 {
0196     m_TreeWidget->closeMe();
0197     m_LogWindow->clear();
0198     slotOnURL(i18n("No repository open"));
0199 }
0200 
0201 void kdesvnView::slotDispPopup(const QString &item, QWidget **target)
0202 {
0203     emit sigShowPopup(item, target);
0204 }
0205 
0206 /*!
0207     \fn kdesvnView::refreshCurrentTree()
0208  */
0209 void kdesvnView::refreshCurrentTree()
0210 {
0211     m_TreeWidget->refreshCurrentTree();
0212 }
0213 
0214 /*!
0215     \fn kdesvnView::slotSettingsChanged()
0216  */
0217 void kdesvnView::slotSettingsChanged()
0218 {
0219     m_TreeWidget->slotSettingsChanged();
0220 }
0221 
0222 /*!
0223     \fn kdesvnView::slotCreateRepo()
0224  */
0225 void kdesvnView::slotCreateRepo()
0226 {
0227     QPointer<CreaterepoDlg> dlg(new CreaterepoDlg(this));
0228     if (dlg->exec() != QDialog::Accepted) {
0229         delete dlg;
0230         return;
0231     }
0232     QScopedPointer<svn::repository::Repository> _rep(new svn::repository::Repository(this));
0233     bool ok = true;
0234     closeMe();
0235     try {
0236         _rep->CreateOpen(dlg->parameter());
0237     } catch (const svn::ClientException &e) {
0238         slotAppendLog(e.msg());
0239         ok = false;
0240     }
0241     if (!ok) {
0242         delete dlg;
0243         return;
0244     }
0245     bool createdirs = dlg->createMain();
0246     // repo is created on a local path
0247     const QUrl path = QUrl::fromLocalFile(dlg->targetDir());
0248     delete dlg;
0249     openUrl(path);
0250     if (createdirs) {
0251         emit sigMakeBaseDirs();
0252     }
0253 }
0254 
0255 void kdesvnView::slotHotcopy()
0256 {
0257     QPointer<KSvnSimpleOkDialog> dlg(new KSvnSimpleOkDialog(QStringLiteral("hotcopy_repo_size"), QApplication::activeModalWidget()));
0258     dlg->setWindowTitle(i18nc("@title:window", "Hotcopy a Repository"));
0259     dlg->setWithCancelButton();
0260 
0261     HotcopyDlg_impl *ptr = new HotcopyDlg_impl(dlg);
0262     dlg->addWidget(ptr);
0263     if (dlg->exec() != QDialog::Accepted) {
0264         delete dlg;
0265         return;
0266     }
0267     bool cleanlogs = ptr->cleanLogs();
0268     QString src = ptr->srcPath();
0269     QString dest = ptr->destPath();
0270     delete dlg;
0271     if (src.isEmpty() || dest.isEmpty()) {
0272         return;
0273     }
0274     try {
0275         svn::repository::Repository::hotcopy(src, dest, cleanlogs);
0276         slotAppendLog(i18n("Hotcopy finished."));
0277     } catch (const svn::ClientException &e) {
0278         slotAppendLog(e.msg());
0279     }
0280 }
0281 
0282 void kdesvnView::slotLoaddump()
0283 {
0284     QPointer<KSvnSimpleOkDialog> dlg(new KSvnSimpleOkDialog(QStringLiteral("loaddump_repo_size"), this));
0285     dlg->setWindowTitle(i18nc("@title:window", "Load a Repository From an svndump"));
0286     dlg->setWithCancelButton();
0287 
0288     LoadDmpDlg_impl *ptr(new LoadDmpDlg_impl(dlg));
0289     dlg->addWidget(ptr);
0290     if (dlg->exec() != QDialog::Accepted) {
0291         delete dlg;
0292         return;
0293     }
0294     svn::repository::Repository _rep(this);
0295     m_ReposCancel = false;
0296 
0297     try {
0298         _rep.Open(ptr->repository());
0299     } catch (const svn::ClientException &e) {
0300         slotAppendLog(e.msg());
0301         return ;
0302     }
0303 
0304     svn::repository::Repository::LOAD_UUID _act;
0305     switch (ptr->uuidAction()) {
0306     case 1:
0307         _act = svn::repository::Repository::UUID_IGNORE_ACTION;
0308         break;
0309     case 2:
0310         _act = svn::repository::Repository::UUID_FORCE_ACTION;
0311         break;
0312     case 0:
0313     default:
0314         _act = svn::repository::Repository::UUID_DEFAULT_ACTION;
0315         break;
0316     }
0317 
0318     const QUrl _uri = ptr->dumpFile();
0319     QString _input;
0320     QTemporaryFile tmpfile;
0321     if (_uri.isLocalFile()) {
0322         _input = _uri.toLocalFile();
0323     } else {
0324         tmpfile.open();
0325         KIO::FileCopyJob *job = KIO::file_copy(_uri, QUrl::fromLocalFile(tmpfile.fileName()));
0326         KJobWidgets::setWindow(job, this);
0327         if (!job->exec()) {
0328             KMessageBox::error(this, job->errorString());
0329             return;
0330         }
0331         _input = tmpfile.fileName();
0332     }
0333 
0334     try {
0335         StopDlg sdlg(nullptr, this, i18nc("@title:window", "Load Dump"), i18n("Loading a dump into a repository."));
0336         _rep.loaddump(_input, _act, ptr->parentPath(), ptr->usePre(), ptr->usePost(), ptr->validateProps());
0337         slotAppendLog(i18n("Loading dump finished."));
0338     } catch (const svn::ClientException &e) {
0339         slotAppendLog(e.msg());
0340     }
0341     delete dlg;
0342 }
0343 
0344 void kdesvnView::slotDumpRepo()
0345 {
0346     QPointer<KSvnSimpleOkDialog> dlg(new KSvnSimpleOkDialog(QStringLiteral("dump_repo_size"), QApplication::activeModalWidget()));
0347     dlg->setWindowTitle(i18nc("@title:window", "Dump a Repository"));
0348     dlg->setWithCancelButton();
0349 
0350     DumpRepo_impl *ptr(new DumpRepo_impl(dlg));
0351     dlg->addWidget(ptr);
0352     if (dlg->exec() != QDialog::Accepted) {
0353         delete dlg;
0354         return;
0355     }
0356 
0357     const QString re = ptr->reposPath();
0358     const QString out = ptr->targetFile();
0359     const bool incr = ptr->incremental();
0360     const bool diffs = ptr->use_deltas();
0361     const int s = ptr->startNumber();
0362     const int e = ptr->endNumber();
0363 
0364     delete dlg;
0365 
0366     m_ReposCancel = false;
0367     svn::Revision st = svn::Revision::UNDEFINED;
0368     svn::Revision en = svn::Revision::UNDEFINED;
0369 
0370     if (s > -1) {
0371         st = s;
0372     }
0373     if (e > -1) {
0374         en = e;
0375     }
0376 
0377     svn::repository::Repository *_rep(new svn::repository::Repository(this));
0378     try {
0379         _rep->Open(re);
0380     } catch (const svn::ClientException &e) {
0381         slotAppendLog(e.msg());
0382         delete _rep;
0383         return;
0384     }
0385 
0386     try {
0387         StopDlg sdlg(nullptr, this, i18nc("@title:window", "Dump"), i18n("Dumping a repository"));
0388         _rep->dump(out, st, en, incr, diffs);
0389         slotAppendLog(i18n("Dump finished."));
0390     } catch (const svn::ClientException &e) {
0391         slotAppendLog(e.msg());
0392     }
0393     delete _rep;
0394 }
0395 
0396 /*!
0397     \fn kdesvnView::setupActions()
0398  */
0399 void kdesvnView::setupActions()
0400 {
0401 }
0402 
0403 void kdesvnView::sendWarning(const QString &aMsg)
0404 {
0405     slotAppendLog(aMsg);
0406 }
0407 
0408 void kdesvnView::sendError(const QString &aMsg)
0409 {
0410     slotAppendLog(aMsg);
0411 }
0412 
0413 bool kdesvnView::isCanceld()
0414 {
0415     if (!m_ReposCancel) {
0416         emit tickProgress();
0417         return false;
0418     }
0419     return true;
0420 }
0421 
0422 void kdesvnView::setCanceled(bool how)
0423 {
0424     m_ReposCancel = how;
0425 }
0426 
0427 void kdesvnView::fillCacheStatus(qlonglong current, qlonglong max)
0428 {
0429     if (current > -1 && max > -1) {
0430         if (!m_CacheProgressBar) {
0431             m_CacheProgressBar = new QProgressBar(this);
0432             m_CacheProgressBar->setRange(0, (int)max);
0433             m_topLayout->addWidget(m_CacheProgressBar);
0434             m_CacheProgressBar->setFormat(i18n("Inserted %v not cached log entries of %m."));
0435         }
0436         if (!m_CacheProgressBar->isVisible()) {
0437             m_CacheProgressBar->show();
0438         }
0439         m_CacheProgressBar->setValue((int)current);
0440     } else {
0441         delete m_CacheProgressBar;
0442         m_CacheProgressBar = nullptr;
0443     }
0444 }
0445 
0446 void kdesvnView::stopCacheThreads()
0447 {
0448     m_TreeWidget->stopLogCache();
0449 }
0450 
0451 void kdesvnView::onCustomLogWindowContextMenuRequested(const QPoint &pos)
0452 {
0453     QPointer<QMenu> menu = m_LogWindow->createStandardContextMenu();
0454     QAction *clearAction = new QAction(tr("Clear"), menu.data());
0455     clearAction->setEnabled(!m_LogWindow->toPlainText().isEmpty());
0456     connect(clearAction, &QAction::triggered,
0457             m_LogWindow, &QTextEdit::clear);
0458     menu->addAction(clearAction);
0459     menu->exec(m_LogWindow->mapToGlobal(pos));
0460     delete menu;
0461 }