1 /*
2     SPDX-FileCopyrightText: 2010-2011 Friedrich W. H. Kossebau <kossebau@kde.org>
3 
4     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 
7 #include "oktetadocument.h"
8 
9 // plugin
10 #include "oktetaplugin.h"
11 #include "oktetaview.h"
12 // Okteta
13 #include <Kasten/Okteta/ByteArrayViewProfileManager>
14 #include <Kasten/Okteta/ByteArrayViewProfileSynchronizer>
15 #include <Kasten/Okteta/ByteArrayRawFileSynchronizerFactory>
16 #include <Kasten/Okteta/ByteArrayDocument>
17 // Kasten
18 #include <Kasten/JobManager>
19 #include <Kasten/AbstractLoadJob>
20 #include <Kasten/AbstractSyncToRemoteJob>
21 #include <Kasten/AbstractSyncFromRemoteJob>
22 #include <Kasten/AbstractModelSynchronizer>
23 // KDevelop
24 #include <shell/core.h>
25 #include <shell/uicontroller.h>
26 #include <interfaces/icore.h>
27 #include <interfaces/iuicontroller.h>
28 // Sublime
29 #include <sublime/mainwindow.h>
30 #include <sublime/view.h>
31 #include <sublime/area.h>
32 #include <sublime/controller.h>
33 // KF
34 #include <KMessageBox>
35 #include <KLocalizedString>
36 #include <KTextEditor/Cursor>
37 // Qt
38 #include <QApplication>
39 #include <QMimeDatabase>
40 
41 
42 namespace KDevelop
43 {
44 
OktetaDocument(const QUrl & url,ICore * core)45 OktetaDocument::OktetaDocument( const QUrl &url , ICore* core )
46     : Sublime::UrlDocument( core->uiController()->controller(), url )
47     , IDocument( core )
48     , mPlugin( nullptr )
49     , mByteArrayDocument( nullptr )
50 {
51 }
52 
url() const53 QUrl OktetaDocument::url() const { return Sublime::UrlDocument::url(); }
54 
55 // TODO: use fromContentAndUrl(ByteArrayIODevice) if document loaded
mimeType() const56 QMimeType OktetaDocument::mimeType() const { return QMimeDatabase().mimeTypeForUrl( url() ); }
57 
partForView(QWidget *) const58 KParts::Part* OktetaDocument::partForView( QWidget* ) const { return nullptr; }
textDocument() const59 KTextEditor::Document* OktetaDocument::textDocument() const { return nullptr; }
cursorPosition() const60 KTextEditor::Cursor OktetaDocument::cursorPosition() const { return KTextEditor::Cursor(); }
61 
state() const62 IDocument::DocumentState OktetaDocument::state() const
63 {
64     return mByteArrayDocument ?
65                ( mByteArrayDocument->synchronizer()->localSyncState() == Kasten::LocalHasChanges ?
66                    IDocument::Modified :
67                    IDocument::Clean ) :
68                IDocument::Clean;
69 }
70 
71 
save(IDocument::DocumentSaveMode mode)72 bool OktetaDocument::save( IDocument::DocumentSaveMode mode )
73 {
74     if( mode & Discard )
75         return true;
76 
77     if(  state() == IDocument::Clean )
78         return false;
79 
80     Kasten::AbstractModelSynchronizer* synchronizer = mByteArrayDocument->synchronizer();
81 
82     Kasten::AbstractSyncToRemoteJob* syncJob = synchronizer->startSyncToRemote();
83     const bool syncSucceeded = Kasten::JobManager::executeJob( syncJob );
84 
85     if( syncSucceeded )
86     {
87         notifySaved();
88         notifyStateChanged();
89     }
90 
91     return syncSucceeded;
92 }
93 
94 
reload()95 void OktetaDocument::reload()
96 {
97     Kasten::AbstractModelSynchronizer* synchronizer = mByteArrayDocument->synchronizer();
98 
99     Kasten::AbstractSyncFromRemoteJob* syncJob = synchronizer->startSyncFromRemote();
100     const bool syncSucceeded = Kasten::JobManager::executeJob( syncJob );
101 
102     if( syncSucceeded )
103         notifyStateChanged();
104 }
105 
close(IDocument::DocumentSaveMode mode)106 bool OktetaDocument::close( IDocument::DocumentSaveMode mode )
107 {
108     bool isCanceled = false;
109     if( !(mode & Discard) )
110     {
111         if (mode & Silent)
112         {
113             if (!save(mode))
114                 isCanceled = true;
115 
116         }
117         else
118         {
119             if( state() == IDocument::Modified )
120             {
121                 // TODO: use Kasten::*Manager
122                 int code = KMessageBox::warningYesNoCancel(
123                     qApp->activeWindow(),
124                     i18n("The document \"%1\" has unsaved changes. Would you like to save them?", url().toLocalFile()),
125                     i18nc("@title:window", "Close Document"));
126 
127                 if (code == KMessageBox::Yes) {
128                     if (!save(mode))
129                 isCanceled = true;
130 
131                 } else if (code == KMessageBox::Cancel)
132                     isCanceled = true;
133 
134             }
135             else if( state() == IDocument::DirtyAndModified )
136             {
137                 if( !save(mode) )
138                     isCanceled = true;
139             }
140         }
141     }
142 
143     if( isCanceled )
144         return false;
145 
146     //close all views and then delete ourself
147     ///@todo test this
148     const QList<Sublime::Area*>& allAreas =
149         ICore::self()->uiController()->controller()->allAreas();
150     for (Sublime::Area* area : allAreas ) {
151         const QList<Sublime::View*> areaViews = area->views();
152         for (Sublime::View* view : areaViews) {
153             if (views().contains(view))
154             {
155                 area->removeView(view);
156                 delete view;
157             }
158         }
159     }
160 
161     // The document is deleted automatically when there are no views left
162 
163     return true;
164 }
165 
isActive() const166 bool OktetaDocument::isActive() const
167 {
168     return Core::self()->uiControllerInternal()->activeSublimeWindow()->activeView()->document() == this;
169 }
170 
171 
setCursorPosition(const KTextEditor::Cursor &)172 void OktetaDocument::setCursorPosition( const KTextEditor::Cursor& ) {}
setTextSelection(const KTextEditor::Range &)173 void OktetaDocument::setTextSelection( const KTextEditor::Range& ) {}
174 
activate(Sublime::View *,KParts::MainWindow *)175 void OktetaDocument::activate( Sublime::View* /* view */, KParts::MainWindow* /* mainWindow */ )
176 {
177     notifyActivated();
178 }
179 
setPlugin(OktetaPlugin * plugin)180 void OktetaDocument::setPlugin( OktetaPlugin* plugin )
181 {
182     mPlugin = plugin;
183 }
184 
newView(Sublime::Document *)185 Sublime::View* OktetaDocument::newView( Sublime::Document* /* document */ )
186 {
187     if( mByteArrayDocument == nullptr )
188     {
189         auto* synchronizerFactory =
190             new Kasten::ByteArrayRawFileSynchronizerFactory();
191         Kasten::AbstractModelSynchronizer* synchronizer = synchronizerFactory->createSynchronizer();
192 
193         Kasten::AbstractLoadJob* loadJob = synchronizer->startLoad( url() );
194         connect( loadJob, &Kasten::AbstractLoadJob::documentLoaded,
195                  this, &OktetaDocument::onByteArrayDocumentLoaded );
196         Kasten::JobManager::executeJob( loadJob );
197 
198         delete synchronizerFactory;
199     }
200 
201     Kasten::ByteArrayViewProfileManager* const viewProfileManager = mPlugin->viewProfileManager();
202     auto* viewProfileSynchronizer =
203         new Kasten::ByteArrayViewProfileSynchronizer( viewProfileManager );
204     viewProfileSynchronizer->setViewProfileId( viewProfileManager->defaultViewProfileId() );
205     return new OktetaView( this, viewProfileSynchronizer );
206 }
207 
closeDocument(bool silent)208 bool OktetaDocument::closeDocument(bool silent)
209 {
210     return close(silent ? Silent : Default);
211 }
212 
onByteArrayDocumentLoaded(Kasten::AbstractDocument * document)213 void OktetaDocument::onByteArrayDocumentLoaded( Kasten::AbstractDocument* document )
214 {
215     if( document )
216     {
217         mByteArrayDocument = static_cast<Kasten::ByteArrayDocument*>( document );
218         connect( mByteArrayDocument->synchronizer(), &Kasten::AbstractModelSynchronizer::localSyncStateChanged,
219                  this, &OktetaDocument::onByteArrayDocumentChanged );
220     }
221 }
222 
onByteArrayDocumentChanged()223 void OktetaDocument::onByteArrayDocumentChanged()
224 {
225     notifyStateChanged();
226 }
227 
~OktetaDocument()228 OktetaDocument::~OktetaDocument()
229 {
230     delete mByteArrayDocument;
231 }
232 
233 }
234