Warning, file /sdk/cervisia/cervisiapart.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-2005 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 "cervisiapart.h"
0022 
0023 #include <QList>
0024 #include <QSplitter>
0025 #include <QStatusBar>
0026 #include <qlabel.h>
0027 #include <qmenu.h>
0028 #include <qmessagebox.h>
0029 #include <qpushbutton.h>
0030 #include <qtextstream.h>
0031 
0032 #include <KConfig>
0033 #include <KConfigGroup>
0034 #include <KIO/ApplicationLauncherJob>
0035 #include <KLocalizedString>
0036 #include <KSharedConfig>
0037 #include <QDebug>
0038 #include <kaboutdata.h>
0039 #include <kactioncollection.h>
0040 #include <kmessagebox.h>
0041 #include <knotification.h>
0042 #include <kparts/guiactivateevent.h>
0043 #include <kpropertiesdialog.h>
0044 #include <krecentfilesaction.h>
0045 #include <krun.h>
0046 #include <kshell.h>
0047 #include <kstandardaction.h>
0048 #include <ktoggleaction.h>
0049 #include <ktoolinvocation.h>
0050 #include <kxmlguifactory.h>
0051 
0052 #include "addignoremenu.h"
0053 #include "annotatecontroller.h"
0054 #include "annotatedialog.h"
0055 #include "changelogdialog.h"
0056 #include "cvsinitdialog.h"
0057 #include "cvsserviceinterface.h"
0058 #include "debug.h"
0059 #include "diffdialog.h"
0060 #include "editwithmenu.h"
0061 #include "globalignorelist.h"
0062 #include "historydialog.h"
0063 #include "logdialog.h"
0064 #include "mergedialog.h"
0065 #include "misc.h"
0066 #include "patchoptiondialog.h"
0067 #include "progressdialog.h"
0068 #include "protocolview.h"
0069 #include "repositorydialog.h"
0070 #include "resolvedialog.h"
0071 #include "settingsdialog.h"
0072 #include "updatedialog.h"
0073 #include "updateview.h"
0074 #include "updateview_items.h"
0075 #include "watchersdialog.h"
0076 #include <QFileDialog>
0077 #include <repositoryinterface.h>
0078 
0079 #include "cervisia_version.h"
0080 #include "cvsjobinterface.h"
0081 
0082 using Cervisia::TagDialog;
0083 
0084 K_PLUGIN_FACTORY(CervisiaFactory, registerPlugin<CervisiaPart>();)
0085 #include <cervisiapart.moc>
0086 
0087 CervisiaPart::CervisiaPart(QWidget *parentWidget, QObject *parent, const QVariantList & /*args*/)
0088     : KParts::ReadOnlyPart(parent)
0089     , hasRunningJob(false)
0090     , opt_hideFiles(false)
0091     , opt_hideUpToDate(false)
0092     , opt_hideRemoved(false)
0093     , opt_hideNotInCVS(false)
0094     , opt_hideEmptyDirectories(false)
0095     , opt_createDirs(false)
0096     , opt_pruneDirs(false)
0097     , opt_updateRecursive(true)
0098     , opt_commitRecursive(true)
0099     , opt_doCVSEdit(false)
0100     , recent(0)
0101     , cvsService(0)
0102     , m_statusBar(new KParts::StatusBarExtension(this))
0103     , m_browserExt(0)
0104     , filterLabel(0)
0105     , m_editWithAction(0)
0106     , m_currentEditMenu(0)
0107     , m_addIgnoreAction(0)
0108     , m_currentIgnoreMenu(0)
0109     , m_jobType(Unknown)
0110 {
0111     setComponentName("cervisiapart", i18n("Cervisia"));
0112 
0113     m_browserExt = new CervisiaBrowserExtension(this);
0114 
0115     // start the cvs D-Bus service
0116     QString error;
0117     if (KToolInvocation::startServiceByDesktopName("org.kde.cvsservice5", QStringList(), &error, &m_cvsServiceInterfaceName)) {
0118         KMessageBox::error(0, i18n("Starting cvsservice failed with message: ") + error, "Cervisia");
0119     } else
0120         // create a reference to the service
0121         cvsService = new OrgKdeCervisia5CvsserviceCvsserviceInterface(m_cvsServiceInterfaceName, "/CvsService", QDBusConnection::sessionBus(), this);
0122     // qCDebug(log_cervisia) << "m_cvsServiceInterfaceName:" << m_cvsServiceInterfaceName;
0123     // kdDebug(8050) << "cvsService->service():" << cvsService->service()<<endl;
0124     //  Create UI
0125     KConfigGroup conf(config(), "LookAndFeel");
0126     bool splitHorz = conf.readEntry("SplitHorizontally", true);
0127 
0128     // When we couldn't start the D-Bus service, we just display a QLabel with
0129     // an explanation
0130     if (cvsService) {
0131         Qt::Orientation o = splitHorz ? Qt::Vertical : Qt::Horizontal;
0132         splitter = new QSplitter(o, parentWidget);
0133         // avoid PartManager's warning that Part's window can't handle focus
0134         splitter->setFocusPolicy(Qt::StrongFocus);
0135 
0136         update = new UpdateView(*config(), splitter);
0137         update->setFocusPolicy(Qt::StrongFocus);
0138         update->setContextMenuPolicy(Qt::CustomContextMenu);
0139         update->setFocus();
0140         connect(update, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(popupRequested(QPoint)));
0141 
0142         connect(update, SIGNAL(fileOpened(QString)), this, SLOT(openFile(QString)));
0143         protocol = new ProtocolView(m_cvsServiceInterfaceName, splitter);
0144         protocol->setFocusPolicy(Qt::StrongFocus);
0145 
0146         setWidget(splitter);
0147     } else {
0148         setWidget(new QLabel(i18n("This KPart is non-functional, because the "
0149                                   "cvs D-Bus service could not be started."),
0150                              parentWidget));
0151     }
0152 
0153     if (cvsService) {
0154         setupActions();
0155         readSettings();
0156         connect(update, SIGNAL(itemSelectionChanged()), this, SLOT(updateActions()));
0157     }
0158 
0159     setXMLFile("cervisiaui.rc");
0160 
0161     QTimer::singleShot(0, this, SLOT(slotSetupStatusBar()));
0162 }
0163 
0164 CervisiaPart::~CervisiaPart()
0165 {
0166     // stop the cvs DCOP service and delete reference
0167     if (cvsService) {
0168         writeSettings();
0169         cvsService->quit();
0170         delete cvsService;
0171     }
0172 }
0173 
0174 KConfig *CervisiaPart::config()
0175 {
0176     KSharedConfigPtr tmp = KSharedConfig::openConfig();
0177     return tmp.data(); // the pointer won't get invalid even if the temporary tmp object is
0178                        // destroyed
0179 }
0180 
0181 bool CervisiaPart::openUrl(const QUrl &u)
0182 {
0183     // right now, we are unfortunately not network-aware
0184     if (!u.isLocalFile()) {
0185         KMessageBox::error(widget(),
0186                            i18n("Remote CVS working folders are not "
0187                                 "supported."),
0188                            "Cervisia");
0189         return false;
0190     }
0191 
0192     if (hasRunningJob) {
0193         KMessageBox::error(widget(),
0194                            i18n("You cannot change to a different folder "
0195                                 "while there is a running cvs job."),
0196                            "Cervisia");
0197         return false;
0198     }
0199 
0200     // make a deep copy as if we're called via KRecentFilesAction::urlSelected()
0201     // KRecentFilesAction::addUrl() makes the URL invalid
0202     const QUrl deepCopy(u);
0203 
0204     return openSandbox(deepCopy);
0205 }
0206 
0207 void CervisiaPart::slotSetupStatusBar()
0208 {
0209     // create the active filter indicator and add it to the statusbar
0210     filterLabel = new QLabel("UR", m_statusBar->statusBar());
0211     filterLabel->setFixedSize(filterLabel->sizeHint());
0212     filterLabel->setText("");
0213     filterLabel->setToolTip(
0214         i18n("F - All files are hidden, the tree shows only folders\n"
0215              "N - All up-to-date files are hidden\n"
0216              "R - All removed files are hidden"));
0217     m_statusBar->addStatusBarItem(filterLabel, 0, true);
0218 }
0219 
0220 void CervisiaPart::setupActions()
0221 {
0222     QAction *action;
0223     QString hint;
0224     //
0225     // File Menu
0226     //
0227     action = new QAction(QIcon::fromTheme("document-open"), i18n("Open Sandbox..."), this);
0228     actionCollection()->addAction("file_open", action);
0229     actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_O));
0230     connect(action, SIGNAL(triggered(bool)), SLOT(slotOpenSandbox()));
0231     hint = i18n("Opens a CVS working folder in the main window");
0232     action->setToolTip(hint);
0233     action->setWhatsThis(hint);
0234 
0235     recent = new KRecentFilesAction(i18n("Recent Sandboxes"), this);
0236     actionCollection()->addAction("file_open_recent", recent);
0237     connect(recent, SIGNAL(urlSelected(QUrl)), SLOT(openUrl(QUrl))),
0238 
0239         action = new QAction(i18n("&Insert ChangeLog Entry..."), this);
0240     actionCollection()->addAction("insert_changelog_entry", action);
0241     connect(action, SIGNAL(triggered(bool)), SLOT(slotChangeLog()));
0242     hint = i18n("Inserts a new intro into the file ChangeLog in the toplevel folder");
0243     action->setToolTip(hint);
0244     action->setWhatsThis(hint);
0245 
0246     action = new QAction(QIcon::fromTheme("vcs-update-cvs-cervisia"), i18n("&Update"), this);
0247     actionCollection()->addAction("file_update", action);
0248     connect(action, SIGNAL(triggered(bool)), SLOT(slotUpdate()));
0249     actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_U));
0250     hint = i18n("Updates (cvs update) the selected files and folders");
0251     action->setToolTip(hint);
0252     action->setWhatsThis(hint);
0253 
0254     action = new QAction(QIcon::fromTheme("vcs-status-cvs-cervisia"), i18n("&Status"), this);
0255     actionCollection()->addAction("file_status", action);
0256     connect(action, SIGNAL(triggered(bool)), SLOT(slotStatus()));
0257     actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::Key_F5));
0258     hint = i18n("Updates the status (cvs -n update) of the selected files and folders");
0259     action->setToolTip(hint);
0260     action->setWhatsThis(hint);
0261 
0262     action = new QAction(i18n("&Edit"), this);
0263     actionCollection()->addAction("file_edit", action);
0264     connect(action, SIGNAL(triggered(bool)), SLOT(slotOpen()));
0265     hint = i18n("Opens the marked file for editing");
0266     action->setToolTip(hint);
0267     action->setWhatsThis(hint);
0268 
0269     action = new QAction(i18n("Reso&lve..."), this);
0270     actionCollection()->addAction("file_resolve", action);
0271     connect(action, SIGNAL(triggered(bool)), SLOT(slotResolve()));
0272     hint = i18n("Opens the resolve dialog with the selected file");
0273     action->setToolTip(hint);
0274     action->setWhatsThis(hint);
0275 
0276     action = new QAction(QIcon::fromTheme("vcs-commit-cvs-cervisia"), i18n("&Commit..."), this);
0277     actionCollection()->addAction("file_commit", action);
0278     connect(action, SIGNAL(triggered(bool)), SLOT(slotCommit()));
0279     actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::Key_NumberSign));
0280     hint = i18n("Commits the selected files");
0281     action->setToolTip(hint);
0282     action->setWhatsThis(hint);
0283 
0284     action = new QAction(QIcon::fromTheme("vcs-add-cvs-cervisia"), i18n("&Add to Repository..."), this);
0285     actionCollection()->addAction("file_add", action);
0286     connect(action, SIGNAL(triggered(bool)), SLOT(slotAdd()));
0287     action->setIconText(i18n("Add"));
0288     actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::Key_Insert));
0289     hint = i18n("Adds (cvs add) the selected files to the repository");
0290     action->setToolTip(hint);
0291     action->setWhatsThis(hint);
0292 
0293     action = new QAction(i18n("Add &Binary..."), this);
0294     actionCollection()->addAction("file_add_binary", action);
0295     connect(action, SIGNAL(triggered(bool)), SLOT(slotAddBinary()));
0296     hint = i18n("Adds (cvs -kb add) the selected files as binaries to the repository");
0297     action->setToolTip(hint);
0298     action->setWhatsThis(hint);
0299 
0300     action = new QAction(QIcon::fromTheme("vcs-remove-cvs-cervisia"), i18n("&Remove From Repository..."), this);
0301     actionCollection()->addAction("file_remove", action);
0302     connect(action, SIGNAL(triggered(bool)), SLOT(slotRemove()));
0303     action->setIconText(i18n("Remove"));
0304     actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::Key_Delete));
0305     hint = i18n("Removes (cvs remove) the selected files from the repository");
0306     action->setToolTip(hint);
0307     action->setWhatsThis(hint);
0308 
0309     action = new QAction(i18n("Rever&t"), this);
0310     actionCollection()->addAction("file_revert_local_changes", action);
0311     connect(action, SIGNAL(triggered(bool)), SLOT(slotRevert()));
0312     hint = i18n("Reverts (cvs update -C) the selected files (only cvs 1.11)");
0313     action->setToolTip(hint);
0314     action->setWhatsThis(hint);
0315 
0316     action = new QAction(i18n("&Properties"), this);
0317     actionCollection()->addAction("file_properties", action);
0318     connect(action, SIGNAL(triggered()), SLOT(slotFileProperties()));
0319 
0320     //
0321     // View Menu
0322     //
0323     action = new QAction(QIcon::fromTheme("process-stop"), i18n("Stop"), this);
0324     actionCollection()->addAction("stop_job", action);
0325     connect(action, SIGNAL(triggered(bool)), protocol, SLOT(cancelJob()));
0326     actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::Key_Escape));
0327     action->setEnabled(false);
0328     hint = i18n("Stops any running sub-processes");
0329     action->setToolTip(hint);
0330     action->setWhatsThis(hint);
0331 
0332     action = new QAction(i18n("Browse &Log..."), this);
0333     actionCollection()->addAction("view_log", action);
0334     connect(action, SIGNAL(triggered(bool)), SLOT(slotBrowseLog()));
0335     actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_L));
0336     hint = i18n("Shows the revision tree of the selected file");
0337     action->setToolTip(hint);
0338     action->setWhatsThis(hint);
0339 
0340 #if 0
0341     action = new QAction( i18n("Browse Multi-File Log..."), 0,
0342                           this, SLOT(slotBrowseMultiLog()),
0343                           actionCollection() );
0344 #endif
0345     action = new QAction(i18n("&Annotate..."), this);
0346     actionCollection()->addAction("view_annotate", action);
0347     connect(action, SIGNAL(triggered(bool)), SLOT(slotAnnotate()));
0348     actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_A));
0349     hint = i18n("Shows a blame-annotated view of the selected file");
0350     action->setToolTip(hint);
0351     action->setWhatsThis(hint);
0352 
0353     action = new QAction(QIcon::fromTheme("vcs-diff-cvs-cervisia"), i18n("&Difference to Repository (BASE)..."), this);
0354     actionCollection()->addAction("view_diff_base", action);
0355     connect(action, SIGNAL(triggered(bool)), SLOT(slotDiffBase()));
0356     actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_D));
0357     hint = i18n("Shows the differences of the selected file to the checked out version (tag BASE)");
0358     action->setToolTip(hint);
0359     action->setWhatsThis(hint);
0360 
0361     action = new QAction(QIcon::fromTheme("vcs-diff-cvs-cervisia"), i18n("Difference to Repository (HEAD)..."), this);
0362     actionCollection()->addAction("view_diff_head", action);
0363     connect(action, SIGNAL(triggered(bool)), SLOT(slotDiffHead()));
0364     actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_H));
0365     hint = i18n("Shows the differences of the selected file to the newest version in the repository (tag HEAD)");
0366     action->setToolTip(hint);
0367     action->setWhatsThis(hint);
0368 
0369     action = new QAction(i18n("Last &Change..."), this);
0370     actionCollection()->addAction("view_last_change", action);
0371     connect(action, SIGNAL(triggered(bool)), SLOT(slotLastChange()));
0372     hint = i18n("Shows the differences between the last two revisions of the selected file");
0373     action->setToolTip(hint);
0374     action->setWhatsThis(hint);
0375 
0376     action = new QAction(i18n("&History..."), this);
0377     actionCollection()->addAction("view_history", action);
0378     connect(action, SIGNAL(triggered(bool)), SLOT(slotHistory()));
0379     hint = i18n("Shows the CVS history as reported by the server");
0380     action->setToolTip(hint);
0381     action->setWhatsThis(hint);
0382 
0383     action = new QAction(i18n("&Unfold File Tree"), this);
0384     actionCollection()->addAction("view_unfold_tree", action);
0385     connect(action, SIGNAL(triggered(bool)), SLOT(slotUnfoldTree()));
0386 
0387     hint = i18n("Opens all branches of the file tree");
0388     action->setToolTip(hint);
0389     action->setWhatsThis(hint);
0390 
0391     action = new QAction(i18n("&Fold File Tree"), this);
0392     actionCollection()->addAction("view_fold_tree", action);
0393     connect(action, SIGNAL(triggered(bool)), SLOT(slotFoldTree()));
0394     hint = i18n("Closes all branches of the file tree");
0395     action->setToolTip(hint);
0396     action->setWhatsThis(hint);
0397 
0398     //
0399     // Advanced Menu
0400     //
0401     action = new QAction(i18n("&Tag/Branch..."), this);
0402     actionCollection()->addAction("create_tag", action);
0403     connect(action, SIGNAL(triggered(bool)), SLOT(slotCreateTag()));
0404     hint = i18n("Creates a tag or branch for the selected files");
0405     action->setToolTip(hint);
0406     action->setWhatsThis(hint);
0407 
0408     action = new QAction(i18n("&Delete Tag..."), this);
0409     actionCollection()->addAction("delete_tag", action);
0410     connect(action, SIGNAL(triggered(bool)), SLOT(slotDeleteTag()));
0411     hint = i18n("Deletes a tag from the selected files");
0412     action->setToolTip(hint);
0413     action->setWhatsThis(hint);
0414 
0415     action = new QAction(i18n("&Update to Tag/Date..."), this);
0416     actionCollection()->addAction("update_to_tag", action);
0417     connect(action, SIGNAL(triggered(bool)), SLOT(slotUpdateToTag()));
0418     hint = i18n("Updates the selected files to a given tag, branch or date");
0419     action->setToolTip(hint);
0420     action->setWhatsThis(hint);
0421 
0422     action = new QAction(i18n("Update to &HEAD"), this);
0423     actionCollection()->addAction("update_to_head", action);
0424     connect(action, SIGNAL(triggered(bool)), SLOT(slotUpdateToHead()));
0425     hint = i18n("Updates the selected files to the HEAD revision");
0426     action->setToolTip(hint);
0427     action->setWhatsThis(hint);
0428 
0429     action = new QAction(i18n("&Merge..."), this);
0430     actionCollection()->addAction("merge", action);
0431     connect(action, SIGNAL(triggered(bool)), SLOT(slotMerge()));
0432     hint = i18n("Merges a branch or a set of modifications into the selected files");
0433     action->setToolTip(hint);
0434     action->setWhatsThis(hint);
0435 
0436     action = new QAction(i18n("&Add Watch..."), this);
0437     actionCollection()->addAction("add_watch", action);
0438     connect(action, SIGNAL(triggered(bool)), SLOT(slotAddWatch()));
0439     hint = i18n("Adds a watch for the selected files");
0440     action->setToolTip(hint);
0441     action->setWhatsThis(hint);
0442 
0443     action = new QAction(i18n("&Remove Watch..."), this);
0444     actionCollection()->addAction("remove_watch", action);
0445     connect(action, SIGNAL(triggered(bool)), SLOT(slotRemoveWatch()));
0446     hint = i18n("Removes a watch from the selected files");
0447     action->setToolTip(hint);
0448     action->setWhatsThis(hint);
0449 
0450     action = new QAction(i18n("Show &Watchers"), this);
0451     actionCollection()->addAction("show_watchers", action);
0452     connect(action, SIGNAL(triggered(bool)), SLOT(slotShowWatchers()));
0453     hint = i18n("Shows the watchers of the selected files");
0454     action->setToolTip(hint);
0455     action->setWhatsThis(hint);
0456 
0457     action = new QAction(i18n("Ed&it Files"), this);
0458     actionCollection()->addAction("edit_files", action);
0459     connect(action, SIGNAL(triggered(bool)), SLOT(slotEdit()));
0460     hint = i18n("Edits (cvs edit) the selected files");
0461     action->setToolTip(hint);
0462     action->setWhatsThis(hint);
0463 
0464     action = new QAction(i18n("U&nedit Files"), this);
0465     actionCollection()->addAction("unedit_files", action);
0466     connect(action, SIGNAL(triggered(bool)), SLOT(slotUnedit()));
0467     hint = i18n("Unedits (cvs unedit) the selected files");
0468     action->setToolTip(hint);
0469     action->setWhatsThis(hint);
0470 
0471     action = new QAction(i18n("Show &Editors"), this);
0472     actionCollection()->addAction("show_editors", action);
0473     connect(action, SIGNAL(triggered(bool)), SLOT(slotShowEditors()));
0474     hint = i18n("Shows the editors of the selected files");
0475     action->setToolTip(hint);
0476     action->setWhatsThis(hint);
0477 
0478     action = new QAction(i18n("&Lock Files"), this);
0479     actionCollection()->addAction("lock_files", action);
0480     connect(action, SIGNAL(triggered(bool)), SLOT(slotLock()));
0481     hint = i18n("Locks the selected files, so that others cannot modify them");
0482     action->setToolTip(hint);
0483     action->setWhatsThis(hint);
0484 
0485     action = new QAction(i18n("Unl&ock Files"), this);
0486     actionCollection()->addAction("unlock_files", action);
0487     connect(action, SIGNAL(triggered(bool)), SLOT(slotUnlock()));
0488     hint = i18n("Unlocks the selected files");
0489     action->setToolTip(hint);
0490     action->setWhatsThis(hint);
0491 
0492     action = new QAction(i18n("Create &Patch Against Repository..."), this);
0493     actionCollection()->addAction("make_patch", action);
0494     connect(action, SIGNAL(triggered(bool)), SLOT(slotMakePatch()));
0495     hint = i18n("Creates a patch from the modifications in your sandbox");
0496     action->setToolTip(hint);
0497     action->setWhatsThis(hint);
0498 
0499     //
0500     // Repository Menu
0501     //
0502     action = new QAction(i18n("&Create..."), this);
0503     actionCollection()->addAction("repository_create", action);
0504     connect(action, SIGNAL(triggered(bool)), SLOT(slotCreateRepository()));
0505 
0506     action = new QAction(i18n("&Checkout..."), this);
0507     actionCollection()->addAction("repository_checkout", action);
0508     connect(action, SIGNAL(triggered(bool)), SLOT(slotCheckout()));
0509     hint = i18n("Allows you to checkout a module from a repository");
0510     action->setToolTip(hint);
0511     action->setWhatsThis(hint);
0512 
0513     action = new QAction(i18n("&Import..."), this);
0514     actionCollection()->addAction("repository_import", action);
0515     connect(action, SIGNAL(triggered(bool)), SLOT(slotImport()));
0516     hint = i18n("Allows you to import a module into a repository");
0517     action->setToolTip(hint);
0518     action->setWhatsThis(hint);
0519 
0520     action = new QAction(i18n("&Repositories..."), this);
0521     actionCollection()->addAction("show_repositories", action);
0522     connect(action, SIGNAL(triggered(bool)), SLOT(slotRepositories()));
0523     hint = i18n("Configures a list of repositories you regularly use");
0524     action->setToolTip(hint);
0525     action->setWhatsThis(hint);
0526 
0527     //
0528     // Settings menu
0529     //
0530     action = new KToggleAction(i18n("Hide All &Files"), this);
0531     actionCollection()->addAction("settings_hide_files", action);
0532     connect(action, SIGNAL(triggered(bool)), SLOT(slotHideFiles()));
0533     hint = i18n("Determines whether only folders are shown");
0534     action->setToolTip(hint);
0535     action->setWhatsThis(hint);
0536 
0537     action = new KToggleAction(i18n("Hide Unmodified Files"), this);
0538     actionCollection()->addAction("settings_hide_uptodate", action);
0539     connect(action, SIGNAL(triggered(bool)), SLOT(slotHideUpToDate()));
0540     hint = i18n(
0541         "Determines whether files with status up-to-date or "
0542         "unknown are hidden");
0543     action->setToolTip(hint);
0544     action->setWhatsThis(hint);
0545 
0546     action = new KToggleAction(i18n("Hide Removed Files"), this);
0547     actionCollection()->addAction("settings_hide_removed", action);
0548     connect(action, SIGNAL(triggered(bool)), SLOT(slotHideRemoved()));
0549     hint = i18n("Determines whether removed files are hidden");
0550     action->setToolTip(hint);
0551     action->setWhatsThis(hint);
0552 
0553     action = new KToggleAction(i18n("Hide Non-CVS Files"), this);
0554     actionCollection()->addAction("settings_hide_notincvs", action);
0555     connect(action, SIGNAL(triggered(bool)), SLOT(slotHideNotInCVS()));
0556     hint = i18n("Determines whether files not in CVS are hidden");
0557     action->setToolTip(hint);
0558     action->setWhatsThis(hint);
0559 
0560     action = new KToggleAction(i18n("Hide Empty Folders"), this);
0561     actionCollection()->addAction("settings_hide_empty_directories", action);
0562     connect(action, SIGNAL(triggered(bool)), SLOT(slotHideEmptyDirectories()));
0563     hint = i18n("Determines whether folders without visible entries are hidden");
0564     action->setToolTip(hint);
0565     action->setWhatsThis(hint);
0566 
0567     action = new KToggleAction(i18n("Create &Folders on Update"), this);
0568     actionCollection()->addAction("settings_create_dirs", action);
0569     connect(action, SIGNAL(triggered(bool)), SLOT(slotCreateDirs()));
0570     hint = i18n("Determines whether updates create folders");
0571     action->setToolTip(hint);
0572     action->setWhatsThis(hint);
0573 
0574     action = new KToggleAction(i18n("&Prune Empty Folders on Update"), this);
0575     actionCollection()->addAction("settings_prune_dirs", action);
0576     connect(action, SIGNAL(triggered(bool)), SLOT(slotPruneDirs()));
0577     hint = i18n("Determines whether updates remove empty folders");
0578     action->setToolTip(hint);
0579     action->setWhatsThis(hint);
0580 
0581     action = new KToggleAction(i18n("&Update Recursively"), this);
0582     actionCollection()->addAction("settings_update_recursively", action);
0583     connect(action, SIGNAL(triggered(bool)), SLOT(slotUpdateRecursive()));
0584     hint = i18n("Determines whether updates are recursive");
0585     action->setToolTip(hint);
0586     action->setWhatsThis(hint);
0587 
0588     action = new KToggleAction(i18n("C&ommit && Remove Recursively"), this);
0589     actionCollection()->addAction("settings_commit_recursively", action);
0590     connect(action, SIGNAL(triggered(bool)), SLOT(slotCommitRecursive()));
0591     hint = i18n("Determines whether commits and removes are recursive");
0592     action->setToolTip(hint);
0593     action->setWhatsThis(hint);
0594 
0595     action = new KToggleAction(i18n("Do cvs &edit Automatically When Necessary"), this);
0596     actionCollection()->addAction("settings_do_cvs_edit", action);
0597     connect(action, SIGNAL(triggered(bool)), SLOT(slotDoCVSEdit()));
0598     hint = i18n("Determines whether automatic cvs editing is active");
0599     action->setToolTip(hint);
0600     action->setWhatsThis(hint);
0601 
0602     action = new QAction(QIcon::fromTheme("configure"), i18n("Configure Cervisia..."), this);
0603     actionCollection()->addAction("configure_cervisia", action);
0604     connect(action, SIGNAL(triggered(bool)), SLOT(slotConfigure()));
0605     hint = i18n("Allows you to configure the Cervisia KPart");
0606     action->setToolTip(hint);
0607     action->setWhatsThis(hint);
0608 
0609     //
0610     // Help Menu
0611     //
0612 
0613     action = new QAction(i18n("CVS &Manual"), this);
0614     actionCollection()->addAction("help_cvs_manual", action);
0615     connect(action, SIGNAL(triggered(bool)), SLOT(slotCVSInfo()));
0616     hint = i18n("Opens the help browser with the CVS documentation");
0617     action->setToolTip(hint);
0618     action->setWhatsThis(hint);
0619 
0620     //
0621     // Folder context menu
0622     //
0623     action = new KToggleAction(i18n("Unfold Folder"), this);
0624     actionCollection()->addAction("unfold_folder", action);
0625     connect(action, SIGNAL(triggered(bool)), SLOT(slotUnfoldFolder()));
0626 }
0627 
0628 void CervisiaPart::popupRequested(const QPoint &p)
0629 {
0630     QString xmlName = "context_popup";
0631     QTreeWidgetItem *item = update->itemAt(p);
0632 
0633     // context menu for non-cvs files
0634     if (isFileItem(item)) {
0635         auto fileItem = static_cast<UpdateItem *>(item);
0636         if (fileItem->entry().m_status == Cervisia::NotInCVS)
0637             xmlName = "noncvs_context_popup";
0638     }
0639 
0640     // context menu for folders
0641     if (isDirItem(item) && update->fileSelection().isEmpty()) {
0642         xmlName = "folder_context_popup";
0643         KToggleAction *action = static_cast<KToggleAction *>(actionCollection()->action("unfold_folder"));
0644         action->setChecked(item->isExpanded());
0645     }
0646 
0647     if (auto popup = static_cast<QMenu *>(hostContainer(xmlName))) {
0648         if (isFileItem(item)) {
0649             // get name of selected file
0650             QString selectedFile;
0651             update->getSingleSelection(&selectedFile);
0652 
0653             if (!selectedFile.isEmpty()) {
0654                 m_currentEditMenu = new Cervisia::EditWithMenu(QUrl::fromLocalFile(sandbox + '/' + selectedFile), popup);
0655 
0656                 if (m_currentEditMenu->menu())
0657                     m_editWithAction = popup->insertMenu(popup->actions().at(1), m_currentEditMenu->menu());
0658             }
0659         }
0660 
0661         // Add to Ignore List Menu
0662         if (xmlName == "noncvs_context_popup") {
0663             // remove old 'Add to Ignore List' menu
0664             if (m_addIgnoreAction && popup->actions().contains(m_addIgnoreAction)) {
0665                 popup->removeAction(m_addIgnoreAction);
0666                 delete m_currentIgnoreMenu;
0667 
0668                 m_addIgnoreAction = 0;
0669                 m_currentIgnoreMenu = 0;
0670             }
0671 
0672             QStringList list = update->multipleSelection();
0673             m_currentIgnoreMenu = new Cervisia::AddIgnoreMenu(sandbox, list, popup);
0674             if (m_currentIgnoreMenu->menu())
0675                 m_addIgnoreAction = popup->insertMenu(actionCollection()->action("file_add"), m_currentIgnoreMenu->menu());
0676         }
0677 
0678         popup->exec(update->viewport()->mapToGlobal(p));
0679 
0680         // remove old 'Edit with...' menu
0681         if (m_editWithAction && popup->actions().contains(m_editWithAction)) {
0682             popup->removeAction(m_editWithAction);
0683             delete m_currentEditMenu;
0684 
0685             m_editWithAction = 0;
0686             m_currentEditMenu = 0;
0687         }
0688     } else
0689         qCDebug(log_cervisia) << "can't get XML definition for" << xmlName << ", factory()=" << factory();
0690 }
0691 
0692 void CervisiaPart::updateActions()
0693 {
0694     bool hassandbox = !sandbox.isEmpty();
0695     stateChanged("has_sandbox", hassandbox ? StateNoReverse : StateReverse);
0696 
0697     bool single = update->hasSingleSelection();
0698     stateChanged("has_single_selection", single ? StateNoReverse : StateReverse);
0699 
0700     bool singleFolder = (update->multipleSelection().count() == 1);
0701     stateChanged("has_single_folder", singleFolder ? StateNoReverse : StateReverse);
0702 
0703     //    bool nojob = !( actionCollection()->action( "stop_job" )->isEnabled() );
0704     bool selected = (update->currentItem() != 0);
0705     bool nojob = !hasRunningJob && selected;
0706 
0707     stateChanged("item_selected", selected ? StateNoReverse : StateReverse);
0708     stateChanged("has_no_job", nojob ? StateNoReverse : StateReverse);
0709     stateChanged("has_running_job", hasRunningJob ? StateNoReverse : StateReverse);
0710 }
0711 
0712 KAboutData *CervisiaPart::createAboutData()
0713 {
0714     auto about = new KAboutData("cervisiapart",
0715                                 i18n("Cervisia Part"),
0716                                 CERVISIA_VERSION_STRING,
0717                                 i18n("A CVS frontend"),
0718                                 KAboutLicense::GPL,
0719                                 i18n("Copyright (c) 1999-2002 Bernd Gehrmann\n"
0720                                      "Copyright (c) 2002-2008 the Cervisia authors"),
0721                                 QString(),
0722                                 QLatin1String("http://cervisia.kde.org"));
0723 
0724     about->addAuthor(i18n("Bernd Gehrmann"),
0725                      i18n("Original author and former "
0726                           "maintainer"),
0727                      "bernd@mail.berlios.de");
0728     about->addAuthor(i18n("Christian Loose"), i18n("Maintainer"), "christian.loose@kdemail.net");
0729     about->addAuthor(i18n("Andr\303\251 W\303\266bbeking"), i18n("Developer"), "woebbeking@kde.org");
0730     about->addAuthor(i18n("Carlos Woelz"), i18n("Documentation"), "carloswoelz@imap-mail.com");
0731 
0732     about->addCredit(i18n("Richard Moore"), i18n("Conversion to KPart"), "rich@kde.org");
0733     about->addCredit(i18n("Laurent Montel"), i18n("Conversion to D-Bus"), "montel@kde.org");
0734     about->addCredit(i18n("Martin Koller"), i18n("Port to KDE Frameworks 5"), "kollix@aon.at");
0735 
0736     return about;
0737 }
0738 
0739 void CervisiaPart::slotOpenSandbox()
0740 {
0741     QString dirname = QFileDialog::getExistingDirectory(widget(), i18n("Open Sandbox"));
0742 
0743     if (dirname.isEmpty())
0744         return;
0745 
0746     openSandbox(QUrl::fromLocalFile(dirname));
0747 }
0748 
0749 void CervisiaPart::slotChangeLog()
0750 {
0751     // Modal dialog
0752     ChangeLogDialog dlg(*config(), widget());
0753     if (dlg.readFile(sandbox + "/ChangeLog")) {
0754         if (dlg.exec())
0755             changelogstr = dlg.message();
0756     }
0757 }
0758 
0759 void CervisiaPart::slotOpen()
0760 {
0761     QStringList filenames = update->fileSelection();
0762     if (filenames.isEmpty())
0763         return;
0764     openFiles(filenames);
0765 }
0766 
0767 void CervisiaPart::openFile(QString filename)
0768 {
0769     QStringList files;
0770     files << filename;
0771     openFiles(files);
0772 }
0773 
0774 void CervisiaPart::openFiles(const QStringList &filenames)
0775 {
0776     // call cvs edit automatically?
0777     if (opt_doCVSEdit) {
0778         QStringList files;
0779 
0780         // only edit read-only files
0781         QStringList::ConstIterator it = filenames.begin();
0782         QStringList::ConstIterator end = filenames.end();
0783         for (; it != end; ++it) {
0784             if (!QFileInfo(*it).isWritable())
0785                 files << *it;
0786         }
0787 
0788         if (files.count()) {
0789             QDBusReply<QDBusObjectPath> job = cvsService->edit(files);
0790 
0791             ProgressDialog dlg(widget(), "Edit", cvsService->service(), job, "edit", i18n("CVS Edit"));
0792             if (!dlg.execute())
0793                 return;
0794         }
0795     }
0796 
0797     // Now open the files by using KRun
0798     QDir dir(sandbox);
0799 
0800     QStringList::ConstIterator it = filenames.begin();
0801     QStringList::ConstIterator end = filenames.end();
0802     for (; it != end; ++it) {
0803         KRun *run = new KRun(QUrl::fromLocalFile(dir.absoluteFilePath(*it)), 0);
0804         run->setRunExecutables(false);
0805     }
0806 }
0807 
0808 void CervisiaPart::slotResolve()
0809 {
0810     QString filename;
0811     update->getSingleSelection(&filename);
0812     if (filename.isEmpty())
0813         return;
0814 
0815     // Non-modal dialog
0816     auto l = new ResolveDialog(*config());
0817     if (l->parseFile(filename))
0818         l->show();
0819     else
0820         delete l;
0821 }
0822 
0823 void CervisiaPart::slotUpdate()
0824 {
0825     updateSandbox();
0826 }
0827 
0828 void CervisiaPart::slotStatus()
0829 {
0830     QStringList list = update->multipleSelection();
0831     if (list.isEmpty())
0832         return;
0833 
0834     update->prepareJob(opt_updateRecursive, UpdateView::UpdateNoAct);
0835 
0836     QDBusReply<QDBusObjectPath> cvsJobPath = cvsService->simulateUpdate(list, opt_updateRecursive, opt_createDirs, opt_pruneDirs);
0837 
0838     // get command line from cvs job
0839     QString cmdline;
0840     QDBusObjectPath cvsJob = cvsJobPath;
0841     if (cvsJob.path().isEmpty())
0842         return;
0843 
0844     OrgKdeCervisia5CvsserviceCvsjobInterface cvsjobinterface(m_cvsServiceInterfaceName, cvsJob.path(), QDBusConnection::sessionBus(), this);
0845     QDBusReply<QString> reply = cvsjobinterface.cvsCommand();
0846     if (reply.isValid())
0847         cmdline = reply;
0848 
0849     if (protocol->startJob(true)) {
0850         showJobStart(cmdline);
0851         connect(protocol, SIGNAL(receivedLine(QString)), update, SLOT(processUpdateLine(QString)));
0852         connect(protocol, SIGNAL(jobFinished(bool, int)), update, SLOT(finishJob(bool, int)));
0853         connect(protocol, SIGNAL(jobFinished(bool, int)), this, SLOT(slotJobFinished()));
0854     }
0855 }
0856 
0857 void CervisiaPart::slotUpdateToTag()
0858 {
0859     auto l = new UpdateDialog(cvsService, widget());
0860 
0861     if (l->exec()) {
0862         QString tagopt;
0863         if (l->byTag()) {
0864             tagopt = "-r ";
0865             tagopt += l->tag();
0866         } else {
0867             tagopt = "-D ";
0868             tagopt += KShell::quoteArg(l->date());
0869         }
0870         tagopt += ' ';
0871         updateSandbox(tagopt);
0872     }
0873     delete l;
0874 }
0875 
0876 void CervisiaPart::slotUpdateToHead()
0877 {
0878     updateSandbox("-A");
0879 }
0880 
0881 void CervisiaPart::slotRevert()
0882 {
0883     updateSandbox("-C");
0884 }
0885 
0886 void CervisiaPart::slotMerge()
0887 {
0888     MergeDialog dlg(cvsService, widget());
0889 
0890     if (dlg.exec()) {
0891         QString tagopt;
0892         if (dlg.byBranch()) {
0893             tagopt = "-j ";
0894             tagopt += dlg.branch();
0895         } else {
0896             tagopt = "-j ";
0897             tagopt += dlg.tag1();
0898             tagopt += " -j ";
0899             tagopt += dlg.tag2();
0900         }
0901         tagopt += ' ';
0902         updateSandbox(tagopt);
0903     }
0904 }
0905 
0906 void CervisiaPart::slotCommit()
0907 {
0908     QStringList list = update->multipleSelection();
0909     if (list.isEmpty())
0910         return;
0911 
0912     // modal dialog
0913     CommitDialog dlg(*config(), cvsService, widget());
0914     dlg.setLogMessage(changelogstr);
0915     dlg.setLogHistory(recentCommits);
0916     dlg.setFileList(list);
0917 
0918     if (dlg.exec()) {
0919         // get new list of files
0920         list = dlg.fileList();
0921         if (list.isEmpty())
0922             return;
0923 
0924         QString msg = dlg.logMessage();
0925         if (!recentCommits.contains(msg)) {
0926             recentCommits.prepend(msg);
0927             while (recentCommits.count() > 50)
0928                 recentCommits.removeLast();
0929 
0930             KConfigGroup conf(config(), "CommitLogs");
0931             conf.writeEntry(sandbox, recentCommits);
0932         }
0933 
0934         update->prepareJob(opt_commitRecursive, UpdateView::Commit);
0935 
0936         QDBusReply<QDBusObjectPath> cvsJobPath = cvsService->commit(list, dlg.logMessage(), opt_commitRecursive);
0937         QString cmdline;
0938         QDBusObjectPath cvsJob = cvsJobPath;
0939         qCDebug(log_cervisia) << " commit: cvsJob.path():" << cvsJob.path();
0940         qCDebug(log_cervisia) << " list:" << list << "dlg.logMessage():" << dlg.logMessage() << "opt_commitRecursive" << opt_commitRecursive;
0941         if (cvsJob.path().isEmpty())
0942             return;
0943 
0944         OrgKdeCervisia5CvsserviceCvsjobInterface cvsjobinterface(m_cvsServiceInterfaceName, cvsJob.path(), QDBusConnection::sessionBus(), this);
0945         QDBusReply<QString> reply = cvsjobinterface.cvsCommand();
0946         if (reply.isValid())
0947             cmdline = reply;
0948 
0949         if (protocol->startJob()) {
0950             m_jobType = Commit;
0951             showJobStart(cmdline);
0952             connect(protocol, SIGNAL(jobFinished(bool, int)), update, SLOT(finishJob(bool, int)));
0953             connect(protocol, SIGNAL(jobFinished(bool, int)), this, SLOT(slotJobFinished()));
0954         }
0955     }
0956 }
0957 
0958 void CervisiaPart::slotAdd()
0959 {
0960     addOrRemove(AddRemoveDialog::Add);
0961 }
0962 
0963 void CervisiaPart::slotAddBinary()
0964 {
0965     addOrRemove(AddRemoveDialog::AddBinary);
0966 }
0967 
0968 void CervisiaPart::slotRemove()
0969 {
0970     addOrRemove(AddRemoveDialog::Remove);
0971 }
0972 
0973 void CervisiaPart::slotFileProperties()
0974 {
0975     QString filename;
0976     update->getSingleSelection(&filename);
0977     if (filename.isEmpty())
0978         return;
0979 
0980     // Create URL from selected filename
0981     QDir dir(sandbox);
0982 
0983     // show file properties dialog
0984     KPropertiesDialog dlg(QUrl::fromLocalFile(dir.absoluteFilePath(filename)), widget());
0985     dlg.exec();
0986 }
0987 
0988 void CervisiaPart::updateSandbox(const QString &extraopt)
0989 {
0990     QStringList list = update->multipleSelection();
0991     if (list.isEmpty())
0992         return;
0993 
0994     update->prepareJob(opt_updateRecursive, UpdateView::Update);
0995 
0996     QDBusReply<QDBusObjectPath> cvsJobPath = cvsService->update(list, opt_updateRecursive, opt_createDirs, opt_pruneDirs, extraopt);
0997 
0998     // get command line from cvs job
0999     QString cmdline;
1000     QDBusObjectPath cvsJob = cvsJobPath;
1001     if (cvsJob.path().isEmpty())
1002         return;
1003     OrgKdeCervisia5CvsserviceCvsjobInterface cvsjobinterface(m_cvsServiceInterfaceName, cvsJob.path(), QDBusConnection::sessionBus(), this);
1004     QDBusReply<QString> reply = cvsjobinterface.cvsCommand();
1005 
1006     if (reply.isValid())
1007         cmdline = reply;
1008 
1009     if (protocol->startJob(true)) {
1010         showJobStart(cmdline);
1011         connect(protocol, SIGNAL(receivedLine(QString)), update, SLOT(processUpdateLine(QString)));
1012         connect(protocol, SIGNAL(jobFinished(bool, int)), update, SLOT(finishJob(bool, int)));
1013         connect(protocol, SIGNAL(jobFinished(bool, int)), this, SLOT(slotJobFinished()));
1014     }
1015 }
1016 
1017 void CervisiaPart::addOrRemove(AddRemoveDialog::ActionType action)
1018 {
1019     QStringList list = update->multipleSelection();
1020     if (list.isEmpty())
1021         return;
1022 
1023     // modal dialog
1024     AddRemoveDialog dlg(action, widget());
1025     dlg.setFileList(list);
1026 
1027     if (dlg.exec()) {
1028         QDBusReply<QDBusObjectPath> cvsJob;
1029 
1030         switch (action) {
1031         case AddRemoveDialog::Add:
1032             update->prepareJob(false, UpdateView::Add);
1033             cvsJob = cvsService->add(list, false);
1034             break;
1035 
1036         case AddRemoveDialog::AddBinary:
1037             update->prepareJob(false, UpdateView::Add);
1038             cvsJob = cvsService->add(list, true);
1039             break;
1040 
1041         case AddRemoveDialog::Remove:
1042             update->prepareJob(opt_commitRecursive, UpdateView::Remove);
1043             cvsJob = cvsService->remove(list, opt_commitRecursive);
1044             break;
1045         }
1046 
1047         // get command line from cvs job
1048         QString cmdline;
1049         QDBusObjectPath cvsJobPath = cvsJob;
1050         if (cvsJobPath.path().isEmpty())
1051             return;
1052 
1053         OrgKdeCervisia5CvsserviceCvsjobInterface cvsjobinterface(m_cvsServiceInterfaceName, cvsJobPath.path(), QDBusConnection::sessionBus(), this);
1054         QDBusReply<QString> reply = cvsjobinterface.cvsCommand();
1055 
1056         if (reply.isValid())
1057             cmdline = reply;
1058 
1059         if (protocol->startJob()) {
1060             showJobStart(cmdline);
1061             connect(protocol, SIGNAL(jobFinished(bool, int)), update, SLOT(finishJob(bool, int)));
1062             connect(protocol, SIGNAL(jobFinished(bool, int)), this, SLOT(slotJobFinished()));
1063         }
1064     }
1065 }
1066 
1067 void CervisiaPart::slotBrowseLog()
1068 {
1069     QString filename;
1070     update->getSingleSelection(&filename);
1071     if (filename.isEmpty())
1072         return;
1073 
1074     // Non-modal dialog
1075     auto l = new LogDialog(*CervisiaPart::config());
1076     if (l->parseCvsLog(cvsService, filename))
1077         l->show();
1078     else
1079         delete l;
1080 }
1081 
1082 void CervisiaPart::slotAnnotate()
1083 {
1084     QString filename, revision;
1085     update->getSingleSelection(&filename, &revision);
1086 
1087     if (filename.isEmpty())
1088         return;
1089 
1090     // Non-modal dialog
1091     auto dlg = new AnnotateDialog(*config());
1092     AnnotateController ctl(dlg, cvsService);
1093     ctl.showDialog(filename, revision);
1094 }
1095 
1096 void CervisiaPart::slotDiffBase()
1097 {
1098     showDiff(QLatin1String("BASE"));
1099 }
1100 
1101 void CervisiaPart::slotDiffHead()
1102 {
1103     showDiff(QLatin1String("HEAD"));
1104 }
1105 
1106 void CervisiaPart::slotAddWatch()
1107 {
1108     addOrRemoveWatch(WatchDialog::Add);
1109 }
1110 
1111 void CervisiaPart::slotRemoveWatch()
1112 {
1113     addOrRemoveWatch(WatchDialog::Remove);
1114 }
1115 
1116 void CervisiaPart::addOrRemoveWatch(WatchDialog::ActionType action)
1117 {
1118     QStringList list = update->multipleSelection();
1119     if (list.isEmpty())
1120         return;
1121 
1122     WatchDialog dlg(action, widget());
1123 
1124     if (dlg.exec() && dlg.events() != WatchDialog::None) {
1125         QDBusReply<QDBusObjectPath> cvsJob;
1126 
1127         if (action == WatchDialog::Add)
1128             cvsJob = cvsService->addWatch(list, dlg.events());
1129         else
1130             cvsJob = cvsService->removeWatch(list, dlg.events());
1131 
1132         QString cmdline;
1133         QDBusObjectPath cvsJobPath = cvsJob;
1134         if (cvsJobPath.path().isEmpty())
1135             return;
1136 
1137         OrgKdeCervisia5CvsserviceCvsjobInterface cvsjobinterface(m_cvsServiceInterfaceName, cvsJobPath.path(), QDBusConnection::sessionBus(), this);
1138         QDBusReply<QString> reply = cvsjobinterface.cvsCommand();
1139 
1140         if (reply.isValid())
1141             cmdline = reply;
1142 
1143         if (protocol->startJob()) {
1144             showJobStart(cmdline);
1145             connect(protocol, SIGNAL(jobFinished(bool, int)), this, SLOT(slotJobFinished()));
1146         }
1147     }
1148 }
1149 
1150 void CervisiaPart::slotShowWatchers()
1151 {
1152     QStringList list = update->multipleSelection();
1153     if (list.isEmpty())
1154         return;
1155 
1156     // Non-modal dialog
1157     auto dlg = new WatchersDialog(*config());
1158     if (dlg->parseWatchers(cvsService, list))
1159         dlg->show();
1160     else
1161         delete dlg;
1162 }
1163 
1164 void CervisiaPart::slotEdit()
1165 {
1166     QStringList list = update->multipleSelection();
1167     if (list.isEmpty())
1168         return;
1169 
1170     QDBusReply<QDBusObjectPath> cvsJobPath = cvsService->edit(list);
1171 
1172     QString cmdline;
1173     QDBusObjectPath cvsJob = cvsJobPath;
1174     if (cvsJob.path().isEmpty())
1175         return;
1176 
1177     OrgKdeCervisia5CvsserviceCvsjobInterface cvsjobinterface(m_cvsServiceInterfaceName, cvsJob.path(), QDBusConnection::sessionBus(), this);
1178     QDBusReply<QString> reply = cvsjobinterface.cvsCommand();
1179 
1180     if (reply.isValid())
1181         cmdline = reply;
1182 
1183     if (protocol->startJob()) {
1184         showJobStart(cmdline);
1185         connect(protocol, SIGNAL(jobFinished(bool, int)), this, SLOT(slotJobFinished()));
1186     }
1187 }
1188 
1189 void CervisiaPart::slotUnedit()
1190 {
1191     QStringList list = update->multipleSelection();
1192     if (list.isEmpty())
1193         return;
1194 
1195     QDBusReply<QDBusObjectPath> cvsJob = cvsService->unedit(list);
1196 
1197     QString cmdline;
1198     QDBusObjectPath cvsJobPath = cvsJob;
1199     if (cvsJobPath.path().isEmpty())
1200         return;
1201 
1202     OrgKdeCervisia5CvsserviceCvsjobInterface cvsjobinterface(m_cvsServiceInterfaceName, cvsJobPath.path(), QDBusConnection::sessionBus(), this);
1203     QDBusReply<QString> reply = cvsjobinterface.cvsCommand();
1204 
1205     if (reply.isValid())
1206         cmdline = reply;
1207 
1208     if (protocol->startJob()) {
1209         showJobStart(cmdline);
1210         connect(protocol, SIGNAL(jobFinished(bool, int)), this, SLOT(slotJobFinished()));
1211     }
1212 }
1213 
1214 void CervisiaPart::slotLock()
1215 {
1216     QStringList list = update->multipleSelection();
1217     if (list.isEmpty())
1218         return;
1219 
1220     QDBusReply<QDBusObjectPath> cvsJobPath = cvsService->lock(list);
1221     QDBusObjectPath cvsJob = cvsJobPath;
1222     if (cvsJob.path().isEmpty())
1223         return;
1224     QString cmdline;
1225     OrgKdeCervisia5CvsserviceCvsjobInterface cvsjobinterface(m_cvsServiceInterfaceName, cvsJob.path(), QDBusConnection::sessionBus(), this);
1226     QDBusReply<QString> reply = cvsjobinterface.cvsCommand();
1227 
1228     if (reply.isValid())
1229         cmdline = reply;
1230 
1231     if (protocol->startJob()) {
1232         showJobStart(cmdline);
1233         connect(protocol, SIGNAL(jobFinished(bool, int)), this, SLOT(slotJobFinished()));
1234     }
1235 }
1236 
1237 void CervisiaPart::slotUnlock()
1238 {
1239     QStringList list = update->multipleSelection();
1240     if (list.isEmpty())
1241         return;
1242 
1243     QDBusReply<QDBusObjectPath> cvsJobPath = cvsService->unlock(list);
1244     QDBusObjectPath cvsJob = cvsJobPath;
1245     if (cvsJob.path().isEmpty())
1246         return;
1247 
1248     QString cmdline;
1249     OrgKdeCervisia5CvsserviceCvsjobInterface cvsjobinterface(m_cvsServiceInterfaceName, cvsJob.path(), QDBusConnection::sessionBus(), this);
1250     QDBusReply<QString> reply = cvsjobinterface.cvsCommand();
1251 
1252     if (reply.isValid())
1253         cmdline = reply;
1254 
1255     if (protocol->startJob()) {
1256         showJobStart(cmdline);
1257         connect(protocol, SIGNAL(jobFinished(bool, int)), this, SLOT(slotJobFinished()));
1258     }
1259 }
1260 
1261 void CervisiaPart::slotShowEditors()
1262 {
1263     QStringList list = update->multipleSelection();
1264     if (list.isEmpty())
1265         return;
1266 
1267     QDBusReply<QDBusObjectPath> cvsJobPath = cvsService->editors(list);
1268     QDBusObjectPath cvsJob = cvsJobPath;
1269     if (cvsJob.path().isEmpty())
1270         return;
1271 
1272     QString cmdline;
1273     OrgKdeCervisia5CvsserviceCvsjobInterface cvsjobinterface(m_cvsServiceInterfaceName, cvsJob.path(), QDBusConnection::sessionBus(), this);
1274     QDBusReply<QString> reply = cvsjobinterface.cvsCommand();
1275 
1276     if (reply.isValid())
1277         cmdline = reply;
1278 
1279     if (protocol->startJob()) {
1280         showJobStart(cmdline);
1281         connect(protocol, SIGNAL(jobFinished(bool, int)), this, SLOT(slotJobFinished()));
1282     }
1283 }
1284 
1285 void CervisiaPart::slotMakePatch()
1286 {
1287     Cervisia::PatchOptionDialog optionDlg;
1288     if (optionDlg.exec() == QDialog::Rejected)
1289         return;
1290 
1291     QString format = optionDlg.formatOption();
1292     QString diffOptions = optionDlg.diffOptions();
1293 
1294     QDBusReply<QDBusObjectPath> job = cvsService->makePatch(diffOptions, format);
1295     if (!job.isValid())
1296         return;
1297 
1298     ProgressDialog dlg(widget(), "Diff", cvsService->service(), job, "", i18n("CVS Diff"));
1299     if (!dlg.execute())
1300         return;
1301 
1302     QString fileName = QFileDialog::getSaveFileName();
1303     if (fileName.isEmpty())
1304         return;
1305 
1306     if (!Cervisia::CheckOverwrite(fileName))
1307         return;
1308 
1309     QFile f(fileName);
1310     if (!f.open(QIODevice::WriteOnly)) {
1311         KMessageBox::error(widget(), i18n("Could not open file for writing."), "Cervisia");
1312         return;
1313     }
1314 
1315     QTextStream t(&f);
1316     QString line;
1317     while (dlg.getLine(line))
1318         t << line << '\n';
1319 
1320     f.close();
1321 }
1322 
1323 void CervisiaPart::slotImport()
1324 {
1325     CheckoutDialog dlg(*config(), cvsService, CheckoutDialog::Import, widget());
1326 
1327     if (!dlg.exec())
1328         return;
1329 
1330     QDBusReply<QDBusObjectPath> cvsJobPath = cvsService->import(dlg.workingDirectory(),
1331                                                                 dlg.repository(),
1332                                                                 dlg.module(),
1333                                                                 dlg.ignoreFiles(),
1334                                                                 dlg.comment(),
1335                                                                 dlg.vendorTag(),
1336                                                                 dlg.releaseTag(),
1337                                                                 dlg.importBinary(),
1338                                                                 dlg.useModificationTime());
1339 
1340     QDBusObjectPath cvsJob = cvsJobPath;
1341     QString cmdline;
1342     ////qDebug()<<" cvsJob.path() :"<<cvsJob.path()<<endl;
1343     if (cvsJob.path().isEmpty())
1344         return;
1345     OrgKdeCervisia5CvsserviceCvsjobInterface cvsjobinterface(m_cvsServiceInterfaceName, cvsJob.path(), QDBusConnection::sessionBus(), this);
1346     QDBusReply<QString> reply = cvsjobinterface.cvsCommand();
1347 
1348     if (reply.isValid())
1349         cmdline = reply;
1350 
1351     if (protocol->startJob()) {
1352         showJobStart(cmdline);
1353         connect(protocol, SIGNAL(jobFinished(bool, int)), this, SLOT(slotJobFinished()));
1354     }
1355 }
1356 
1357 void CervisiaPart::slotCreateRepository()
1358 {
1359     Cervisia::CvsInitDialog dlg(widget());
1360 
1361     if (!dlg.exec())
1362         return;
1363 
1364     QDBusReply<QDBusObjectPath> cvsJobPath = cvsService->createRepository(dlg.directory());
1365     QDBusObjectPath cvsJob = cvsJobPath;
1366     QString cmdline;
1367     if (cvsJob.path().isEmpty())
1368         return;
1369     OrgKdeCervisia5CvsserviceCvsjobInterface cvsjobinterface(m_cvsServiceInterfaceName, cvsJob.path(), QDBusConnection::sessionBus(), this);
1370     QDBusReply<QString> reply = cvsjobinterface.cvsCommand();
1371 
1372     if (reply.isValid())
1373         cmdline = reply;
1374 
1375     if (protocol->startJob()) {
1376         showJobStart(cmdline);
1377         connect(protocol, SIGNAL(jobFinished(bool, int)), this, SLOT(slotJobFinished()));
1378     }
1379 }
1380 
1381 void CervisiaPart::slotCheckout()
1382 {
1383     CheckoutDialog dlg(*config(), cvsService, CheckoutDialog::Checkout, widget());
1384 
1385     if (!dlg.exec())
1386         return;
1387 
1388     QDBusReply<QDBusObjectPath> cvsJobPath =
1389         cvsService
1390             ->checkout(dlg.workingDirectory(), dlg.repository(), dlg.module(), dlg.branch(), opt_pruneDirs, dlg.alias(), dlg.exportOnly(), dlg.recursive());
1391     QDBusObjectPath cvsJob = cvsJobPath;
1392     QString cmdline;
1393     OrgKdeCervisia5CvsserviceCvsjobInterface cvsjobinterface(m_cvsServiceInterfaceName, cvsJob.path(), QDBusConnection::sessionBus(), this);
1394     QDBusReply<QString> reply = cvsjobinterface.cvsCommand();
1395 
1396     if (reply.isValid())
1397         cmdline = reply;
1398 
1399     if (protocol->startJob()) {
1400         showJobStart(cmdline);
1401         connect(protocol, SIGNAL(jobFinished(bool, int)), this, SLOT(slotJobFinished()));
1402     }
1403 }
1404 
1405 void CervisiaPart::slotRepositories()
1406 {
1407     auto l = new RepositoryDialog(*config(), cvsService, m_cvsServiceInterfaceName, widget());
1408     l->show();
1409 }
1410 
1411 void CervisiaPart::slotCreateTag()
1412 {
1413     createOrDeleteTag(TagDialog::Create);
1414 }
1415 
1416 void CervisiaPart::slotDeleteTag()
1417 {
1418     createOrDeleteTag(TagDialog::Delete);
1419 }
1420 
1421 void CervisiaPart::createOrDeleteTag(TagDialog::ActionType action)
1422 {
1423     QStringList list = update->multipleSelection();
1424     if (list.isEmpty())
1425         return;
1426 
1427     TagDialog dlg(action, cvsService, widget());
1428 
1429     if (dlg.exec()) {
1430         QDBusReply<QDBusObjectPath> cvsJob;
1431 
1432         if (action == TagDialog::Create)
1433             cvsJob = cvsService->createTag(list, dlg.tag(), dlg.branchTag(), dlg.forceTag());
1434         else
1435             cvsJob = cvsService->deleteTag(list, dlg.tag(), dlg.branchTag(), dlg.forceTag());
1436         QDBusObjectPath cvsJobPath = cvsJob;
1437         QString cmdline;
1438         OrgKdeCervisia5CvsserviceCvsjobInterface cvsjobinterface(m_cvsServiceInterfaceName, cvsJobPath.path(), QDBusConnection::sessionBus(), this);
1439         QDBusReply<QString> reply = cvsjobinterface.cvsCommand();
1440 
1441         if (reply.isValid())
1442             cmdline = reply;
1443 
1444         if (protocol->startJob()) {
1445             showJobStart(cmdline);
1446             connect(protocol, SIGNAL(jobFinished(bool, int)), this, SLOT(slotJobFinished()));
1447         }
1448     }
1449 }
1450 
1451 void CervisiaPart::slotLastChange()
1452 {
1453     QString filename, revA, revB;
1454     update->getSingleSelection(&filename, &revA);
1455     if (filename.isEmpty())
1456         return;
1457 
1458     int pos, lastnumber = 0;
1459     bool ok;
1460     if ((pos = revA.lastIndexOf('.')) == -1 || (lastnumber = revA.right(revA.length() - pos - 1).toUInt(&ok), !ok)) {
1461         KMessageBox::error(widget(), i18n("The revision looks invalid."), "Cervisia");
1462         return;
1463     }
1464     if (lastnumber == 0) {
1465         KMessageBox::error(widget(), i18n("This is the first revision of the branch."), "Cervisia");
1466         return;
1467     }
1468     revB = revA.left(pos + 1);
1469     revB += QString::number(lastnumber - 1);
1470 
1471     // Non-modal dialog
1472     auto l = new DiffDialog(*config());
1473     if (l->parseCvsDiff(cvsService, filename, revB, revA))
1474         l->show();
1475     else
1476         delete l;
1477 }
1478 
1479 void CervisiaPart::slotHistory()
1480 {
1481     // Non-modal dialog
1482     auto l = new HistoryDialog(*config());
1483     if (l->parseHistory(cvsService))
1484         l->show();
1485     else
1486         delete l;
1487 }
1488 
1489 void CervisiaPart::slotHideFiles()
1490 {
1491     opt_hideFiles = !opt_hideFiles;
1492     setFilter();
1493 }
1494 
1495 void CervisiaPart::slotHideUpToDate()
1496 {
1497     opt_hideUpToDate = !opt_hideUpToDate;
1498     setFilter();
1499 }
1500 
1501 void CervisiaPart::slotHideRemoved()
1502 {
1503     opt_hideRemoved = !opt_hideRemoved;
1504     setFilter();
1505 }
1506 
1507 void CervisiaPart::slotHideNotInCVS()
1508 {
1509     opt_hideNotInCVS = !opt_hideNotInCVS;
1510     setFilter();
1511 }
1512 
1513 void CervisiaPart::slotHideEmptyDirectories()
1514 {
1515     opt_hideEmptyDirectories = !opt_hideEmptyDirectories;
1516     setFilter();
1517 }
1518 
1519 void CervisiaPart::slotFoldTree()
1520 {
1521     update->foldTree();
1522     setFilter();
1523 }
1524 
1525 void CervisiaPart::slotUnfoldTree()
1526 {
1527     update->unfoldTree();
1528     setFilter();
1529 }
1530 
1531 void CervisiaPart::slotUnfoldFolder()
1532 {
1533     update->unfoldSelectedFolders();
1534     setFilter();
1535 }
1536 
1537 void CervisiaPart::slotCreateDirs()
1538 {
1539     opt_createDirs = !opt_createDirs;
1540 }
1541 
1542 void CervisiaPart::slotPruneDirs()
1543 {
1544     opt_pruneDirs = !opt_pruneDirs;
1545 }
1546 
1547 void CervisiaPart::slotUpdateRecursive()
1548 {
1549     opt_updateRecursive = !opt_updateRecursive;
1550 }
1551 
1552 void CervisiaPart::slotCommitRecursive()
1553 {
1554     opt_commitRecursive = !opt_commitRecursive;
1555 }
1556 
1557 void CervisiaPart::slotDoCVSEdit()
1558 {
1559     opt_doCVSEdit = !opt_doCVSEdit;
1560 }
1561 
1562 void CervisiaPart::slotConfigure()
1563 {
1564     KConfig *conf = config();
1565     auto l = new SettingsDialog(conf, widget());
1566     l->exec();
1567 
1568     bool splitHorz = conf->group("LookAndFeel").readEntry("SplitHorizontally", true);
1569     splitter->setOrientation(splitHorz ? Qt::Vertical : Qt::Horizontal);
1570     delete l;
1571 }
1572 
1573 void CervisiaPart::slotCVSInfo()
1574 {
1575     emit setStatusBarText(i18n("Invoking help on CVS"));
1576     auto job = new KIO::ApplicationLauncherJob(KService::serviceByDesktopName("org.kde.khelpcenter"));
1577     job->setUrls({QUrl(QStringLiteral("man:/(1)/cvs"))});
1578     job->start();
1579 }
1580 
1581 void CervisiaPart::showJobStart(const QString &cmdline)
1582 {
1583     hasRunningJob = true;
1584     actionCollection()->action("stop_job")->setEnabled(true);
1585 
1586     emit setStatusBarText(cmdline);
1587     updateActions();
1588 }
1589 
1590 void CervisiaPart::showDiff(const QString &revision)
1591 {
1592     QString fileName;
1593     update->getSingleSelection(&fileName);
1594 
1595     if (fileName.isEmpty())
1596         return;
1597 
1598     // Non-modal dialog
1599     auto l = new DiffDialog(*config());
1600     if (l->parseCvsDiff(cvsService, fileName, revision, QString()))
1601         l->show();
1602     else
1603         delete l;
1604 }
1605 
1606 void CervisiaPart::slotJobFinished()
1607 {
1608     actionCollection()->action("stop_job")->setEnabled(false);
1609     hasRunningJob = false;
1610     emit setStatusBarText(i18n("Done"));
1611     updateActions();
1612 
1613     disconnect(protocol, SIGNAL(receivedLine(QString)), update, SLOT(processUpdateLine(QString)));
1614 
1615     if (m_jobType == Commit) {
1616         KNotification::event("cvs_commit_done", i18n("A CVS commit to repository %1 is done", repository), QPixmap(), widget()->parentWidget());
1617         m_jobType = Unknown;
1618     }
1619 }
1620 
1621 bool CervisiaPart::openSandbox(const QUrl &url)
1622 {
1623     // Do we have a cvs service?
1624     if (!cvsService)
1625         return false;
1626     OrgKdeCervisia5RepositoryInterface cvsRepository(m_cvsServiceInterfaceName, "/CvsRepository", QDBusConnection::sessionBus());
1627 
1628     // change the working copy directory for the cvs D-Bus service
1629     QDBusReply<bool> reply = cvsRepository.setWorkingCopy(url.path());
1630 
1631     if (!reply.isValid() || !reply.value()) {
1632         KMessageBox::error(widget(),
1633                            i18n("This is not a CVS folder.\n"
1634                                 "If you did not intend to use Cervisia, you can "
1635                                 "switch view modes within Konqueror."),
1636                            "Cervisia");
1637 
1638         // remove path from recent sandbox menu
1639         recent->removeUrl(url);
1640 
1641         return false;
1642     }
1643 
1644     changelogstr = "";
1645     sandbox = "";
1646     repository = "";
1647 
1648     // get path of sandbox for recent sandbox menu
1649     sandbox = cvsRepository.workingCopy();
1650     recent->addUrl(url);
1651 
1652     // get repository for the caption of the window
1653     repository = cvsRepository.location();
1654     emit setWindowCaption(sandbox + '(' + repository + ')');
1655 
1656     // set m_url member for tabbed window modus of Konqueror
1657     setUrl(url);
1658 
1659     // *NOTICE*
1660     // The order is important here. We have to set the url member before
1661     // calling this function because the progress dialog uses the enter_loop()/
1662     // exit_loop() methods. Those methods result in a call to queryExit() in
1663     // cervisiashell.cpp which then uses the url member to save the last used
1664     // directory.
1665     if (cvsRepository.retrieveCvsignoreFile())
1666         Cervisia::GlobalIgnoreList().retrieveServerIgnoreList(cvsService, repository);
1667     QDir::setCurrent(sandbox);
1668     update->openDirectory(sandbox);
1669     setFilter();
1670 
1671     KConfig *conf = config();
1672     bool dostatus = conf->group("General").readEntry(repository.contains(":") ? "StatusForRemoteRepos" : "StatusForLocalRepos", false);
1673     if (dostatus) {
1674         update->topLevelItem(0)->setSelected(true);
1675         slotStatus();
1676     }
1677 
1678     // load the recentCommits for this app from the KConfig app
1679     recentCommits = conf->group("CommitLogs").readEntry(sandbox, QStringList());
1680 
1681     return true;
1682 }
1683 
1684 void CervisiaPart::setFilter()
1685 {
1686     auto filter = UpdateView::Filter(0);
1687     if (opt_hideFiles)
1688         filter = UpdateView::Filter(filter | UpdateView::OnlyDirectories);
1689     if (opt_hideUpToDate)
1690         filter = UpdateView::Filter(filter | UpdateView::NoUpToDate);
1691     if (opt_hideRemoved)
1692         filter = UpdateView::Filter(filter | UpdateView::NoRemoved);
1693     if (opt_hideNotInCVS)
1694         filter = UpdateView::Filter(filter | UpdateView::NoNotInCVS);
1695     if (opt_hideEmptyDirectories)
1696         filter = UpdateView::Filter(filter | UpdateView::NoEmptyDirectories);
1697     update->setFilter(filter);
1698 
1699     QString str;
1700     if (opt_hideFiles)
1701         str = 'F';
1702     else {
1703         if (opt_hideUpToDate)
1704             str += 'N';
1705         if (opt_hideRemoved)
1706             str += 'R';
1707     }
1708 
1709     if (filterLabel)
1710         filterLabel->setText(str);
1711 }
1712 
1713 void CervisiaPart::readSettings()
1714 {
1715     const KConfigGroup config(this->config(), "Session");
1716     recent->loadEntries(config);
1717 
1718     // Unfortunately, the KConfig systems sucks and we have to live
1719     // with all entries in one group for session management.
1720 
1721     opt_createDirs = config.readEntry("Create Dirs", true);
1722     (static_cast<KToggleAction *>(actionCollection()->action("settings_create_dirs")))->setChecked(opt_createDirs);
1723 
1724     opt_pruneDirs = config.readEntry("Prune Dirs", true);
1725     (static_cast<KToggleAction *>(actionCollection()->action("settings_prune_dirs")))->setChecked(opt_pruneDirs);
1726 
1727     opt_updateRecursive = config.readEntry("Update Recursive", false);
1728     (static_cast<KToggleAction *>(actionCollection()->action("settings_update_recursively")))->setChecked(opt_updateRecursive);
1729 
1730     opt_commitRecursive = config.readEntry("Commit Recursive", false);
1731     (static_cast<KToggleAction *>(actionCollection()->action("settings_commit_recursively")))->setChecked(opt_commitRecursive);
1732 
1733     opt_doCVSEdit = config.readEntry("Do cvs edit", false);
1734     (static_cast<KToggleAction *>(actionCollection()->action("settings_do_cvs_edit")))->setChecked(opt_doCVSEdit);
1735 
1736     opt_hideFiles = config.readEntry("Hide Files", false);
1737     (static_cast<KToggleAction *>(actionCollection()->action("settings_hide_files")))->setChecked(opt_hideFiles);
1738 
1739     opt_hideUpToDate = config.readEntry("Hide UpToDate Files", false);
1740     (static_cast<KToggleAction *>(actionCollection()->action("settings_hide_uptodate")))->setChecked(opt_hideUpToDate);
1741 
1742     opt_hideRemoved = config.readEntry("Hide Removed Files", false);
1743     (static_cast<KToggleAction *>(actionCollection()->action("settings_hide_removed")))->setChecked(opt_hideRemoved);
1744 
1745     opt_hideNotInCVS = config.readEntry("Hide Non CVS Files", false);
1746     (static_cast<KToggleAction *>(actionCollection()->action("settings_hide_notincvs")))->setChecked(opt_hideNotInCVS);
1747 
1748     opt_hideEmptyDirectories = config.readEntry("Hide Empty Directories", false);
1749     (static_cast<KToggleAction *>(actionCollection()->action("settings_hide_empty_directories")))->setChecked(opt_hideEmptyDirectories);
1750 
1751     setFilter();
1752 
1753     int splitterpos1 = config.readEntry("Splitter Pos 1", 0);
1754     int splitterpos2 = config.readEntry("Splitter Pos 2", 0);
1755     if (splitterpos1) {
1756         QList<int> sizes;
1757         sizes << splitterpos1;
1758         sizes << splitterpos2;
1759         splitter->setSizes(sizes);
1760     }
1761 }
1762 
1763 void CervisiaPart::writeSettings()
1764 {
1765     KConfigGroup config(this->config(), "Session");
1766     recent->saveEntries(config);
1767 
1768     config.writeEntry("Create Dirs", opt_createDirs);
1769     config.writeEntry("Prune Dirs", opt_pruneDirs);
1770     config.writeEntry("Update Recursive", opt_updateRecursive);
1771     config.writeEntry("Commit Recursive", opt_commitRecursive);
1772     config.writeEntry("Do cvs edit", opt_doCVSEdit);
1773     config.writeEntry("Hide Files", opt_hideFiles);
1774     config.writeEntry("Hide UpToDate Files", opt_hideUpToDate);
1775     config.writeEntry("Hide Removed Files", opt_hideRemoved);
1776     config.writeEntry("Hide Non CVS Files", opt_hideNotInCVS);
1777     config.writeEntry("Hide Empty Directories", opt_hideEmptyDirectories);
1778     QList<int> sizes = splitter->sizes();
1779     config.writeEntry("Splitter Pos 1", sizes[0]);
1780     config.writeEntry("Splitter Pos 2", sizes[1]);
1781 
1782     // write to disk
1783     config.sync();
1784 }
1785 
1786 void CervisiaPart::guiActivateEvent(KParts::GUIActivateEvent *event)
1787 {
1788     if (event->activated() && cvsService) {
1789         // initial setup of the menu items' state
1790         updateActions();
1791     }
1792 
1793     // don't call this as it overwrites Konqueror's caption (if you have a
1794     // Konqueror with more than one view and switch back to Cervisia)
1795     //
1796     // KParts::ReadOnlyPart::guiActivateEvent(event);
1797 }
1798 
1799 CervisiaBrowserExtension::CervisiaBrowserExtension(CervisiaPart *p)
1800     : KParts::BrowserExtension(p)
1801 {
1802 }
1803 
1804 CervisiaBrowserExtension::~CervisiaBrowserExtension() = default;
1805 
1806 // Local Variables:
1807 // c-basic-offset: 4
1808 // End: