File indexing completed on 2024-04-28 04:39:03

0001 /*
0002     SPDX-FileCopyrightText: 2010-2011 Friedrich W. H. Kossebau <kossebau@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "oktetadocument.h"
0008 
0009 // plugin
0010 #include "oktetaplugin.h"
0011 #include "oktetaview.h"
0012 // Okteta
0013 #include <Kasten/Okteta/ByteArrayViewProfileManager>
0014 #include <Kasten/Okteta/ByteArrayViewProfileSynchronizer>
0015 #include <Kasten/Okteta/ByteArrayRawFileSynchronizerFactory>
0016 #include <Kasten/Okteta/ByteArrayDocument>
0017 // Kasten
0018 #include <Kasten/JobManager>
0019 #include <Kasten/AbstractLoadJob>
0020 #include <Kasten/AbstractSyncToRemoteJob>
0021 #include <Kasten/AbstractSyncFromRemoteJob>
0022 #include <Kasten/AbstractModelSynchronizer>
0023 // KDevelop
0024 #include <shell/core.h>
0025 #include <shell/uicontroller.h>
0026 #include <interfaces/icore.h>
0027 #include <interfaces/iuicontroller.h>
0028 // Sublime
0029 #include <sublime/mainwindow.h>
0030 #include <sublime/view.h>
0031 #include <sublime/area.h>
0032 #include <sublime/controller.h>
0033 // KF
0034 #include <KMessageBox>
0035 #include <KMessageBox_KDevCompat>
0036 #include <KLocalizedString>
0037 #include <KTextEditor/Cursor>
0038 // Qt
0039 #include <QApplication>
0040 #include <QMimeDatabase>
0041 
0042 
0043 namespace KDevelop
0044 {
0045 
0046 OktetaDocument::OktetaDocument( const QUrl &url , ICore* core )
0047     : Sublime::UrlDocument( core->uiController()->controller(), url )
0048     , IDocument( core )
0049     , mPlugin( nullptr )
0050     , mByteArrayDocument( nullptr )
0051 {
0052 }
0053 
0054 QUrl OktetaDocument::url() const { return Sublime::UrlDocument::url(); }
0055 
0056 // TODO: use fromContentAndUrl(ByteArrayIODevice) if document loaded
0057 QMimeType OktetaDocument::mimeType() const { return QMimeDatabase().mimeTypeForUrl( url() ); }
0058 
0059 KParts::Part* OktetaDocument::partForView( QWidget* ) const { return nullptr; }
0060 KTextEditor::Document* OktetaDocument::textDocument() const { return nullptr; }
0061 KTextEditor::Cursor OktetaDocument::cursorPosition() const { return KTextEditor::Cursor(); }
0062 
0063 IDocument::DocumentState OktetaDocument::state() const
0064 {
0065     return mByteArrayDocument ?
0066                ( mByteArrayDocument->synchronizer()->localSyncState() == Kasten::LocalHasChanges ?
0067                    IDocument::Modified :
0068                    IDocument::Clean ) :
0069                IDocument::Clean;
0070 }
0071 
0072 
0073 bool OktetaDocument::save( IDocument::DocumentSaveMode mode )
0074 {
0075     if( mode & Discard )
0076         return true;
0077 
0078     if(  state() == IDocument::Clean )
0079         return false;
0080 
0081     Kasten::AbstractModelSynchronizer* synchronizer = mByteArrayDocument->synchronizer();
0082 
0083     Kasten::AbstractSyncToRemoteJob* syncJob = synchronizer->startSyncToRemote();
0084     const bool syncSucceeded = Kasten::JobManager::executeJob( syncJob );
0085 
0086     if( syncSucceeded )
0087     {
0088         notifySaved();
0089         notifyStateChanged();
0090     }
0091 
0092     return syncSucceeded;
0093 }
0094 
0095 
0096 void OktetaDocument::reload()
0097 {
0098     Kasten::AbstractModelSynchronizer* synchronizer = mByteArrayDocument->synchronizer();
0099 
0100     Kasten::AbstractSyncFromRemoteJob* syncJob = synchronizer->startSyncFromRemote();
0101     const bool syncSucceeded = Kasten::JobManager::executeJob( syncJob );
0102 
0103     if( syncSucceeded )
0104         notifyStateChanged();
0105 }
0106 
0107 bool OktetaDocument::close( IDocument::DocumentSaveMode mode )
0108 {
0109     bool isCanceled = false;
0110     if( !(mode & Discard) )
0111     {
0112         if (mode & Silent)
0113         {
0114             if (!save(mode))
0115                 isCanceled = true;
0116 
0117         }
0118         else
0119         {
0120             if( state() == IDocument::Modified )
0121             {
0122                 // TODO: use Kasten::*Manager
0123                 int code = KMessageBox::warningTwoActionsCancel(
0124                     qApp->activeWindow(),
0125                     i18n("The document \"%1\" has unsaved changes. Would you like to save them?", url().toLocalFile()),
0126                     i18nc("@title:window", "Close Document"), KStandardGuiItem::save(), KStandardGuiItem::cancel());
0127 
0128                 if (code == KMessageBox::PrimaryAction) {
0129                     if (!save(mode))
0130                 isCanceled = true;
0131 
0132                 } else if (code == KMessageBox::Cancel)
0133                     isCanceled = true;
0134 
0135             }
0136             else if( state() == IDocument::DirtyAndModified )
0137             {
0138                 if( !save(mode) )
0139                     isCanceled = true;
0140             }
0141         }
0142     }
0143 
0144     if( isCanceled )
0145         return false;
0146 
0147     //close all views and then delete ourself
0148     ///@todo test this
0149     const QList<Sublime::Area*>& allAreas =
0150         ICore::self()->uiController()->controller()->allAreas();
0151     for (Sublime::Area* area : allAreas ) {
0152         const QList<Sublime::View*> areaViews = area->views();
0153         for (Sublime::View* view : areaViews) {
0154             if (views().contains(view))
0155             {
0156                 area->removeView(view);
0157                 delete view;
0158             }
0159         }
0160     }
0161 
0162     // The document is deleted automatically when there are no views left
0163 
0164     return true;
0165 }
0166 
0167 bool OktetaDocument::isActive() const
0168 {
0169     return Core::self()->uiControllerInternal()->activeSublimeWindow()->activeView()->document() == this;
0170 }
0171 
0172 
0173 void OktetaDocument::setCursorPosition( const KTextEditor::Cursor& ) {}
0174 void OktetaDocument::setTextSelection( const KTextEditor::Range& ) {}
0175 
0176 void OktetaDocument::activate( Sublime::View* /* view */, KParts::MainWindow* /* mainWindow */ )
0177 {
0178     notifyActivated();
0179 }
0180 
0181 void OktetaDocument::setPlugin( OktetaPlugin* plugin )
0182 {
0183     mPlugin = plugin;
0184 }
0185 
0186 Sublime::View* OktetaDocument::newView( Sublime::Document* /* document */ )
0187 {
0188     if( mByteArrayDocument == nullptr )
0189     {
0190         auto* synchronizerFactory =
0191             new Kasten::ByteArrayRawFileSynchronizerFactory();
0192         Kasten::AbstractModelSynchronizer* synchronizer = synchronizerFactory->createSynchronizer();
0193 
0194         Kasten::AbstractLoadJob* loadJob = synchronizer->startLoad( url() );
0195         connect( loadJob, &Kasten::AbstractLoadJob::documentLoaded,
0196                  this, &OktetaDocument::onByteArrayDocumentLoaded );
0197         Kasten::JobManager::executeJob( loadJob );
0198 
0199         delete synchronizerFactory;
0200     }
0201 
0202     Kasten::ByteArrayViewProfileManager* const viewProfileManager = mPlugin->viewProfileManager();
0203     auto* viewProfileSynchronizer =
0204         new Kasten::ByteArrayViewProfileSynchronizer( viewProfileManager );
0205     viewProfileSynchronizer->setViewProfileId( viewProfileManager->defaultViewProfileId() );
0206     return new OktetaView( this, viewProfileSynchronizer );
0207 }
0208 
0209 bool OktetaDocument::closeDocument(bool silent)
0210 {
0211     return close(silent ? Silent : Default);
0212 }
0213 
0214 void OktetaDocument::onByteArrayDocumentLoaded( Kasten::AbstractDocument* document )
0215 {
0216     if( document )
0217     {
0218         mByteArrayDocument = static_cast<Kasten::ByteArrayDocument*>( document );
0219         connect( mByteArrayDocument->synchronizer(), &Kasten::AbstractModelSynchronizer::localSyncStateChanged,
0220                  this, &OktetaDocument::onByteArrayDocumentChanged );
0221     }
0222 }
0223 
0224 void OktetaDocument::onByteArrayDocumentChanged()
0225 {
0226     notifyStateChanged();
0227 }
0228 
0229 OktetaDocument::~OktetaDocument()
0230 {
0231     delete mByteArrayDocument;
0232 }
0233 
0234 }
0235 
0236 #include "moc_oktetadocument.cpp"