File indexing completed on 2025-01-26 05:24:16

0001 /*
0002     This file is part of the Kasten Framework, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2008 Friedrich W. H. Kossebau <kossebau@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007 */
0008 
0009 #include "versioncontroller.hpp"
0010 
0011 // Kasten core
0012 #include <Kasten/DocumentVersionData>
0013 #include <Kasten/Versionable>
0014 #include <Kasten/AbstractModel>
0015 // KF
0016 #include <KXMLGUIClient>
0017 #include <KLocalizedString>
0018 #include <KActionCollection>
0019 #include <KToolBarPopupAction>
0020 #include <KStandardShortcut>
0021 // Qt
0022 #include <QMenu>
0023 
0024 namespace Kasten {
0025 
0026 static constexpr int MaxMenuEntries = 10;
0027 
0028 VersionController::VersionController(KXMLGUIClient* guiClient)
0029 {
0030     KActionCollection* actionCollection = guiClient->actionCollection();
0031 
0032     mSetToOlderVersionAction = new KToolBarPopupAction(QIcon::fromTheme(QStringLiteral("edit-undo")), i18nc("@action:inmenu", "Undo"), this);
0033     actionCollection->addAction(QStringLiteral("edit_undo"), mSetToOlderVersionAction);
0034     actionCollection->setDefaultShortcuts(mSetToOlderVersionAction, KStandardShortcut::undo());
0035 
0036     connect(mSetToOlderVersionAction, &QAction::triggered,
0037             this, &VersionController::onSetToOlderVersionTriggered);
0038     connect(mSetToOlderVersionAction->menu(), &QMenu::aboutToShow,
0039             this, &VersionController::onOlderVersionMenuAboutToShow);
0040     connect(mSetToOlderVersionAction->menu(), &QMenu::triggered,
0041             this, &VersionController::onOlderVersionMenuTriggered);
0042 
0043     mSetToNewerVersionAction = new KToolBarPopupAction(QIcon::fromTheme(QStringLiteral("edit-redo")), i18nc("@action:inmenu", "Redo"), this);
0044     actionCollection->addAction(QStringLiteral("edit_redo"), mSetToNewerVersionAction);
0045     actionCollection->setDefaultShortcuts(mSetToNewerVersionAction, KStandardShortcut::redo());
0046 
0047     connect(mSetToNewerVersionAction, &QAction::triggered,
0048             this, &VersionController::onSetToNewerVersionTriggered);
0049     connect(mSetToNewerVersionAction->menu(), &QMenu::aboutToShow,
0050             this, &VersionController::onNewerVersionMenuAboutToShow);
0051     connect(mSetToNewerVersionAction->menu(), &QMenu::triggered,
0052             this, &VersionController::onNewerVersionMenuTriggered);
0053 
0054     setTargetModel(nullptr);
0055 }
0056 
0057 void VersionController::setTargetModel(AbstractModel* model)
0058 {
0059     if (mModel) {
0060         mModel->disconnect(this);
0061         AbstractModel* versionedModel = mModel->findBaseModelWithInterface<If::Versionable*>();
0062         if (versionedModel) {
0063             versionedModel->disconnect(this);
0064         }
0065     }
0066 
0067     mModel = model;
0068     AbstractModel* versionedModel = mModel ? mModel->findBaseModelWithInterface<If::Versionable*>() : nullptr;
0069     mVersionControl = versionedModel ? qobject_cast<If::Versionable*>(versionedModel) : nullptr;
0070 
0071     if (mVersionControl) {
0072         connect(versionedModel, SIGNAL(revertedToVersionIndex(int)), SLOT(onVersionIndexChanged(int)));
0073         connect(versionedModel, SIGNAL(headVersionChanged(int)),     SLOT(onVersionIndexChanged(int)));
0074         connect(mModel, &AbstractModel::readOnlyChanged,
0075                 this, &VersionController::onReadOnlyChanged);
0076     } else {
0077         mModel = nullptr;
0078     }
0079 
0080     const bool isVersionable = (mVersionControl && !mModel->isReadOnly());
0081 
0082     if (isVersionable) {
0083         onVersionIndexChanged(mVersionControl->versionIndex());
0084     } else {
0085         mSetToOlderVersionAction->setEnabled(false);
0086         mSetToNewerVersionAction->setEnabled(false);
0087     }
0088 }
0089 
0090 void VersionController::onVersionIndexChanged(int versionIndex)
0091 {
0092     const bool hasOlderVersions = (versionIndex > 0);
0093     mSetToOlderVersionAction->setEnabled(hasOlderVersions);
0094     if (hasOlderVersions) {
0095         mSetToOlderVersionAction->setData(versionIndex - 1);
0096     }
0097 
0098     const bool hasNewerVersions = (versionIndex < (mVersionControl->versionCount() - 1));
0099     mSetToNewerVersionAction->setEnabled(hasNewerVersions);
0100     if (hasNewerVersions) {
0101         mSetToNewerVersionAction->setData(versionIndex + 1);
0102     }
0103 }
0104 
0105 void VersionController::onSetToOlderVersionTriggered()
0106 {
0107     const int versionIndex = mSetToOlderVersionAction->data().toInt();
0108     mVersionControl->revertToVersionByIndex(versionIndex);
0109 }
0110 
0111 void VersionController::onSetToNewerVersionTriggered()
0112 {
0113     const int versionIndex = mSetToNewerVersionAction->data().toInt();
0114     mVersionControl->revertToVersionByIndex(versionIndex);
0115 }
0116 
0117 void VersionController::onOlderVersionMenuAboutToShow()
0118 {
0119     QMenu* menu = mSetToOlderVersionAction->menu();
0120     menu->clear();
0121 
0122     int menuEntries = 0;
0123     for (int versionIndex = mVersionControl->versionIndex();
0124          versionIndex > 0 && menuEntries < MaxMenuEntries;
0125          --versionIndex, ++menuEntries) {
0126         DocumentVersionData versionData = mVersionControl->versionData(versionIndex);
0127 
0128         const QString changeComment = versionData.changeComment();
0129 
0130         const QString actionText = i18nc("@action Undo: [change]", "Undo: %1", changeComment);
0131 
0132         QAction* action = menu->addAction(actionText);
0133         action->setData(versionIndex - 1);
0134     }
0135 }
0136 
0137 void VersionController::onNewerVersionMenuAboutToShow()
0138 {
0139     QMenu* menu = mSetToNewerVersionAction->menu();
0140     menu->clear();
0141 
0142     int menuEntries = 0;
0143     for (int versionIndex = mVersionControl->versionIndex() + 1;
0144          versionIndex < mVersionControl->versionCount() && menuEntries < MaxMenuEntries;
0145          ++versionIndex, ++menuEntries) {
0146         DocumentVersionData versionData = mVersionControl->versionData(versionIndex);
0147 
0148         const QString changeComment = versionData.changeComment();
0149 
0150         const QString actionText = i18nc("@action Redo: [change]", "Redo: %1", changeComment);
0151 
0152         QAction* action = menu->addAction(actionText);
0153         action->setData(versionIndex);
0154     }
0155 }
0156 
0157 void VersionController::onOlderVersionMenuTriggered(QAction* action)
0158 {
0159     const int versionIndex = action->data().toInt();
0160     mVersionControl->revertToVersionByIndex(versionIndex);
0161 }
0162 
0163 void VersionController::onNewerVersionMenuTriggered(QAction* action)
0164 {
0165     const int versionIndex = action->data().toInt();
0166     mVersionControl->revertToVersionByIndex(versionIndex);
0167 }
0168 
0169 void VersionController::onReadOnlyChanged(bool isReadOnly)
0170 {
0171     if (isReadOnly) {
0172         mSetToOlderVersionAction->setEnabled(false);
0173         mSetToNewerVersionAction->setEnabled(false);
0174     } else {
0175         onVersionIndexChanged(mVersionControl->versionIndex());
0176     }
0177 }
0178 
0179 }
0180 
0181 #include "moc_versioncontroller.cpp"