File indexing completed on 2024-04-28 17:08:12

0001 /*
0002     This file is part of the Okteta program, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2006-2011 Friedrich W. H. Kossebau <kossebau@kde.org>
0005 
0006     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0007 */
0008 
0009 #include "mainwindow.hpp"
0010 
0011 // program
0012 #include "program.hpp"
0013 // tmp
0014 #include <Kasten/Okteta/ByteArrayViewProfileManager>
0015 // tools
0016 #include <Kasten/Okteta/StringsExtractToolViewFactory>
0017 #include <Kasten/Okteta/StringsExtractToolFactory>
0018 #include <Kasten/Okteta/InfoToolViewFactory>
0019 #include <Kasten/Okteta/InfoToolFactory>
0020 #include <Kasten/Okteta/FilterToolViewFactory>
0021 #include <Kasten/Okteta/FilterToolFactory>
0022 #include <Kasten/Okteta/CharsetConversionToolViewFactory>
0023 #include <Kasten/Okteta/CharsetConversionToolFactory>
0024 #include <Kasten/Okteta/ChecksumToolViewFactory>
0025 #include <Kasten/Okteta/ChecksumToolFactory>
0026 #include <Kasten/Okteta/DocumentInfoToolViewFactory>
0027 #include <Kasten/Okteta/DocumentInfoToolFactory>
0028 #include <Kasten/Okteta/PODDecoderToolViewFactory>
0029 #include <Kasten/Okteta/PODDecoderToolFactory>
0030 #include <Kasten/Okteta/ByteTableToolViewFactory>
0031 #include <Kasten/Okteta/ByteTableToolFactory>
0032 #include <Kasten/Okteta/BookmarksToolViewFactory>
0033 #include <Kasten/Okteta/BookmarksToolFactory>
0034 #include <Kasten/Okteta/StructuresToolViewFactory>
0035 #include <Kasten/Okteta/StructuresToolFactory>
0036 
0037 // Kasten tools
0038 #include <Kasten/VersionViewToolViewFactory>
0039 #include <Kasten/VersionViewToolFactory>
0040 #include <Kasten/FileSystemBrowserToolViewFactory>
0041 #include <Kasten/FileSystemBrowserToolFactory>
0042 #include <Kasten/DocumentsToolViewFactory>
0043 #include <Kasten/DocumentsToolFactory>
0044 #include <Kasten/TerminalToolViewFactory>
0045 #include <Kasten/TerminalToolFactory>
0046 // controllers
0047 // #include <Kasten/Okteta/OverwriteOnlyControllerFactory>
0048 #include <Kasten/Okteta/OverwriteModeControllerFactory>
0049 #include <Kasten/Okteta/GotoOffsetControllerFactory>
0050 #include <Kasten/Okteta/SelectRangeControllerFactory>
0051 #include <Kasten/Okteta/SearchControllerFactory>
0052 #include <Kasten/Okteta/ReplaceControllerFactory>
0053 #include <Kasten/Okteta/BookmarksControllerFactory>
0054 #include <Kasten/Okteta/PrintControllerFactory>
0055 #include <Kasten/Okteta/ViewConfigControllerFactory>
0056 #include <Kasten/Okteta/ViewModeControllerFactory>
0057 #include <Kasten/Okteta/ViewContextMenuControllerFactory>
0058 #include <Kasten/Okteta/ViewStatusControllerFactory>
0059 #include <Kasten/Okteta/ViewProfileControllerFactory>
0060 #include <Kasten/Okteta/ViewProfilesManageControllerFactory>
0061 // Kasten controllers
0062 #include <Kasten/ModifiedBarControllerFactory>
0063 #include <Kasten/ReadOnlyControllerFactory>
0064 #include <Kasten/ReadOnlyBarControllerFactory>
0065 #include <Kasten/CreatorControllerFactory>
0066 #include <Kasten/LoaderControllerFactory>
0067 #include <Kasten/CloseControllerFactory>
0068 #include <Kasten/SetRemoteControllerFactory>
0069 #include <Kasten/SynchronizeControllerFactory>
0070 #include <Kasten/ClipboardControllerFactory>
0071 #include <Kasten/InsertControllerFactory>
0072 #include <Kasten/CopyAsControllerFactory>
0073 #include <Kasten/ExportControllerFactory>
0074 #include <Kasten/VersionControllerFactory>
0075 #include <Kasten/ZoomControllerFactory>
0076 #include <Kasten/ZoomBarControllerFactory>
0077 #include <Kasten/SelectControllerFactory>
0078 #include <Kasten/ViewAreaContextMenuControllerFactory>
0079 #include <Kasten/SwitchViewControllerFactory>
0080 #include <Kasten/ViewListMenuControllerFactory>
0081 #include <Kasten/ViewAreaSplitControllerFactory>
0082 #include <Kasten/ToolListMenuControllerFactory>
0083 #include <Kasten/FullScreenControllerFactory>
0084 #ifndef KASTEN_NO_UICOLORSCHEMECONTROLLER
0085 #include <Kasten/UiColorSchemeControllerFactory>
0086 #endif
0087 #include <Kasten/QuitControllerFactory>
0088 // Kasten gui
0089 #include <Kasten/MultiDocumentStrategy>
0090 #include <Kasten/ModelCodecViewManager>
0091 #include <Kasten/ViewManager>
0092 #include <Kasten/MultiViewAreas>
0093 #include <Kasten/StatusBar>
0094 // Kasten core
0095 #include <Kasten/ModelCodecManager>
0096 #include <Kasten/DocumentCreateManager>
0097 #include <Kasten/DocumentSyncManager>
0098 #include <Kasten/DocumentManager>
0099 // KF
0100 #include <KConfigGroup>
0101 #include <KSharedConfig>
0102 // Qt
0103 #include <QUrl>
0104 #include <QMimeData>
0105 
0106 namespace Kasten {
0107 
0108 static constexpr char LoadedUrlsKey[] = "LoadedUrls";
0109 
0110 OktetaMainWindow::OktetaMainWindow(OktetaProgram* program)
0111     : ShellWindow(program->viewManager())
0112     , mProgram(program)
0113 {
0114     setObjectName(QStringLiteral("Shell"));
0115 
0116     // there is only one mainwindow, so have this show the document if requested
0117     connect(mProgram->documentManager(), &DocumentManager::focusRequested,
0118             this, &OktetaMainWindow::showDocument);
0119     connect(viewArea(), &MultiViewAreas::dataOffered,
0120             this, &OktetaMainWindow::onDataOffered);
0121     connect(viewArea(), &MultiViewAreas::dataDropped,
0122             this, &OktetaMainWindow::onDataDropped);
0123     connect(viewArea(), &MultiViewAreas::newDocumentRequested,
0124             this, &OktetaMainWindow::onNewDocumentRequested);
0125     connect(viewArea(), &AbstractGroupedViews::closeRequest,
0126             this, &OktetaMainWindow::onCloseRequest);
0127 
0128 // Using State value as generated with Qt 5.15.11-KDE
0129 #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 11)
0130     // XXX: Workaround for Qt 4.4's lacking of proper handling of the initial layout of dock widgets
0131     //      This state is taken from an oktetarc where the docker constellation was configured by hand.
0132     //      Setting this state if none is present seems to work, but there's
0133     //      still the versioning problem to be accounted for.
0134     //      Hack borrowed from trunk/koffice/krita/ui/kis_view2.cpp:
0135     const QString mainWindowState = QStringLiteral(
0136         "AAAA/wAAAAD9AAAAAwAAAAAAAAEVAAACLvwCAAAAAfwAAABLAAACLgAAAI8BAAAd+gAAAAABAAAAAvsAAAAiAEYAaQBsAGUAUwB5AHMAdABlAG0AQgByAG8AdwBzAGUAcgEAAAAA/////wAAAGQA////+wAAABIARABvAGMAdQBtAGUAbgB0AHMBAAAAAP////8AAABcAP///wAAAAEAAAHhAAACLvwCAAAABfsAAAAUAFMAdAByAHUAYwB0AFQAbwBvAGwDAAACjQAAAPwAAAIyAAABT/sAAAAQAFYAZQByAHMAaQBvAG4AcwAAAAA2AAAAiQAAAAAAAAAA/AAAAEsAAAEqAAABKgEAAB36AAAAAQEAAAAH+wAAABgARABvAGMAdQBtAGUAbgB0AEkAbgBmAG8BAAAAAP////8AAACMAP////sAAAASAEIAeQB0AGUAVABhAGIAbABlAQAAAAD/////AAAAXAD////7AAAADgBTAHQAcgBpAG4AZwBzAQAAAAD/////AAAAiQD////7AAAAEABDAGgAZQBjAGsAcwB1AG0BAAAAAP////8AAAEFAP////sAAAAcAFMAdAByAHUAYwB0AHUAcgBlAHMAVABvAG8AbAEAAAAA/////wAAAJkA////+wAAABQAUwB0AHIAdQBjAHQAVABvAG8AbAMAAAKNAAAA/AAAAjIAAAFP+wAAABQAUABPAEQARABlAGMAbwBkAGUAcgEAAAAA/////wAAAJQA/////AAAAQsAAADsAAAAAAD////6AAAAAAEAAAAB+wAAABAAQwBoAGUAYwBrAFMAdQBtAQAAAAD/////AAAAAAAAAAD8AAABdgAAAQMAAAEDAQAAHfoAAAAAAQAAAAT7AAAAGABCAGkAbgBhAHIAeQBGAGkAbAB0AGUAcgEAAAAA/////wAAAVMA////+wAAACIAQwBoAGEAcgBzAGUAdABDAG8AbgB2AGUAcgBzAGkAbwBuAQAAAAD/////AAABRAD////7AAAACABJAG4AZgBvAQAAAAD/////AAAAiQD////7AAAAEgBCAG8AbwBrAG0AYQByAGsAcwEAAAAA/////wAAAFwA////AAAAAwAABVYAAABC/AEAAAAB+wAAABAAVABlAHIAbQBpAG4AYQBsAAAAAAAAAAVWAAAAXAD///8AAADlAAACLgAAAAQAAAAEAAAACAAAAAj8AAAAAQAAAAIAAAABAAAAFgBtAGEAaQBuAFQAbwBvAGwAQgBhAHIBAAAAAAAABAYAAAAAAAAAAA==");
0137     const char mainWindowStateKey[] = "State";
0138     KConfigGroup group(KSharedConfig::openConfig(), QStringLiteral("MainWindow"));
0139     if (!group.hasKey(mainWindowStateKey)) {
0140         group.writeEntry(mainWindowStateKey, mainWindowState);
0141     }
0142 #endif
0143 
0144     setStatusBar(new Kasten::StatusBar(this));
0145 
0146     setupControllers();
0147     setupGUI();
0148 
0149     // all controllers which use plugActionList have to do so after(!) setupGUI() or their entries will be removed
0150     // TODO: why is this so?
0151     // tmp
0152     addXmlGuiControllerFromFactory(ToolListMenuControllerFactory(this));
0153     addXmlGuiControllerFromFactory(ViewListMenuControllerFactory(viewManager(), viewArea()));
0154 }
0155 
0156 OktetaMainWindow::~OktetaMainWindow() = default;
0157 
0158 void OktetaMainWindow::setupControllers()
0159 {
0160     MultiDocumentStrategy* const documentStrategy = mProgram->documentStrategy();
0161     ViewManager* const viewManager = this->viewManager();
0162     MultiViewAreas* const viewArea = this->viewArea();
0163     ModelCodecViewManager* const codecViewManager = viewManager->codecViewManager();
0164     DocumentManager* const documentManager = mProgram->documentManager();
0165     ModelCodecManager* const codecManager = documentManager->codecManager();
0166     DocumentSyncManager* const syncManager = documentManager->syncManager();
0167     // tmp
0168     ByteArrayViewProfileManager* const byteArrayViewProfileManager = mProgram->byteArrayViewProfileManager();
0169 
0170     // general, part of Kasten
0171     addXmlGuiControllerFromFactory(CreatorControllerFactory(codecManager, documentStrategy));
0172     addXmlGuiControllerFromFactory(LoaderControllerFactory(documentStrategy));
0173     addXmlGuiControllerFromFactory(SetRemoteControllerFactory(syncManager));
0174     addXmlGuiControllerFromFactory(SynchronizeControllerFactory(syncManager));
0175     addXmlGuiControllerFromFactory(ExportControllerFactory(codecViewManager, codecManager));
0176     addXmlGuiControllerFromFactory(CloseControllerFactory(documentStrategy));
0177     addXmlGuiControllerFromFactory(VersionControllerFactory());
0178     addXmlGuiControllerFromFactory(ReadOnlyControllerFactory());
0179     addXmlGuiControllerFromFactory(ViewAreaContextMenuControllerFactory(viewArea, syncManager));
0180     addXmlGuiControllerFromFactory(SwitchViewControllerFactory(viewArea));
0181     addXmlGuiControllerFromFactory(ViewAreaSplitControllerFactory(viewManager, viewArea));
0182     addXmlGuiControllerFromFactory(FullScreenControllerFactory(this));
0183 #ifndef KASTEN_NO_UICOLORSCHEMECONTROLLER
0184     addXmlGuiControllerFromFactory(UiColorSchemeControllerFactory(this));
0185 #endif
0186     addXmlGuiControllerFromFactory(QuitControllerFactory(this));
0187 
0188     addXmlGuiControllerFromFactory(ZoomControllerFactory());
0189     addXmlGuiControllerFromFactory(SelectControllerFactory());
0190     addXmlGuiControllerFromFactory(ClipboardControllerFactory());
0191     addXmlGuiControllerFromFactory(InsertControllerFactory(codecViewManager, codecManager));
0192     addXmlGuiControllerFromFactory(CopyAsControllerFactory(codecViewManager, codecManager));
0193 
0194     addToolFromFactory(FileSystemBrowserToolViewFactory(), FileSystemBrowserToolFactory(syncManager));
0195     addToolFromFactory(DocumentsToolViewFactory(), DocumentsToolFactory(documentManager));
0196     addToolFromFactory(TerminalToolViewFactory(), TerminalToolFactory(syncManager));
0197 #ifndef NDEBUG
0198     addToolFromFactory(VersionViewToolViewFactory(), VersionViewToolFactory());
0199 #endif
0200 
0201     // Okteta specific
0202 //     addXmlGuiControllerFromFactory(OverwriteOnlyControllerFactory() );
0203     addXmlGuiControllerFromFactory(OverwriteModeControllerFactory());
0204     addXmlGuiControllerFromFactory(SearchControllerFactory(this));
0205     addXmlGuiControllerFromFactory(ReplaceControllerFactory(this));
0206     addXmlGuiControllerFromFactory(GotoOffsetControllerFactory(viewArea));
0207     addXmlGuiControllerFromFactory(SelectRangeControllerFactory(viewArea));
0208     addXmlGuiControllerFromFactory(BookmarksControllerFactory());
0209     addXmlGuiControllerFromFactory(PrintControllerFactory());
0210     addXmlGuiControllerFromFactory(ViewConfigControllerFactory());
0211     addXmlGuiControllerFromFactory(ViewModeControllerFactory());
0212     addXmlGuiControllerFromFactory(ViewContextMenuControllerFactory());
0213     addXmlGuiControllerFromFactory(ViewProfileControllerFactory(byteArrayViewProfileManager, this));
0214     addXmlGuiControllerFromFactory(ViewProfilesManageControllerFactory(byteArrayViewProfileManager, this));
0215 
0216     auto* const bottomBar = static_cast<Kasten::StatusBar*>(statusBar());
0217     addXmlGuiControllerFromFactory(ViewStatusControllerFactory(bottomBar));
0218     addXmlGuiControllerFromFactory(ModifiedBarControllerFactory(bottomBar));
0219     addXmlGuiControllerFromFactory(ReadOnlyBarControllerFactory(bottomBar));
0220     addXmlGuiControllerFromFactory(ZoomBarControllerFactory(bottomBar));
0221 
0222     addToolFromFactory(DocumentInfoToolViewFactory(), DocumentInfoToolFactory(syncManager));
0223     addToolFromFactory(ChecksumToolViewFactory(), ChecksumToolFactory());
0224     addToolFromFactory(FilterToolViewFactory(), FilterToolFactory());
0225     addToolFromFactory(CharsetConversionToolViewFactory(), CharsetConversionToolFactory());
0226     addToolFromFactory(StringsExtractToolViewFactory(), StringsExtractToolFactory());
0227     addToolFromFactory(ByteTableToolViewFactory(), ByteTableToolFactory());
0228     addToolFromFactory(InfoToolViewFactory(), InfoToolFactory());
0229     addToolFromFactory(PodDecoderToolViewFactory(), PodDecoderToolFactory());
0230     addToolFromFactory(StructuresToolViewFactory(), StructuresToolFactory());
0231     addToolFromFactory(BookmarksToolViewFactory(), BookmarksToolFactory());
0232 }
0233 
0234 void OktetaMainWindow::addToolFromFactory(const AbstractToolViewFactory& toolViewFactory,
0235                                           const AbstractToolFactory& toolFactory)
0236 {
0237     AbstractTool* tool = toolFactory.create();
0238     AbstractToolView* toolView = toolViewFactory.create(tool);
0239 
0240     addTool(toolView);
0241 }
0242 
0243 void OktetaMainWindow::addXmlGuiControllerFromFactory(const AbstractXmlGuiControllerFactory& factory)
0244 {
0245     AbstractXmlGuiController* controller = factory.create(this);
0246     addXmlGuiController(controller);
0247 }
0248 
0249 
0250 bool OktetaMainWindow::queryClose()
0251 {
0252     // TODO: query the document manager or query the view manager?
0253     return mProgram->documentManager()->canCloseAll();
0254 }
0255 
0256 void OktetaMainWindow::saveProperties(KConfigGroup& configGroup)
0257 {
0258     DocumentManager* const documentManager = mProgram->documentManager();
0259     DocumentSyncManager* const syncManager = documentManager->syncManager();
0260     const QVector<AbstractDocument*> documents = documentManager->documents();
0261 
0262     QStringList urls;
0263     urls.reserve(documents.size());
0264     for (AbstractDocument* document : documents) {
0265         urls.append(syncManager->urlOf(document).url());
0266     }
0267 
0268     configGroup.writePathEntry(LoadedUrlsKey, urls);
0269 }
0270 
0271 void OktetaMainWindow::readProperties(const KConfigGroup& configGroup)
0272 {
0273     const QStringList urls = configGroup.readPathEntry(LoadedUrlsKey, QStringList());
0274 
0275     DocumentManager* const documentManager = mProgram->documentManager();
0276     DocumentSyncManager* const syncManager = documentManager->syncManager();
0277     DocumentCreateManager* const createManager = documentManager->createManager();
0278     for (const QString& url : urls) {
0279         if (url.isEmpty()) {
0280             createManager->createNew();
0281         } else {
0282             syncManager->load(QUrl(url, QUrl::TolerantMode));
0283         }
0284         // TODO: set view to offset
0285         // if( offset != -1 )
0286     }
0287 }
0288 
0289 void OktetaMainWindow::onDataOffered(const QMimeData* mimeData, bool& accept)
0290 {
0291     accept = mimeData->hasUrls()
0292              || mProgram->documentManager()->createManager()->canCreateNewFromData(mimeData);
0293 }
0294 
0295 void OktetaMainWindow::onDataDropped(const QMimeData* mimeData)
0296 {
0297     const QList<QUrl> urls = mimeData->urls();
0298 
0299     DocumentManager* const documentManager = mProgram->documentManager();
0300     if (!urls.isEmpty()) {
0301         DocumentSyncManager* const syncManager = documentManager->syncManager();
0302 
0303         for (const QUrl& url : urls) {
0304             syncManager->load(url);
0305         }
0306     } else {
0307         documentManager->createManager()->createNewFromData(mimeData, true);
0308     }
0309 }
0310 
0311 void OktetaMainWindow::onNewDocumentRequested()
0312 {
0313     mProgram->documentManager()->createManager()->createNew();
0314 }
0315 
0316 void OktetaMainWindow::onCloseRequest(const QVector<Kasten::AbstractView*>& views)
0317 {
0318     // group views per document
0319     QHash<AbstractDocument*, QVector<AbstractView*>> viewsToClosePerDocument;
0320     for (AbstractView* view : views) {
0321         auto* document = view->findBaseModel<AbstractDocument*>();
0322         viewsToClosePerDocument[document].append(view);
0323     }
0324 
0325     // find documents which lose all views
0326     const QVector<AbstractView*> allViews = viewManager()->views();
0327     for (AbstractView* view : allViews) {
0328         auto* document = view->findBaseModel<AbstractDocument*>();
0329         QHash<AbstractDocument*, QVector<AbstractView*>>::Iterator it =
0330             viewsToClosePerDocument.find(document);
0331 
0332         if (it != viewsToClosePerDocument.end()) {
0333             const QVector<AbstractView*>& viewsOfDocument = it.value();
0334             const bool isAnotherView = !viewsOfDocument.contains(view);
0335             if (isAnotherView) {
0336                 viewsToClosePerDocument.erase(it);
0337             }
0338         }
0339     }
0340 
0341     const QVector<AbstractDocument*> documentsWithoutViews = viewsToClosePerDocument.keys().toVector();
0342 
0343     DocumentManager* const documentManager = mProgram->documentManager();
0344     if (documentManager->canClose(documentsWithoutViews)) {
0345         viewManager()->removeViews(views);
0346         documentManager->closeDocuments(documentsWithoutViews);
0347     }
0348 }
0349 
0350 }
0351 
0352 #include "moc_mainwindow.cpp"