File indexing completed on 2024-05-05 05:56:43

0001 /*
0002     This file is part of the Okteta KPart module, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2003, 2007, 2009, 2011, 2019 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 "part.hpp"
0010 
0011 // part
0012 #include "partfactory.hpp"
0013 #include "browserextension.hpp"
0014 // Okteta Kasten controllers
0015 // #include <Kasten/Okteta/OverwriteOnlyControllerFactory>
0016 #include <Kasten/Okteta/OverwriteModeControllerFactory>
0017 #include <Kasten/Okteta/GotoOffsetControllerFactory>
0018 #include <Kasten/Okteta/SelectRangeControllerFactory>
0019 #include <Kasten/Okteta/SearchControllerFactory>
0020 #include <Kasten/Okteta/ReplaceControllerFactory>
0021 #include <Kasten/Okteta/BookmarksControllerFactory>
0022 #include <Kasten/Okteta/PrintControllerFactory>
0023 #include <Kasten/Okteta/ViewConfigControllerFactory>
0024 #include <Kasten/Okteta/ViewModeControllerFactory>
0025 #include <Kasten/Okteta/ViewContextMenuControllerFactory>
0026 #include <Kasten/Okteta/ViewStatusControllerFactory>
0027 #include <Kasten/Okteta/ViewProfileControllerFactory>
0028 // Okteta Kasten
0029 #include <Kasten/Okteta/ByteArrayDocument>
0030 #include <Kasten/Okteta/ByteArrayView>
0031 #include <Kasten/Okteta/ByteArrayViewProfileSynchronizer>
0032 #include <Kasten/Okteta/ByteArrayViewProfileManager>
0033 #include <Kasten/Okteta/ByteArrayRawFileSynchronizerFactory>
0034 // Kasten controllers
0035 #include <Kasten/ReadOnlyControllerFactory>
0036 // #include <Kasten/ReadOnlyBarController>
0037 // #include <Kasten/SynchronizeController>
0038 #include <Kasten/ClipboardControllerFactory>
0039 #include <Kasten/InsertControllerFactory>
0040 #include <Kasten/CopyAsControllerFactory>
0041 #include <Kasten/ExportControllerFactory>
0042 #include <Kasten/VersionControllerFactory>
0043 #include <Kasten/ZoomControllerFactory>
0044 // #include <Kasten/ZoomBarControllerFactory>
0045 #include <Kasten/SelectControllerFactory>
0046 // Kasten
0047 #include <Kasten/SingleViewArea>
0048 #include <Kasten/AbstractXmlGuiController>
0049 #include <Kasten/JobManager>
0050 #include <Kasten/AbstractLoadJob>
0051 #include <Kasten/AbstractSyncWithRemoteJob>
0052 // KF
0053 #include <KPluginMetaData>
0054 // Qt
0055 #include <QWidget>
0056 #include <QVBoxLayout>
0057 #include <QUrl>
0058 // Std
0059 #include <utility>
0060 
0061 static constexpr const char* UIFileName[] =
0062 {
0063     "oktetapartreadonlyui.rc",
0064     "oktetapartbrowserui.rc",
0065     "oktetapartreadwriteui.rc"
0066 };
0067 
0068 OktetaPart::OktetaPart(QObject* parent,
0069                        const KPluginMetaData& metaData,
0070                        Modus modus,
0071                        Kasten::ByteArrayViewProfileManager* viewProfileManager,
0072                        Kasten::ModelCodecManager* modelCodecManager,
0073                        Kasten::ModelCodecViewManager* modelCodecViewManager)
0074     : KParts::ReadWritePart(parent)
0075     , mModus(modus)
0076     , mViewProfileManager(viewProfileManager)
0077 {
0078     setMetaData(metaData);
0079 
0080     auto* widget = new QWidget();
0081     mLayout = new QVBoxLayout(widget);
0082     mLayout->setContentsMargins(0, 0, 0, 0);
0083 
0084     setWidget(widget);
0085 
0086     setXMLFile(QLatin1String(UIFileName[modus]));
0087 
0088     mSingleViewArea = new Kasten::SingleViewArea();
0089     QWidget* areaWidget = mSingleViewArea->widget();
0090     mLayout->addWidget(areaWidget);
0091     mLayout->parentWidget()->setFocusProxy(areaWidget);
0092 
0093     if (modus == Modus::ReadWrite) {
0094         addController(Kasten::VersionControllerFactory());
0095     }
0096     if (modus == Modus::ReadWrite) {
0097         addController(Kasten::ReadOnlyControllerFactory());
0098     }
0099     // TODO: save_as
0100     addController(Kasten::ExportControllerFactory(modelCodecViewManager, modelCodecManager));
0101     addController(Kasten::ZoomControllerFactory());
0102     addController(Kasten::SelectControllerFactory());
0103     if (modus != Modus::BrowserView) {
0104         addController(Kasten::ClipboardControllerFactory());
0105     }
0106     if (modus == Modus::ReadWrite) {
0107         addController(Kasten::InsertControllerFactory(modelCodecViewManager, modelCodecManager));
0108     }
0109     addController(Kasten::CopyAsControllerFactory(modelCodecViewManager, modelCodecManager));
0110     if (modus == Modus::ReadWrite) {
0111         addController(Kasten::OverwriteModeControllerFactory());
0112     }
0113     addController(Kasten::SearchControllerFactory(widget));
0114     if (modus == Modus::ReadWrite) {
0115         addController(Kasten::ReplaceControllerFactory(widget));
0116     }
0117     addController(Kasten::GotoOffsetControllerFactory(mSingleViewArea));
0118     addController(Kasten::SelectRangeControllerFactory(mSingleViewArea));
0119 //     addController(Kasten::BookmarksControllerFactory());
0120     addController(Kasten::PrintControllerFactory());
0121     addController(Kasten::ViewConfigControllerFactory());
0122     addController(Kasten::ViewModeControllerFactory());
0123     addController(Kasten::ViewContextMenuControllerFactory());
0124     addController(Kasten::ViewProfileControllerFactory(mViewProfileManager, widget));
0125 
0126 //     Kasten::StatusBar* bottomBar = static_cast<Kasten::StatusBar*>( statusBar() );
0127 //     addController(ViewStatusControllerFactory(bottomBar) );
0128 //     addController(ReadOnlyBarControllerFactory(bottomBar) );
0129 //     addController(ZoomBarControllerFactory(bottomBar) );
0130 
0131 //     addTool( new DocumentInfoToolView(new DocumentInfoTool(mProgram->documentManager()->syncManager())) );
0132 //     addTool( new ChecksumToolView(new ChecksumTool()) );
0133 //     addTool( new FilterToolView(new FilterTool()) );
0134 //     addTool( new StringsExtractToolView(new StringsExtractTool()) );
0135 //     addTool( new ByteTableToolView(new ByteTableTool()) );
0136 //     addTool( new InfoToolView(new InfoTool()) );
0137 //     addTool( new PODDecoderToolView(new PODDecoderTool()) );
0138 //     addTool( new BookmarksToolView(new BookmarksTool()) );
0139 
0140     // TODO: BrowserExtension might rely on existing objects (session snap while loadJob),
0141     // so this hack just creates some dummies
0142     mDocument = new Kasten::ByteArrayDocument(QString());
0143     auto* viewProfileSynchronizer = new Kasten::ByteArrayViewProfileSynchronizer(viewProfileManager);
0144     mByteArrayView = new Kasten::ByteArrayView(mDocument, viewProfileSynchronizer);
0145 
0146     if (modus == Modus::BrowserView) {
0147         new OktetaBrowserExtension(this);
0148     }
0149 }
0150 
0151 OktetaPart::~OktetaPart()
0152 {
0153     qDeleteAll(mControllers);
0154     delete mSingleViewArea;
0155     delete mByteArrayView;
0156     delete mDocument;
0157 }
0158 
0159 void OktetaPart::addController(const Kasten::AbstractXmlGuiControllerFactory& factory)
0160 {
0161     Kasten::AbstractXmlGuiController* controller = factory.create(this);
0162     mControllers.append(controller);
0163 }
0164 
0165 void OktetaPart::setReadWrite(bool readWrite)
0166 {
0167     mDocument->setReadOnly(!readWrite);
0168 
0169     KParts::ReadWritePart::setReadWrite(readWrite);   // TODO: call to super needed?
0170 }
0171 
0172 bool OktetaPart::openFile()
0173 {
0174     auto* synchronizerFactory = new Kasten::ByteArrayRawFileSynchronizerFactory();
0175     Kasten::AbstractModelSynchronizer* synchronizer = synchronizerFactory->createSynchronizer();
0176 
0177     Kasten::AbstractLoadJob* loadJob = synchronizer->startLoad(QUrl::fromLocalFile(localFilePath()));
0178     connect(loadJob, &Kasten::AbstractLoadJob::documentLoaded,
0179             this, &OktetaPart::onDocumentLoaded);
0180     Kasten::JobManager::executeJob(loadJob);
0181 
0182     delete synchronizerFactory;
0183 
0184     return true;
0185 }
0186 
0187 bool OktetaPart::saveFile()
0188 {
0189     Kasten::AbstractModelSynchronizer* synchronizer = mDocument->synchronizer();
0190 
0191     Kasten::AbstractSyncWithRemoteJob* syncJob =
0192         synchronizer->startSyncWithRemote(QUrl::fromLocalFile(localFilePath()), Kasten::AbstractModelSynchronizer::ReplaceRemote);
0193     const bool syncSucceeded = Kasten::JobManager::executeJob(syncJob);
0194 
0195     return syncSucceeded;
0196 }
0197 
0198 void OktetaPart::onDocumentLoaded(Kasten::AbstractDocument* document)
0199 {
0200     if (document) {
0201         for (Kasten::AbstractXmlGuiController* controller : std::as_const(mControllers)) {
0202             controller->setTargetModel(nullptr);
0203         }
0204         mSingleViewArea->setView(nullptr);
0205         delete mByteArrayView;
0206         delete mDocument;
0207 
0208         mDocument = static_cast<Kasten::ByteArrayDocument*>(document);
0209         mDocument->setReadOnly(mModus != Modus::ReadWrite);
0210         connect(mDocument->synchronizer(), &Kasten::AbstractModelSynchronizer::localSyncStateChanged,
0211                 this, &OktetaPart::onModified);
0212 
0213         auto* viewProfileSynchronizer = new Kasten::ByteArrayViewProfileSynchronizer(mViewProfileManager);
0214         viewProfileSynchronizer->setViewProfileId(mViewProfileManager->defaultViewProfileId());
0215 
0216         mByteArrayView = new Kasten::ByteArrayView(mDocument, viewProfileSynchronizer);
0217         connect(mByteArrayView, SIGNAL(hasSelectedDataChanged(bool)), SIGNAL(hasSelectedDataChanged(bool)));
0218 
0219         mSingleViewArea->setView(mByteArrayView);
0220 
0221         for (Kasten::AbstractXmlGuiController* controller : std::as_const(mControllers)) {
0222             controller->setTargetModel(mByteArrayView);
0223         }
0224 
0225         setModified(false);
0226     }
0227 }
0228 
0229 void OktetaPart::onModified(Kasten::LocalSyncState state)
0230 {
0231     const bool isModified = (state != Kasten::LocalInSync);
0232     setModified(isModified);
0233 }
0234 
0235 #include "moc_part.cpp"