File indexing completed on 2024-05-19 04:29:19

0001 /*
0002  *  SPDX-FileCopyrightText: 2018 Jouni Pentikäinen <joupent@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 #include "KisSessionResource.h"
0007 
0008 #include <QDomElement>
0009 
0010 #include <KisPart.h>
0011 #include <kis_properties_configuration.h>
0012 #include <KisDocument.h>
0013 
0014 #include <ksharedconfig.h>
0015 #include <KisViewManager.h>
0016 #include <KisMainWindow.h>
0017 
0018 
0019 struct KisSessionResource::Private
0020 {
0021     struct View
0022     {
0023         QUuid windowId;
0024         // NOTE: path of the file without scheme
0025         QString file;
0026         KisPropertiesConfiguration viewConfig;
0027 
0028         KisMainWindow *getWindow() const {
0029             Q_FOREACH(KisMainWindow *window, KisPart::instance()->mainWindows()) {
0030                 if (window->id() == this->windowId) return window;
0031             }
0032 
0033             return nullptr;
0034         }
0035     };
0036     QString profileName;
0037     QVector<View> views;
0038 };
0039 
0040 KisSessionResource::KisSessionResource(const QString &filename)
0041         : KisWindowLayoutResource(filename)
0042           , d(new Private)
0043 {}
0044 
0045 KisSessionResource::~KisSessionResource()
0046 {}
0047 
0048 KisSessionResource::KisSessionResource(const KisSessionResource &rhs)
0049     : KisWindowLayoutResource(rhs)
0050     , d(new Private(*rhs.d))
0051 {
0052 }
0053 
0054 KoResourceSP KisSessionResource::clone() const
0055 {
0056     return KoResourceSP(new KisSessionResource(*this));
0057 }
0058 
0059 void KisSessionResource::restore()
0060 {
0061     auto *kisPart = KisPart::instance();
0062 
0063     applyLayout();
0064 
0065     QMap<QString, KisDocument *> documents;
0066 
0067     // Find documents which are already open so we don't need to reload them
0068     QList<QPointer<KisView>> oldViews = kisPart->views();
0069     Q_FOREACH(const QPointer<KisView> view, oldViews) {
0070         KisDocument *document = view->document();
0071         const QString path = document->path();
0072         documents.insert(path, document);
0073     }
0074 
0075     Q_FOREACH(auto &viewData, d->views) {
0076         QString path = viewData.file;
0077 
0078         KisMainWindow *window = viewData.getWindow();
0079 
0080         if (!window) {
0081             qDebug() << "Warning: session file contains inconsistent data.";
0082         } else {
0083             KisDocument *document = documents.value(path);
0084 
0085             if (!document) {
0086                 document = kisPart->createDocument();
0087 
0088                 bool ok = document->openPath(path);
0089                 if (!ok) {
0090                     delete document;
0091                     continue;
0092                 }
0093 
0094                 kisPart->addDocument(document);
0095                 documents.insert(path, document);
0096             }
0097             //update profile
0098             QString profileName;
0099             profileName = d->profileName;
0100             window->viewManager()->changeAuthorProfile(profileName);
0101             window->viewManager()->slotUpdateAuthorProfileActions();
0102 
0103 
0104             KisView *view = window->newView(document);
0105             view->restoreViewState(viewData.viewConfig);
0106         }
0107     }
0108 
0109     Q_FOREACH(QPointer<KisView> view, oldViews) {
0110         view->closeView();
0111     }
0112 
0113 }
0114 
0115 
0116 QString KisSessionResource::defaultFileExtension() const
0117 {
0118     return ".ksn";
0119 }
0120 
0121 void KisSessionResource::storeCurrentWindows()
0122 {
0123     KisPart *kisPart = KisPart::instance();
0124     const auto &windows = kisPart->mainWindows();
0125     setWindows(windows);
0126 
0127     d->views.clear();
0128     Q_FOREACH(const KisView *view, kisPart->views()) {
0129         if (view->document()->path().isEmpty()) continue;
0130 
0131         auto viewData = Private::View();
0132         viewData.windowId = view->mainWindow()->id();
0133         viewData.file = view->document()->path();
0134         view->saveViewState(viewData.viewConfig);
0135         d->views.append(viewData);
0136     }
0137 
0138     setValid(true);
0139 }
0140 
0141 void KisSessionResource::saveXml(QDomDocument &doc, QDomElement &root) const
0142 {
0143     KisWindowLayoutResource::saveXml(doc, root);
0144 
0145     Q_FOREACH(const auto view, d->views) {
0146         QDomElement elem = doc.createElement("view");
0147 
0148         elem.setAttribute("window", view.windowId.toString());
0149         // we convert to QUrl to maintain compatibility with Krita 4.4
0150         elem.setAttribute("src", QUrl::fromLocalFile(view.file).toString());
0151         view.viewConfig.toXML(doc, elem);
0152 
0153         root.appendChild(elem);
0154 
0155         // Save profile
0156         KConfigGroup appAuthorGroup(KSharedConfig::openConfig(), "Author");
0157         QString profileName = appAuthorGroup.readEntry("active-profile", "");
0158 
0159         QDomElement session = doc.createElement("session");
0160         session.setAttribute("profile", profileName);
0161         root.appendChild(session);
0162 
0163     }
0164 
0165 }
0166 
0167 void KisSessionResource::loadXml(const QDomElement &root) const
0168 {
0169     KisWindowLayoutResource::loadXml(root);
0170 
0171     d->views.clear();
0172     for (auto viewElement = root.firstChildElement("view");
0173          !viewElement.isNull();
0174          viewElement = viewElement.nextSiblingElement("view")) {
0175         Private::View view;
0176 
0177         view.file = QUrl(viewElement.attribute("src")).toLocalFile();
0178         view.windowId = QUuid(viewElement.attribute("window"));
0179         view.viewConfig.fromXML(viewElement);
0180 
0181         d->views.append(view);
0182     }
0183     //Load session
0184     d->profileName.clear();
0185     auto sessionElement = root.firstChildElement("session");
0186     d->profileName = QString(sessionElement.attribute("profile"));
0187 
0188 }