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