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"