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 }