File indexing completed on 2024-04-28 04:37:20

0001 /*
0002     SPDX-FileCopyrightText: 2007 Alexander Dymo <adymo@kdevelop.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "partdocument.h"
0008 
0009 #include <QMimeDatabase>
0010 
0011 #include <KMessageBox>
0012 #include <KMessageBox_KDevCompat>
0013 #include <KLocalizedString>
0014 #include <KTextEditor/Cursor>
0015 
0016 #include <sublime/area.h>
0017 #include <sublime/view.h>
0018 #include <sublime/mainwindow.h>
0019 
0020 #include "core.h"
0021 #include "uicontroller.h"
0022 #include "partcontroller.h"
0023 
0024 namespace KDevelop {
0025 
0026 class PartDocumentPrivate {
0027 public:
0028     explicit PartDocumentPrivate(const QString& preferredPart)
0029         : preferredPart(preferredPart)
0030     {}
0031 
0032     QMap<QWidget*, KParts::Part*> partForView;
0033     const QString preferredPart;
0034 };
0035 
0036 PartDocument::PartDocument(const QUrl& url, KDevelop::ICore* core, const QString& preferredPart)
0037     : Sublime::UrlDocument(core->uiController()->controller(), url)
0038     , KDevelop::IDocument(core)
0039     , d_ptr(new PartDocumentPrivate(preferredPart))
0040 {
0041 }
0042 
0043 PartDocument::~PartDocument() = default;
0044 
0045 QWidget *PartDocument::createViewWidget(QWidget* /*parent*/)
0046 {
0047     Q_D(PartDocument);
0048 
0049     KParts::Part *part = Core::self()->partControllerInternal()->createPart(url(), d->preferredPart);
0050     if( part )
0051     {
0052         Core::self()->partController()->addPart(part);
0053         QWidget *w = part->widget();
0054         d->partForView[w] = part;
0055         return w;
0056     }
0057     return nullptr;
0058 }
0059 
0060 KParts::Part *PartDocument::partForView(QWidget *view) const
0061 {
0062     Q_D(const PartDocument);
0063 
0064     return d->partForView[view];
0065 }
0066 
0067 
0068 
0069 //KDevelop::IDocument implementation
0070 
0071 
0072 QMimeType PartDocument::mimeType() const
0073 {
0074     return QMimeDatabase().mimeTypeForUrl(url());
0075 }
0076 
0077 KTextEditor::Document *PartDocument::textDocument() const
0078 {
0079     return nullptr;
0080 }
0081 
0082 bool PartDocument::isActive() const
0083 {
0084     const auto activeView = Core::self()->uiControllerInternal()->activeSublimeWindow()->activeView();
0085     if (!activeView) {
0086         return false;
0087     }
0088 
0089     return activeView->document() == this;
0090 }
0091 
0092 bool PartDocument::save(DocumentSaveMode /*mode*/)
0093 {
0094     //part document is read-only so do nothing here
0095     return true;
0096 }
0097 
0098 bool PartDocument::askForCloseFeedback()
0099 {
0100     int code = -1;
0101     if (state() == IDocument::Modified) {
0102         code = KMessageBox::warningTwoActionsCancel(
0103             Core::self()->uiController()->activeMainWindow(),
0104             i18n("The document \"%1\" has unsaved changes. Would you like to save them?", url().toLocalFile()),
0105             i18nc("@title:window", "Close Document"), KStandardGuiItem::save(), KStandardGuiItem::discard());
0106 
0107     /// @todo Is this behavior right?
0108     } else if (state() == IDocument::DirtyAndModified) {
0109         code = KMessageBox::warningTwoActionsCancel(
0110             Core::self()->uiController()->activeMainWindow(),
0111             i18n("The document \"%1\" has unsaved changes and was modified by an external process.\n"
0112                  "Do you want to overwrite the external changes?",
0113                  url().toLocalFile()),
0114             i18nc("@title:window", "Close Document"),
0115             KGuiItem(i18nc("@action:button", "Overwrite External Changes"), QStringLiteral("document-save")),
0116             KStandardGuiItem::discard());
0117     }
0118 
0119     if (code >= 0) {
0120         if (code == KMessageBox::PrimaryAction) {
0121             if (!save(Default))
0122                 return false;
0123 
0124         } else if (code == KMessageBox::Cancel) {
0125             return false;
0126         }
0127     }
0128 
0129     return true;
0130 }
0131 
0132 bool PartDocument::close(DocumentSaveMode mode)
0133 {
0134     Q_D(PartDocument);
0135 
0136     if (!(mode & Discard)) {
0137         if (mode & Silent) {
0138             if (!save(mode))
0139                 return false;
0140         } else {
0141             if( !askForCloseFeedback() )
0142                 return false;
0143         }
0144     }
0145 
0146     //close all views and then delete ourself
0147     closeViews();
0148 
0149     for (KParts::Part* part : qAsConst(d->partForView)) {
0150         part->deleteLater();
0151     }
0152 
0153     // The document will be deleted automatically if there are no views left
0154 
0155     return true;
0156 }
0157 
0158 bool PartDocument::closeDocument(bool silent) {
0159     return close(silent ? Silent : Default);
0160 }
0161 
0162 void PartDocument::reload()
0163 {
0164     //part document is read-only so do nothing here
0165 }
0166 
0167 IDocument::DocumentState PartDocument::state() const
0168 {
0169     return Clean;
0170 }
0171 
0172 void PartDocument::activate(Sublime::View *activeView, KParts::MainWindow *mainWindow)
0173 {
0174     Q_UNUSED(mainWindow);
0175     KParts::Part *part = partForView(activeView->widget());
0176     if (Core::self()->partController()->activePart() != part)
0177         Core::self()->partController()->setActivePart(part);
0178     notifyActivated();
0179 }
0180 
0181 KTextEditor::Cursor KDevelop::PartDocument::cursorPosition() const
0182 {
0183     return KTextEditor::Cursor::invalid();
0184 }
0185 
0186 void PartDocument::setCursorPosition(const KTextEditor::Cursor &cursor)
0187 {
0188     //do nothing here
0189     Q_UNUSED(cursor);
0190 }
0191 
0192 void PartDocument::setTextSelection(const KTextEditor::Range &range)
0193 {
0194     Q_UNUSED(range);
0195 }
0196 
0197 QUrl PartDocument::url() const
0198 {
0199     return Sublime::UrlDocument::url();
0200 }
0201 
0202 void PartDocument::setUrl(const QUrl& newUrl)
0203 {
0204     const auto previousUrl = Sublime::UrlDocument::url();
0205     Sublime::UrlDocument::setUrl(newUrl);
0206     if(!prettyName().isEmpty())
0207         setTitle(prettyName());
0208     notifyUrlChanged(previousUrl);
0209 }
0210 
0211 void PartDocument::setPrettyName(const QString& name)
0212 {
0213     KDevelop::IDocument::setPrettyName(name);
0214     // Re-set the url, to trigger the whole chain
0215     if(!name.isEmpty())
0216         setTitle(name);
0217     else
0218         setTitle(url().fileName());
0219 }
0220 
0221 QMap<QWidget*, KParts::Part*> PartDocument::partForView() const
0222 {
0223     Q_D(const PartDocument);
0224 
0225     return d->partForView;
0226 }
0227 
0228 void PartDocument::addPartForView(QWidget* w, KParts::Part* p)
0229 {
0230     Q_D(PartDocument);
0231 
0232     d->partForView[w]=p;
0233 }
0234 
0235 }
0236 
0237 #include "moc_partdocument.cpp"