File indexing completed on 2024-04-21 05:42:24

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 "kdesvn.h"
0022 #include "helpers/kdesvn_debug.h"
0023 #include "helpers/ktranslateurl.h"
0024 #include "kdesvn_part.h"
0025 #include "urldlg.h"
0026 
0027 #include <QApplication>
0028 #include <QDir>
0029 #include <QMenuBar>
0030 #include <QStatusBar>
0031 #include <QTimer>
0032 
0033 #include <KActionCollection>
0034 #include <KBookmarkManager>
0035 #include <KEditToolBar>
0036 #include <KLocalizedString>
0037 #include <KMessageBox>
0038 #include <KPluginFactory>
0039 #include <KRecentFilesAction>
0040 #include <KShortcutsDialog>
0041 #include <KStandardAction>
0042 #include <KToggleAction>
0043 #include <kconfig.h>
0044 #include <kconfiggroup.h>
0045 #include <khelpmenu.h>
0046 #include <ksharedconfig.h>
0047 
0048 #ifdef TESTING_RC
0049 #include <kcrash.h>
0050 #endif
0051 
0052 kdesvn::kdesvn()
0053     : KParts::MainWindow()
0054     , KBookmarkOwner()
0055 {
0056     setAttribute(Qt::WA_DeleteOnClose);
0057     m_part = nullptr;
0058 #ifdef TESTING_RC
0059     setXMLFile(TESTING_RC);
0060     qCDebug(KDESVN_LOG) << "Using test rc file in " << TESTING_RC << Qt::endl;
0061     // I hate this crashhandler in development
0062     KCrash::setCrashHandler(0);
0063 #else
0064     setXMLFile(QStringLiteral("kdesvnui.rc"));
0065 #endif
0066     setStandardToolBarMenuEnabled(true);
0067     // then, setup our actions
0068     setupActions();
0069     // and a status bar
0070     statusBar()->show();
0071 
0072     QDir bookmarkDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
0073     if (!bookmarkDir.exists()) {
0074         bookmarkDir.mkpath(bookmarkDir.absolutePath());
0075     }
0076 
0077     m_bookmarkFile = bookmarkDir.absolutePath() + QLatin1String("/bookmarks.xml");
0078     m_BookmarkManager = KBookmarkManager::managerForExternalFile(m_bookmarkFile);
0079     m_BookmarksActionmenu = new KBookmarkActionMenu(m_BookmarkManager->root(), i18n("&Bookmarks"), this);
0080 
0081     actionCollection()->addAction(QStringLiteral("bookmarks"), m_BookmarksActionmenu);
0082     m_Bookmarkactions = new KActionCollection(static_cast<QWidget *>(this));
0083     m_pBookmarkMenu = new KBookmarkMenu(m_BookmarkManager, this, m_BookmarksActionmenu->menu(), m_Bookmarkactions);
0084     m_pBookmarkMenu->setParent(this); // clear when kdesvn window gets destroyed
0085 
0086     // this routine will find and load our Part.  it finds the Part by
0087     // name which is a bad idea usually.. but it's alright in this
0088     // case since our Part is made for this Shell
0089     KPluginMetaData md(QStringLiteral("kf5/parts/kdesvnpart"));
0090     const auto result = KPluginFactory::instantiatePlugin<KParts::ReadOnlyPart>(md, this);
0091     if (result) {
0092         m_part = result.plugin;
0093 
0094         // tell the KParts::MainWindow that this is indeed the main widget
0095         setCentralWidget(m_part->widget());
0096         connect(this, SIGNAL(sigSavestate()), m_part->widget(), SLOT(slotSavestate()));
0097         connect(m_part->widget(), SIGNAL(sigExtraStatusMessage(QString)), this, SLOT(slotExtraStatus(QString)));
0098         connect(m_part->widget(), SIGNAL(sigUrlOpened(bool)), this, SLOT(slotUrlOpened(bool)));
0099 
0100         QAction *tmpAction;
0101         tmpAction = actionCollection()->addAction(QStringLiteral("subversion_create_repo"), m_part->widget(), SLOT(slotCreateRepo()));
0102         tmpAction->setText(i18n("Create and open new repository"));
0103         tmpAction->setToolTip(i18n("Create and opens a new local Subversion repository"));
0104 
0105         tmpAction = actionCollection()->addAction(QStringLiteral("subversion_dump_repo"), m_part->widget(), SLOT(slotDumpRepo()));
0106         tmpAction->setText(i18n("Dump repository to file"));
0107         tmpAction->setToolTip(i18n("Dump a Subversion repository to a file"));
0108 
0109         tmpAction = actionCollection()->addAction(QStringLiteral("subversion_hotcopy_repo"), m_part->widget(), SLOT(slotHotcopy()));
0110         tmpAction->setText(i18n("Hotcopy a repository"));
0111         tmpAction->setToolTip(i18n("Hotcopy a Subversion repository to a new folder"));
0112 
0113         tmpAction = actionCollection()->addAction(QStringLiteral("subversion_load_repo"), m_part->widget(), SLOT(slotLoaddump()));
0114         tmpAction->setText(i18n("Load dump into repository"));
0115         tmpAction->setToolTip(i18n("Load a dump file into a repository."));
0116 
0117         tmpAction = actionCollection()->addAction(QStringLiteral("kdesvn_ssh_add"), m_part, SLOT(slotSshAdd()));
0118         tmpAction->setText(i18n("Add ssh identities to ssh-agent"));
0119         tmpAction->setToolTip(i18n("Force add ssh-identities to ssh-agent for future use."));
0120 
0121         tmpAction = actionCollection()->addAction(QStringLiteral("help_about_kdesvnpart"), m_part, SLOT(showAboutApplication()));
0122         tmpAction->setText(i18n("Info about kdesvn part"));
0123         tmpAction->setToolTip(i18n("Shows info about the kdesvn plugin and not the standalone application."));
0124 
0125         tmpAction = actionCollection()->addAction(QStringLiteral("db_show_status"), m_part, SLOT(showDbStatus()));
0126         tmpAction->setText(i18n("Show database content"));
0127         tmpAction->setToolTip(i18n("Show the content of log cache database"));
0128 
0129         // and integrate the part's GUI with the shells
0130         createGUI(m_part);
0131     } else {
0132         // if we couldn't find our Part, we exit since the Shell by
0133         // itself can't do anything useful
0134         KMessageBox::error(this, i18n("Could not load our part:\n%1", result.errorString));
0135         qApp->quit();
0136         // we return here, cause kapp->quit() only means "exit the
0137         // next time we enter the event loop...
0138         return;
0139     }
0140     setAutoSaveSettings();
0141 }
0142 
0143 kdesvn::~kdesvn()
0144 {
0145 }
0146 
0147 void kdesvn::loadRescent(const QUrl &url)
0148 {
0149     load(url, true);
0150 }
0151 
0152 void kdesvn::load(const QUrl &url, bool addRescent)
0153 {
0154     QTimer::singleShot(100, this, &kdesvn::slotResetExtraStatus);
0155     if (m_part) {
0156         bool ret = m_part->openUrl(url);
0157         KRecentFilesAction *rac = nullptr;
0158         if (addRescent) {
0159             QAction *ac = actionCollection()->action(QStringLiteral("file_open_recent"));
0160             if (ac) {
0161                 rac = (KRecentFilesAction *)ac;
0162             }
0163         }
0164         if (!ret) {
0165             changeStatusbar(i18n("Could not open URL %1", url.toString()));
0166             if (rac) {
0167                 rac->removeUrl(url);
0168             }
0169         } else {
0170             resetStatusBar();
0171             if (rac) {
0172                 rac->addUrl(url);
0173             }
0174         }
0175         if (rac) {
0176             KConfigGroup cg(KSharedConfig::openConfig(), "recent_files");
0177             rac->saveEntries(cg);
0178         }
0179     }
0180 }
0181 
0182 void kdesvn::setupActions()
0183 {
0184     QAction *ac;
0185     KStandardAction::open(this, SLOT(fileOpen()), actionCollection());
0186     KStandardAction::openNew(this, SLOT(fileNew()), actionCollection());
0187     ac = KStandardAction::close(this, SLOT(fileClose()), actionCollection());
0188     //     ac->setEnabled(getMemberList()->count()>1);
0189     ac->setEnabled(memberList().count() > 1);
0190     KStandardAction::quit(this, SLOT(close()), actionCollection());
0191 
0192     KRecentFilesAction *rac = KStandardAction::openRecent(this, SLOT(loadRescent(QUrl)), actionCollection());
0193     if (rac) {
0194         rac->setMaxItems(8);
0195         KConfigGroup cg(KSharedConfig::openConfig(), "recent_files");
0196         rac->loadEntries(cg);
0197         rac->setText(i18n("Recent opened URLs"));
0198     }
0199 
0200     KStandardAction::keyBindings(this, SLOT(optionsConfigureKeys()), actionCollection());
0201     KStandardAction::configureToolbars(this, SLOT(optionsConfigureToolbars()), actionCollection());
0202 
0203     m_statusbarAction = KStandardAction::showStatusbar(this, SLOT(optionsShowStatusbar()), actionCollection());
0204 
0205     KToggleAction *toggletemp;
0206     toggletemp = new KToggleAction(i18n("Load last opened URL on start"), this);
0207     actionCollection()->addAction(QStringLiteral("toggle_load_last_url"), toggletemp);
0208     toggletemp->setToolTip(i18n("Reload last opened URL if no one is given on command line"));
0209     KConfigGroup cs(KSharedConfig::openConfig(), "startup");
0210     toggletemp->setChecked(cs.readEntry("load_last_on_start", false));
0211     connect(toggletemp, &QAction::toggled, this, &kdesvn::slotLoadLast);
0212 }
0213 
0214 void kdesvn::optionsShowStatusbar()
0215 {
0216     // this is all very cut and paste code for showing/hiding the
0217     // statusbar
0218     statusBar()->setVisible(m_statusbarAction->isChecked());
0219 }
0220 
0221 void kdesvn::fileClose()
0222 {
0223     if (m_part) {
0224         m_part->closeUrl();
0225     }
0226     //     if (getMemberList()->count()>1) {
0227     if (memberList().count() > 1) {
0228         close();
0229     } else {
0230         enableClose(false);
0231         QTimer::singleShot(100, this, &kdesvn::slotResetExtraStatus);
0232         enableClose(false);
0233     }
0234 }
0235 
0236 void kdesvn::saveProperties(KConfigGroup &config)
0237 {
0238     // the 'config' object points to the session managed
0239     // config file.  anything you write here will be available
0240     // later when this app is restored
0241     if (!m_part) {
0242         return;
0243     }
0244     if (!m_part->url().isEmpty()) {
0245         config.writeEntry("lastURL", m_part->url().toString());
0246     }
0247 }
0248 
0249 void kdesvn::readProperties(const KConfigGroup &config)
0250 {
0251     // the 'config' object points to the session managed
0252     // config file.  this function is automatically called whenever
0253     // the app is being restored.  read in here whatever you wrote
0254     // in 'saveProperties'
0255     if (!m_part) {
0256         return;
0257     }
0258 
0259     const QUrl url(config.readPathEntry("lastURL", QString()));
0260     if (url.isValid()) {
0261         m_part->openUrl(url);
0262     }
0263 }
0264 
0265 void kdesvn::fileNew()
0266 {
0267     // this slot is called whenever the File->New menu is selected,
0268     // the New shortcut is pressed (usually CTRL+N) or the New toolbar
0269     // button is clicked
0270 
0271     // create a new window
0272     (new kdesvn)->show();
0273     enableClose(true);
0274 }
0275 
0276 void kdesvn::fileOpen()
0277 {
0278     QUrl url = UrlDlg::getUrl(this);
0279     if (!url.isEmpty()) {
0280         load(url, true);
0281     }
0282 }
0283 
0284 void kdesvn::changeStatusbar(const QString &text)
0285 {
0286     statusBar()->showMessage(text);
0287 }
0288 
0289 void kdesvn::resetStatusBar()
0290 {
0291     statusBar()->showMessage(i18n("Ready"), 4000);
0292 }
0293 
0294 // kde4 port - pv
0295 void kdesvn::openBookmark(const KBookmark &bm, Qt::MouseButtons mb, Qt::KeyboardModifiers km)
0296 {
0297     Q_UNUSED(mb);
0298     Q_UNUSED(km);
0299     if (!bm.url().isEmpty() && m_part) {
0300         load(bm.url(), false);
0301     }
0302 }
0303 
0304 QUrl kdesvn::currentUrl() const
0305 {
0306     if (!m_part) {
0307         return QUrl();
0308     }
0309     return m_part->url();
0310 }
0311 
0312 QString kdesvn::currentTitle() const
0313 {
0314     if (!m_part) {
0315         return QString();
0316     }
0317     return m_part->url().fileName();
0318 }
0319 
0320 void kdesvn::enableClose(bool how)
0321 {
0322     QAction *ac;
0323     if ((ac = actionCollection()->action(QStringLiteral("file_close")))) {
0324         ac->setEnabled(how);
0325     }
0326 }
0327 
0328 /*!
0329     \fn kdesvn::slotUrlOpened(bool)
0330  */
0331 void kdesvn::slotUrlOpened(bool how)
0332 {
0333     enableClose(how);
0334 }
0335 
0336 /*!
0337     \fn kdesvn::optionsConfigureToolbars()
0338  */
0339 void kdesvn::optionsConfigureToolbars()
0340 {
0341     KConfigGroup cg(KSharedConfig::openConfig(), autoSaveGroup());
0342     saveMainWindowSettings(cg);
0343 
0344     // use the standard toolbar editor
0345     QPointer<KEditToolBar> dlg(new KEditToolBar(factory()));
0346     connect(dlg.data(), &KEditToolBar::newToolBarConfig, this, &kdesvn::applyNewToolbarConfig);
0347     dlg->exec();
0348     delete dlg;
0349 }
0350 
0351 /*!
0352     \fn kdesvn::applyNewToolbarConfig()
0353  */
0354 void kdesvn::applyNewToolbarConfig()
0355 {
0356     KConfigGroup cg(KSharedConfig::openConfig(), autoSaveGroup());
0357     applyMainWindowSettings(cg);
0358 }
0359 
0360 void kdesvn::optionsConfigureKeys()
0361 {
0362     QPointer<KShortcutsDialog> kdlg(new KShortcutsDialog(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsAllowed, m_part->widget()));
0363     kdlg->addCollection(actionCollection());
0364     kdlg->addCollection(m_part->actionCollection());
0365 
0366     kdlg->configure(true);
0367     delete kdlg;
0368 }
0369 
0370 /*!
0371     \fn kdesvn::closeEvent()
0372  */
0373 void kdesvn::closeEvent(QCloseEvent *ev)
0374 {
0375     emit sigSavestate();
0376     if (m_part) {
0377         KConfigGroup cs(KSharedConfig::openConfig(), "startup");
0378         cs.writeEntry("lastURL", m_part->url().toString(QUrl::FullyEncoded));
0379         cs.sync();
0380     }
0381     return KParts::MainWindow::closeEvent(ev);
0382 }
0383 
0384 /*!
0385     \fn kdesvn::checkReload()
0386  */
0387 void kdesvn::checkReload()
0388 {
0389     KConfigGroup cs(KSharedConfig::openConfig(), "startup");
0390     if (!cs.readEntry("load_last_on_start", false)) {
0391         return;
0392     }
0393 
0394     const QUrl url(cs.readPathEntry("lastURL", QString()));
0395     if (url.isValid() && m_part) {
0396         load(url, false);
0397     }
0398 }
0399 
0400 /*!
0401     \fn kdesvn::slotLoadLast(bool)
0402  */
0403 void kdesvn::slotLoadLast(bool how)
0404 {
0405     KConfigGroup cs(KSharedConfig::openConfig(), "startup");
0406     cs.writeEntry("load_last_on_start", how);
0407     cs.sync();
0408 }
0409 
0410 void kdesvn::slotResetExtraStatus()
0411 {
0412     statusBar()->clearMessage();
0413 }
0414 
0415 void kdesvn::slotExtraStatus(const QString &message)
0416 {
0417     statusBar()->clearMessage();
0418     statusBar()->showMessage(message);
0419 }
0420 
0421 #include "moc_kdesvn.cpp"