1 /* This file is part of the KDE project
2  * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3  * Copyright (C) 2000-2005 David Faure <faure@kde.org>
4  * Copyright (C) 2007-2008 Thorsten Zachmann <zachmann@kde.org>
5  * Copyright (C) 2010-2012 Boudewijn Rempt <boud@kogmbh.com>
6  * Copyright (C) 2011 Inge Wallin <ingwa@kogmbh.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 // clazy:excludeall=qstring-arg
25 #include "KoPart.h"
26 
27 #include "KoApplication.h"
28 #include "KoMainWindow.h"
29 #include "KoDocument.h"
30 #include "KoView.h"
31 #include "KoFilterManager.h"
32 #include <KoComponentData.h>
33 
34 //#include <KoCanvasController.h>
35 //#include <KoCanvasControllerWidget.h>
36 #include <KoResourcePaths.h>
37 
38 #include <MainDebug.h>
39 #include <kxmlguifactory.h>
40 #include <kdesktopfile.h>
41 #include <kconfiggroup.h>
42 #include <ksharedconfig.h>
43 
44 #include <QFileInfo>
45 #include <QGraphicsScene>
46 #include <QGraphicsProxyWidget>
47 #include <QMimeDatabase>
48 
49 #ifndef QT_NO_DBUS
50 #include <QDBusConnection>
51 #include "KoPartAdaptor.h"
52 #endif
53 
54 class Q_DECL_HIDDEN KoPart::Private
55 {
56 public:
Private(const KoComponentData & componentData_,KoPart * _parent)57     Private(const KoComponentData &componentData_, KoPart *_parent)
58         : parent(_parent)
59         , document(0)
60         , componentData(componentData_)
61     {
62     }
63 
~Private()64     ~Private()
65     {
66         /// FIXME ok, so this is obviously bad to leave like this
67         // For now, this is undeleted, but only to avoid an odd double
68         // delete condition. Until that's discovered, we'll need this
69         // to avoid crashes in Gemini
70         //delete canvasItem;
71     }
72 
73     KoPart *parent;
74 
75     QList<KoView*> views;
76     QList<KoMainWindow*> mainWindows;
77     QPointer<KoDocument> document;
78     QList<KoDocument*> documents;
79     QString templatesResourcePath;
80 
81     KoComponentData componentData;
82 };
83 
84 
KoPart(const KoComponentData & componentData,QObject * parent)85 KoPart::KoPart(const KoComponentData &componentData, QObject *parent)
86         : QObject(parent)
87         , d(new Private(componentData, this))
88 {
89 #ifndef QT_NO_DBUS
90     new KoPartAdaptor(this);
91     QDBusConnection::sessionBus().registerObject('/' + objectName(), this);
92 #endif
93 }
94 
~KoPart()95 KoPart::~KoPart()
96 {
97     // Tell our views that the document is already destroyed and
98     // that they shouldn't try to access it.
99     foreach(KoView *view, views()) {
100         view->setDocumentDeleted();
101     }
102 
103     while (!d->mainWindows.isEmpty()) {
104         delete d->mainWindows.takeFirst();
105     }
106     // normally document is deleted in KoMainWindow (why?)
107     // but if not, we delete it here
108     delete d->document;
109 
110     delete d;
111 }
112 
componentData() const113 KoComponentData KoPart::componentData() const
114 {
115     return d->componentData;
116 }
117 
setDocument(KoDocument * document)118 void KoPart::setDocument(KoDocument *document)
119 {
120     Q_ASSERT(document);
121     d->document = document;
122 }
123 
document() const124 KoDocument *KoPart::document() const
125 {
126     return d->document;
127 }
128 
createView(KoDocument * document,QWidget * parent)129 KoView *KoPart::createView(KoDocument *document, QWidget *parent)
130 {
131     KoView *view = createViewInstance(document, parent);
132     addView(view, document);
133     if (!d->documents.contains(document)) {
134         d->documents.append(document);
135     }
136     return view;
137 }
138 
addView(KoView * view,KoDocument * document)139 void KoPart::addView(KoView *view, KoDocument *document)
140 {
141     if (!view)
142         return;
143 
144     if (!d->views.contains(view)) {
145         d->views.append(view);
146     }
147     if (!d->documents.contains(document)) {
148         d->documents.append(document);
149     }
150 
151     view->updateReadWrite(document->isReadWrite());
152 
153     if (d->views.size() == 1) {
154         KoApplication *app = qobject_cast<KoApplication*>(qApp);
155         if (0 != app) {
156             emit app->documentOpened('/'+objectName());
157         }
158     }
159 }
160 
removeView(KoView * view)161 void KoPart::removeView(KoView *view)
162 {
163     d->views.removeAll(view);
164 
165     if (d->views.isEmpty()) {
166         KoApplication *app = qobject_cast<KoApplication*>(qApp);
167         if (0 != app) {
168             emit app->documentClosed('/'+objectName());
169         }
170     }
171 }
172 
views() const173 QList<KoView*> KoPart::views() const
174 {
175     return d->views;
176 }
177 
viewCount() const178 int KoPart::viewCount() const
179 {
180     return d->views.count();
181 }
182 
createCanvasItem(KoDocument * document)183 QGraphicsItem *KoPart::createCanvasItem(KoDocument *document)
184 {
185     Q_UNUSED(document)
186     return 0;
187 /*    KoView *view = createView(document);
188     QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget();
189     QWidget *canvasController = view->findChild<KoCanvasControllerWidget*>();
190     proxy->setWidget(canvasController);
191     return proxy;*/
192 }
193 
addMainWindow(KoMainWindow * mainWindow)194 void KoPart::addMainWindow(KoMainWindow *mainWindow)
195 {
196     if (d->mainWindows.indexOf(mainWindow) == -1) {
197         debugMain <<"mainWindow" << (void*)mainWindow <<"added to doc" << this;
198         d->mainWindows.append(mainWindow);
199         connect(mainWindow, &KoMainWindow::configure, this, &KoPart::configure);
200     }
201 }
202 
removeMainWindow(KoMainWindow * mainWindow)203 void KoPart::removeMainWindow(KoMainWindow *mainWindow)
204 {
205     debugMain <<"mainWindow" << (void*)mainWindow <<"removed from doc" << this;
206     if (mainWindow) {
207         d->mainWindows.removeAll(mainWindow);
208         disconnect(mainWindow, &KoMainWindow::configure, this, &KoPart::configure);
209     }
210 }
211 
mainWindows() const212 const QList<KoMainWindow*>& KoPart::mainWindows() const
213 {
214     return d->mainWindows;
215 }
216 
mainwindowCount() const217 int KoPart::mainwindowCount() const
218 {
219     return d->mainWindows.count();
220 }
221 
222 
currentMainwindow() const223 KoMainWindow *KoPart::currentMainwindow() const
224 {
225     QWidget *widget = qApp->activeWindow();
226     KoMainWindow *mainWindow = qobject_cast<KoMainWindow*>(widget);
227     while (!mainWindow && widget) {
228         widget = widget->parentWidget();
229         mainWindow = qobject_cast<KoMainWindow*>(widget);
230     }
231 
232     if (!mainWindow && mainWindows().size() > 0) {
233         mainWindow = mainWindows().first();
234     }
235     return mainWindow;
236 
237 }
238 
openExistingFile(const QUrl & url)239 void KoPart::openExistingFile(const QUrl &url)
240 {
241     QApplication::setOverrideCursor(Qt::BusyCursor);
242     d->document->openUrl(url);
243     d->document->setModified(false);
244     QApplication::restoreOverrideCursor();
245 }
246 
openTemplate(const QUrl & url)247 void KoPart::openTemplate(const QUrl &url)
248 {
249     QApplication::setOverrideCursor(Qt::BusyCursor);
250     bool ok = d->document->loadNativeFormat(url.toLocalFile());
251     d->document->setModified(false);
252     d->document->undoStack()->clear();
253 
254     if (ok) {
255         QString mimeType = QMimeDatabase().mimeTypeForUrl(url).name();
256         // in case this is a open document template remove the -template from the end
257         mimeType.remove(QRegExp("-template$"));
258         d->document->setMimeTypeAfterLoading(mimeType);
259         d->document->resetURL();
260         d->document->setEmpty();
261     } else {
262         d->document->showLoadingErrorDialog();
263         d->document->initEmpty();
264     }
265     QApplication::restoreOverrideCursor();
266 }
267 
openProjectTemplate(const QUrl & url)268 bool KoPart::openProjectTemplate(const QUrl &url)
269 {
270     return false;
271 }
272 
addRecentURLToAllMainWindows(const QString & projectName,const QUrl & url)273 void KoPart::addRecentURLToAllMainWindows(const QString &projectName, const QUrl &url)
274 {
275     // Add to recent actions list in our mainWindows
276     foreach(KoMainWindow *mainWindow, d->mainWindows) {
277         mainWindow->addRecentURL(projectName, url);
278     }
279 
280 }
281 
setTemplatesResourcePath(const QString & templatesResourcePath)282 void KoPart::setTemplatesResourcePath(const QString &templatesResourcePath)
283 {
284     Q_ASSERT(!templatesResourcePath.isEmpty());
285     Q_ASSERT(templatesResourcePath.endsWith(QLatin1Char('/')));
286 
287     d->templatesResourcePath = templatesResourcePath;
288 }
289 
templatesResourcePath() const290 QString KoPart::templatesResourcePath() const
291 {
292     return d->templatesResourcePath;
293 }
294