Merge lp:~elgaton/ubuntu/precise/kile/fix-for-994498 into lp:ubuntu/precise/kile
- Precise (12.04)
- fix-for-994498
- Merge into precise
Proposed by
Alessandro Menti
Status: | Work in progress | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~elgaton/ubuntu/precise/kile/fix-for-994498 | ||||
Merge into: | lp:ubuntu/precise/kile | ||||
Diff against target: |
2490 lines (+2429/-5) 8 files modified
.pc/.quilt_patches (+1/-0) .pc/.quilt_series (+1/-0) .pc/applied-patches (+1/-0) .pc/kile-fix-closing-994498.patch/src/kiledocmanager.cpp (+2382/-0) debian/changelog (+7/-0) debian/patches/kile-fix-closing-994498.patch (+31/-0) debian/patches/series (+1/-0) src/kiledocmanager.cpp (+5/-5) |
||||
To merge this branch: | bzr merge lp:~elgaton/ubuntu/precise/kile/fix-for-994498 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Marc Deslauriers | Approve | ||
Ubuntu branches | Pending | ||
Review via email: mp+118919@code.launchpad.net |
Commit message
Description of the change
Backported patch from upstream to prevent crashes when Kile is closed and a project file is open
To post a comment you must log in.
- 49. By Alessandro Menti
-
* Added missing .pc files
Unmerged revisions
- 49. By Alessandro Menti
-
* Added missing .pc files
- 48. By Alessandro Menti <email address hidden>
-
* Fixed wrong distribution in the changelog
- 47. By Alessandro Menti <email address hidden>
-
* Added missing patch
- 46. By Alessandro Menti <email address hidden>
-
Fixed segfault on close when a project is open (LP: #994498). Patch by
Eugene Shalygin.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file '.pc/.quilt_patches' |
2 | --- .pc/.quilt_patches 1970-01-01 00:00:00 +0000 |
3 | +++ .pc/.quilt_patches 2012-08-25 08:51:18 +0000 |
4 | @@ -0,0 +1,1 @@ |
5 | +debian/patches |
6 | |
7 | === added file '.pc/.quilt_series' |
8 | --- .pc/.quilt_series 1970-01-01 00:00:00 +0000 |
9 | +++ .pc/.quilt_series 2012-08-25 08:51:18 +0000 |
10 | @@ -0,0 +1,1 @@ |
11 | +series |
12 | |
13 | === modified file '.pc/applied-patches' |
14 | --- .pc/applied-patches 2012-04-16 00:46:18 +0000 |
15 | +++ .pc/applied-patches 2012-08-25 08:51:18 +0000 |
16 | @@ -3,3 +3,4 @@ |
17 | kubuntu_01_improved_viewpart_warning.diff |
18 | kubuntu_02_disable_embedded_kbibtex.diff |
19 | kubuntu_use_utf8.diff |
20 | +kile-fix-closing-994498.patch |
21 | |
22 | === added directory '.pc/kile-fix-closing-994498.patch' |
23 | === added directory '.pc/kile-fix-closing-994498.patch/src' |
24 | === added file '.pc/kile-fix-closing-994498.patch/src/kiledocmanager.cpp' |
25 | --- .pc/kile-fix-closing-994498.patch/src/kiledocmanager.cpp 1970-01-01 00:00:00 +0000 |
26 | +++ .pc/kile-fix-closing-994498.patch/src/kiledocmanager.cpp 2012-08-25 08:51:18 +0000 |
27 | @@ -0,0 +1,2382 @@ |
28 | +/***************************************************************************** |
29 | +* Copyright (C) 2004 by Jeroen Wijnhout (Jeroen.Wijnhout@kdemail.net) * |
30 | +* (C) 2006-2010 by Michel Ludwig (michel.ludwig@kdemail.net) * |
31 | +* (C) 2007 by Holger Danielsson (holger.danielsson@versanet.de) * |
32 | +******************************************************************************/ |
33 | + |
34 | +/*************************************************************************** |
35 | + * * |
36 | + * This program is free software; you can redistribute it and/or modify * |
37 | + * it under the terms of the GNU General Public License as published by * |
38 | + * the Free Software Foundation; either version 2 of the License, or * |
39 | + * (at your option) any later version. * |
40 | + * * |
41 | + ***************************************************************************/ |
42 | + |
43 | +// 2007-03-12 dani |
44 | +// - use KileDocument::Extensions |
45 | + |
46 | +#include "kiledocmanager.h" |
47 | + |
48 | +#include <QAbstractItemView> |
49 | + |
50 | +#include <QTextCodec> |
51 | +#include <QFile> |
52 | +#include <QDir> |
53 | + |
54 | +#include <QList> |
55 | +#include <QDropEvent> |
56 | + |
57 | +#include <KTextEditor/Document> |
58 | +#include <KTextEditor/Editor> |
59 | +#include <KTextEditor/EditorChooser> |
60 | +#include <KTextEditor/SessionConfigInterface> |
61 | +#include <KTextEditor/View> |
62 | +#include <kapplication.h> |
63 | +#include "kiledebug.h" |
64 | +#include <KEncodingFileDialog> |
65 | +#include <KLocale> |
66 | +#include <KMimeType> |
67 | +#include <kmessagebox.h> |
68 | +#include <KProgressDialog> |
69 | +#include <kfile.h> |
70 | +#include <krun.h> |
71 | +#include <kstandarddirs.h> |
72 | +#include <kio/netaccess.h> |
73 | +#include <kpushbutton.h> |
74 | +#include <kurl.h> |
75 | +#include <kfileitem.h> |
76 | + |
77 | +#include "templates.h" |
78 | +#include "dialogs/newfilewizard.h" |
79 | +#include "dialogs/managetemplatesdialog.h" |
80 | +#include "kileinfo.h" |
81 | +#include "scriptmanager.h" |
82 | +#include "kileproject.h" |
83 | +#include "documentinfo.h" |
84 | +#include "kileviewmanager.h" |
85 | +#include "widgets/filebrowserwidget.h" |
86 | +#include "widgets/projectview.h" |
87 | +#include "widgets/structurewidget.h" |
88 | +#include "dialogs/projectdialogs.h" |
89 | +#include "kiletool.h" |
90 | +#include "kiletool_enums.h" |
91 | +#include "kilestdtools.h" |
92 | +#include "kilelistselector.h" |
93 | +#include "kiletoolmanager.h" |
94 | +#include "widgets/konsolewidget.h" |
95 | +#include "kileconfig.h" |
96 | +#include "widgets/logwidget.h" |
97 | +#include "widgets/progressdialog.h" |
98 | +#include "dialogs/cleandialog.h" |
99 | + |
100 | +/* |
101 | + * Newly created text documents have an empty URL and a non-empty document name. |
102 | + */ |
103 | + |
104 | +/* |
105 | + * WARNING: Several methods in the document manager can open dialogs and consequently |
106 | + * launch a new event loop. It is therefore possible that the auto save feature |
107 | + * gets triggered when such a dialog is shown, potentially modifying variables |
108 | + * that are currently being modified by the method in question. It is therefore |
109 | + * *essential* that the 'm_autoSaveLock' variable is locked before such a method is |
110 | + * executed (also see the 'Locker' class). |
111 | + */ |
112 | + |
113 | +class Locker |
114 | +{ |
115 | + public: |
116 | + Locker(unsigned int *lock) |
117 | + { |
118 | + m_lock = lock; |
119 | + ++*m_lock; |
120 | + } |
121 | + |
122 | + ~Locker() |
123 | + { |
124 | + if(*m_lock == 0) { |
125 | + return; |
126 | + } |
127 | + --*m_lock; |
128 | + } |
129 | + |
130 | + private: |
131 | + unsigned int *m_lock; |
132 | +}; |
133 | + |
134 | +#define MAX_NUMBER_OF_STORED_SETTINGS 50 |
135 | + |
136 | +namespace KileDocument |
137 | +{ |
138 | + |
139 | +Manager::Manager(KileInfo *info, QObject *parent, const char *name) : |
140 | + QObject(parent), |
141 | + m_ki(info), |
142 | + m_progressDialog(NULL), |
143 | + m_autoSaveLock(0), |
144 | + m_currentlySavingAll(false) |
145 | +{ |
146 | + setObjectName(name); |
147 | + m_editor = KTextEditor::EditorChooser::editor(); |
148 | + if(!m_editor) { |
149 | + KMessageBox::error(m_ki->mainWindow(), i18n("No editor component found. Please check your KDE installation."), |
150 | + i18n("No editor component found.")); |
151 | + } |
152 | +} |
153 | + |
154 | +Manager::~Manager() |
155 | +{ |
156 | + KILE_DEBUG() << "==KileDocument::Manager::~Manager()========="; |
157 | + if(m_progressDialog.isNull()) { |
158 | + delete m_progressDialog.data(); |
159 | + } |
160 | +} |
161 | + |
162 | +void Manager::trashDoc(TextInfo *docinfo, KTextEditor::Document *doc /*= NULL */ ) |
163 | +{ |
164 | + KILE_DEBUG() << "==void Manager::trashDoc(" << docinfo->url().toLocalFile() << ")====="; |
165 | + |
166 | + if(m_ki->isOpen(docinfo->url())) { |
167 | + return; |
168 | + } |
169 | + |
170 | + if(doc) { |
171 | + doc = docinfo->getDoc(); |
172 | + } |
173 | + |
174 | + //look for doc before we detach the docinfo |
175 | + //if we do it the other way around, docFor will always return nil |
176 | + if(!doc) { |
177 | + doc = docFor(docinfo->url()); |
178 | + } |
179 | + |
180 | + KILE_DEBUG() << "DETACHING " << docinfo; |
181 | + docinfo->detach(); |
182 | + |
183 | + KILE_DEBUG() << "\tTRASHING " << doc; |
184 | + if(!doc) { |
185 | + return; |
186 | + } |
187 | + |
188 | + KILE_DEBUG() << "just checking: docinfo->getDoc() = " << docinfo->getDoc(); |
189 | + KILE_DEBUG() << "just checking: docFor(docinfo->url()) = " << docFor(docinfo->url()); |
190 | + |
191 | + for (int i = 0; i < m_textInfoList.count(); ++i) { |
192 | + if((m_textInfoList.at(i) != docinfo) && (m_textInfoList.at(i)->getDoc() == doc)) { |
193 | + KMessageBox::information(0, i18n("The internal structure of Kile is corrupted (probably due to a bug in Kile). Please select Save All from the File menu and close Kile.\nThe Kile team apologizes for any inconvenience and would appreciate a bug report.")); |
194 | + kWarning() << "docinfo " << m_textInfoList.at(i) << " url " << m_textInfoList.at(i)->url().fileName() << " has a wild pointer!!!"; |
195 | + } |
196 | + } |
197 | + |
198 | + KILE_DEBUG() << "DELETING doc"; |
199 | + delete doc; |
200 | +} |
201 | + |
202 | +// update all Info's with changed user commands |
203 | +void Manager::updateInfos() |
204 | +{ |
205 | + for(QList<TextInfo*>::iterator it = m_textInfoList.begin(); it != m_textInfoList.end(); ++it) { |
206 | + (*it)->updateStructLevelInfo(); |
207 | + } |
208 | +} |
209 | + |
210 | +bool Manager::isAutoSaveAllowed() |
211 | +{ |
212 | + return (m_autoSaveLock == 0); |
213 | +} |
214 | + |
215 | +KTextEditor::Editor* Manager::getEditor() |
216 | +{ |
217 | + return m_editor; |
218 | +} |
219 | + |
220 | +KTextEditor::Document* Manager::docFor(const KUrl & url) |
221 | +{ |
222 | + for(QList<TextInfo*>::iterator it = m_textInfoList.begin(); it != m_textInfoList.end(); ++it) { |
223 | + TextInfo *info = *it; |
224 | + |
225 | + if(m_ki->similarOrEqualURL(info->url(), url)) { |
226 | + return info->getDoc(); |
227 | + } |
228 | + } |
229 | + |
230 | + return NULL; |
231 | +} |
232 | + |
233 | +Info* Manager::getInfo() const |
234 | +{ |
235 | + KTextEditor::Document *doc = m_ki->activeTextDocument(); |
236 | + if ( doc != 0L ) |
237 | + return textInfoFor(doc); |
238 | + else |
239 | + return 0L; |
240 | +} |
241 | + |
242 | +TextInfo* Manager::textInfoFor(const QString & path) const |
243 | +{ |
244 | + if(path.isEmpty()) { |
245 | + return NULL; |
246 | + } |
247 | + |
248 | + KILE_DEBUG() << "==KileInfo::textInfoFor(" << path << ")=========================="; |
249 | + for(QList<TextInfo*>::const_iterator it = m_textInfoList.begin(); it != m_textInfoList.end(); ++it) { |
250 | + TextInfo *info = *it; |
251 | + |
252 | + if(info->url().toLocalFile() == path) { |
253 | + return info; |
254 | + } |
255 | + } |
256 | + |
257 | + KILE_DEBUG() << "\tCOULD NOT find info for " << path; |
258 | + return NULL; |
259 | +} |
260 | + |
261 | +TextInfo* Manager::textInfoForURL(const KUrl& url) |
262 | +{ |
263 | + if(url.isEmpty()) { |
264 | + return NULL; |
265 | + } |
266 | + |
267 | + KILE_DEBUG() << "==KileInfo::textInfoFor(" << url << ")=========================="; |
268 | + |
269 | + for(QList<TextInfo*>::iterator it = m_textInfoList.begin(); it != m_textInfoList.end(); ++it) { |
270 | + TextInfo *info = *it; |
271 | + |
272 | + if (info->url() == url) { |
273 | + return info; |
274 | + } |
275 | + } |
276 | + |
277 | + KILE_DEBUG() << "\tCOULD NOT find info for " << url; |
278 | + return NULL; |
279 | +} |
280 | + |
281 | +TextInfo* Manager::textInfoFor(KTextEditor::Document* doc) const |
282 | +{ |
283 | + if(!doc) { |
284 | + return NULL; |
285 | + } |
286 | + |
287 | + for(QList<TextInfo*>::const_iterator it = m_textInfoList.begin(); it != m_textInfoList.end(); ++it) { |
288 | + if((*it)->getDoc() == doc) { |
289 | + return (*it); |
290 | + } |
291 | + } |
292 | + |
293 | + return NULL; |
294 | +} |
295 | + |
296 | +void Manager::mapItem(TextInfo *docinfo, KileProjectItem *item) |
297 | +{ |
298 | + item->setInfo(docinfo); |
299 | +} |
300 | + |
301 | +KileProject* Manager::projectFor(const KUrl &projecturl) |
302 | +{ |
303 | + //find project with url = projecturl |
304 | + for(QList<KileProject*>::iterator it = m_projects.begin(); it != m_projects.end(); ++it) { |
305 | + KileProject *project = *it; |
306 | + if(project->url() == projecturl) { |
307 | + return project; |
308 | + } |
309 | + } |
310 | + |
311 | + return NULL; |
312 | +} |
313 | + |
314 | +KileProject* Manager::projectFor(const QString &name) |
315 | +{ |
316 | + //find project with url = projecturl |
317 | + for(QList<KileProject*>::iterator it = m_projects.begin(); it != m_projects.end(); ++it) { |
318 | + KileProject *project = *it; |
319 | + |
320 | + if (project->name() == name) { |
321 | + return project; |
322 | + } |
323 | + } |
324 | + |
325 | + return NULL; |
326 | +} |
327 | + |
328 | +KileProjectItem* Manager::itemFor(const KUrl &url, KileProject *project /*=0L*/) const |
329 | +{ |
330 | + if (!project) { |
331 | + for(QList<KileProject*>::const_iterator it = m_projects.begin(); it != m_projects.end(); ++it) { |
332 | + KileProject *project = *it; |
333 | + |
334 | + KILE_DEBUG() << "looking in project " << project->name(); |
335 | + if (project->contains(url)) { |
336 | + KILE_DEBUG() << "\t\tfound!"; |
337 | + return project->item(url); |
338 | + } |
339 | + } |
340 | + KILE_DEBUG() << "\t nothing found"; |
341 | + } |
342 | + else { |
343 | + if(project->contains(url)) { |
344 | + return project->item(url); |
345 | + } |
346 | + } |
347 | + |
348 | + return NULL; |
349 | +} |
350 | + |
351 | +KileProjectItem* Manager::itemFor(Info *docinfo, KileProject *project /*=0*/) const |
352 | +{ |
353 | + if(docinfo) |
354 | + return itemFor(docinfo->url(), project); |
355 | + else |
356 | + return NULL; |
357 | +} |
358 | + |
359 | +QList<KileProjectItem*> Manager::itemsFor(Info *docinfo) const |
360 | +{ |
361 | + if(!docinfo) { |
362 | + return QList<KileProjectItem*>(); |
363 | + } |
364 | + |
365 | + KILE_DEBUG() << "==KileInfo::itemsFor(" << docinfo->url().fileName() << ")============"; |
366 | + QList<KileProjectItem*> list; |
367 | + for(QList<KileProject*>::const_iterator it = m_projects.begin(); it != m_projects.end(); ++it) { |
368 | + KileProject *project = *it; |
369 | + |
370 | + KILE_DEBUG() << "\tproject: " << (*it)->name(); |
371 | + if(project->contains(docinfo)) { |
372 | + KILE_DEBUG() << "\t\tcontains"; |
373 | + list.append(project->item(docinfo)); |
374 | + } |
375 | + } |
376 | + |
377 | + return list; |
378 | +} |
379 | + |
380 | +QList<KileProjectItem*> Manager::itemsFor(const KUrl& url) const |
381 | +{ |
382 | + QList<KileProjectItem*> list; |
383 | + for(QList<KileProject*>::const_iterator it = m_projects.begin(); it != m_projects.end(); ++it) { |
384 | + KileProject *project = *it; |
385 | + |
386 | + if(project->contains(url)) { |
387 | + list.append(project->item(url)); |
388 | + } |
389 | + } |
390 | + |
391 | + return list; |
392 | +} |
393 | + |
394 | +bool Manager::isProjectOpen() |
395 | +{ |
396 | + return ( m_projects.count() > 0 ); |
397 | +} |
398 | + |
399 | +KileProject* Manager::activeProject() |
400 | +{ |
401 | + KTextEditor::Document *doc = m_ki->activeTextDocument(); |
402 | + |
403 | + if (doc) { |
404 | + for(QList<KileProject*>::iterator it = m_projects.begin(); it != m_projects.end(); ++it) { |
405 | + KileProject *project = *it; |
406 | + |
407 | + if(project->contains(doc->url())) { |
408 | + return project; |
409 | + } |
410 | + } |
411 | + } |
412 | + |
413 | + return NULL; |
414 | +} |
415 | + |
416 | +KileProjectItem* Manager::activeProjectItem() |
417 | +{ |
418 | + KileProject *curpr = activeProject(); |
419 | + KTextEditor::Document *doc = m_ki->activeTextDocument(); |
420 | + |
421 | + if (curpr && doc) { |
422 | + QList<KileProjectItem*> list = curpr->items(); |
423 | + |
424 | + for(QList<KileProjectItem*>::iterator it = list.begin(); it != list.end(); ++it) { |
425 | + KileProjectItem *item = *it; |
426 | + |
427 | + if (item->url() == doc->url()) { |
428 | + return item; |
429 | + } |
430 | + } |
431 | + } |
432 | + |
433 | + return NULL; |
434 | +} |
435 | + |
436 | +TextInfo* Manager::createTextDocumentInfo(KileDocument::Type type, const KUrl & url, const KUrl& baseDirectory) |
437 | +{ |
438 | + TextInfo *docinfo = 0L; |
439 | + |
440 | + //see if this file belongs to an opened project |
441 | + KileProjectItem *item = itemFor(url); |
442 | + if ( item != 0L ) docinfo = item->getInfo(); |
443 | + |
444 | + if ( docinfo == 0L ) |
445 | + { |
446 | + switch(type) |
447 | + { |
448 | + case Undefined: // fall through |
449 | + case Text: |
450 | + KILE_DEBUG() << "CREATING TextInfo for " << url.url(); |
451 | + docinfo = new TextInfo(NULL, m_ki->extensions(), |
452 | + m_ki->abbreviationManager()); |
453 | + break; |
454 | + case LaTeX: |
455 | + KILE_DEBUG() << "CREATING LaTeXInfo for " << url.url(); |
456 | + docinfo = new LaTeXInfo(NULL, m_ki->extensions(), |
457 | + m_ki->abbreviationManager(), |
458 | + m_ki->latexCommands(), |
459 | + m_ki->editorExtension(), |
460 | + m_ki->configurationManager(), |
461 | + m_ki->codeCompletionManager()); |
462 | + break; |
463 | + case BibTeX: |
464 | + KILE_DEBUG() << "CREATING BibInfo for " << url.url(); |
465 | + docinfo = new BibInfo(NULL, m_ki->extensions(), |
466 | + m_ki->abbreviationManager(), |
467 | + m_ki->latexCommands()); |
468 | + break; |
469 | + case Script: |
470 | + KILE_DEBUG() << "CREATING ScriptInfo for " << url.url(); |
471 | + docinfo = new ScriptInfo(NULL, m_ki->extensions(), |
472 | + m_ki->abbreviationManager()); |
473 | + break; |
474 | + } |
475 | + docinfo->setBaseDirectory(baseDirectory); |
476 | + emit(documentInfoCreated(docinfo)); |
477 | + m_textInfoList.append(docinfo); |
478 | + } |
479 | + |
480 | + KILE_DEBUG() << "DOCINFO: returning " << docinfo << " " << docinfo->url().fileName(); |
481 | + return docinfo; |
482 | +} |
483 | + |
484 | +void Manager::recreateTextDocumentInfo(TextInfo *oldinfo) |
485 | +{ |
486 | + QList<KileProjectItem*> list = itemsFor(oldinfo); |
487 | + KUrl url = oldinfo->url(); |
488 | + TextInfo *newinfo = createTextDocumentInfo(m_ki->extensions()->determineDocumentType(url), url, oldinfo->getBaseDirectory()); |
489 | + |
490 | + newinfo->setDoc(oldinfo->getDoc()); |
491 | + |
492 | + for(QList<KileProjectItem*>::iterator it = list.begin(); it != list.end(); ++it) { |
493 | + (*it)->setInfo(newinfo); |
494 | + } |
495 | + |
496 | + removeTextDocumentInfo(oldinfo); |
497 | + |
498 | + emit(updateStructure(false, newinfo)); |
499 | +} |
500 | + |
501 | +bool Manager::removeTextDocumentInfo(TextInfo *docinfo, bool closingproject /* = false */) |
502 | +{ |
503 | + KILE_DEBUG() << "==Manager::removeTextDocumentInfo(Info *docinfo)====="; |
504 | + QList<KileProjectItem*> itms = itemsFor(docinfo); |
505 | + bool oneItem = false; |
506 | + if(itms.count() == 1) { |
507 | + oneItem = true; |
508 | + } |
509 | + |
510 | + if(itms.count() == 0 || ( closingproject && oneItem )) { |
511 | + KILE_DEBUG() << "\tremoving " << docinfo << " count = " << m_textInfoList.count(); |
512 | + m_textInfoList.removeAll(docinfo); |
513 | + |
514 | + emit(closingDocument(docinfo)); |
515 | + |
516 | + cleanupDocumentInfoForProjectItems(docinfo); |
517 | + delete docinfo; |
518 | + |
519 | + return true; |
520 | + } |
521 | + |
522 | + KILE_DEBUG() << "\tnot removing " << docinfo; |
523 | + return false; |
524 | +} |
525 | + |
526 | + |
527 | +KTextEditor::Document* Manager::createDocument(const KUrl& url, TextInfo *docinfo, const QString& encoding, |
528 | + const QString& mode, |
529 | + const QString& highlight) |
530 | +{ |
531 | + KILE_DEBUG() << "==KTextEditor::Document* Manager::createDocument()==========="; |
532 | + |
533 | + KTextEditor::Document *doc = NULL; |
534 | + |
535 | + if(!m_editor) { |
536 | + return NULL; |
537 | + } |
538 | + |
539 | + doc = docFor(url); |
540 | + if (doc) { |
541 | + kWarning() << url << " already has a document!"; |
542 | + return doc; |
543 | + } |
544 | + doc = m_editor->createDocument(NULL); |
545 | + KILE_DEBUG() << "appending document " << doc; |
546 | + |
547 | + docinfo->setDoc(doc); // do this here to set up all the signals correctly in 'TextInfo' |
548 | + doc->setEncoding(encoding); |
549 | + |
550 | + KILE_DEBUG() << "url is = " << docinfo->url(); |
551 | + |
552 | + if(!url.isEmpty()) { |
553 | + bool r = doc->openUrl(url); |
554 | + // don't add scripts to the recent files |
555 | + if(r && docinfo->getType() != Script) { |
556 | + emit(addToRecentFiles(url)); |
557 | + } |
558 | + } |
559 | + |
560 | + //handle changes of the document |
561 | + connect(doc, SIGNAL(documentNameChanged(KTextEditor::Document*)), this, SIGNAL(documentNameChanged(KTextEditor::Document*))); |
562 | + connect(doc, SIGNAL(documentUrlChanged(KTextEditor::Document*)), this, SIGNAL(documentUrlChanged(KTextEditor::Document*))); |
563 | + connect(doc, SIGNAL(modifiedChanged(KTextEditor::Document*)), this, SLOT(newDocumentStatus(KTextEditor::Document*))); |
564 | + KTextEditor::ModificationInterface *modificationInterface = qobject_cast<KTextEditor::ModificationInterface*>(doc); |
565 | + if(modificationInterface) { |
566 | + modificationInterface->setModifiedOnDiskWarning(true); |
567 | + connect(doc, SIGNAL(modifiedOnDisk(KTextEditor::Document*,bool,KTextEditor::ModificationInterface::ModifiedOnDiskReason)), |
568 | + this, SIGNAL(documentModificationStatusChanged(KTextEditor::Document*,bool,KTextEditor::ModificationInterface::ModifiedOnDiskReason))); |
569 | + } |
570 | + |
571 | + if(!mode.isEmpty()){ |
572 | + docinfo->setMode(mode); // this ensures that mode passed with the mode parameter is actually used |
573 | + } |
574 | + if(!highlight.isEmpty()){ |
575 | + docinfo->setHighlightingMode(highlight); |
576 | + } |
577 | + // FIXME: the whole structure updating stuff needs to be rewritten; updates should originate from |
578 | + // the docinfo only, i.e. the structure view should just react to changes! |
579 | + connect(docinfo, SIGNAL(completed(KileDocument::Info*)), m_ki->structureWidget(), SLOT(update(KileDocument::Info*))); |
580 | + |
581 | + KILE_DEBUG() << "createDocument: url " << doc->url(); |
582 | + KILE_DEBUG() << "createDocument: SANITY check: " << (docinfo->getDoc() == docFor(docinfo->url())); |
583 | + return doc; |
584 | +} |
585 | + |
586 | +KTextEditor::View* Manager::loadItem(KileDocument::Type type, KileProjectItem *item, const QString & text, bool openProjectItemViews) |
587 | +{ |
588 | + KTextEditor::View *view = NULL; |
589 | + |
590 | + KILE_DEBUG() << "==loadItem(" << item->url().toLocalFile() << ")======"; |
591 | + |
592 | + if(item->type() != KileProjectItem::Image) { |
593 | + view = loadText(type, item->url(), item->encoding(), openProjectItemViews && item->isOpen(), item->mode(), item->highlight(), text); |
594 | + KILE_DEBUG() << "\tloadItem: docfor = " << docFor(item->url().toLocalFile()); |
595 | + |
596 | + TextInfo *docinfo = textInfoFor(item->url().toLocalFile()); |
597 | + item->setInfo(docinfo); |
598 | + |
599 | + KILE_DEBUG() << "\tloadItem: docinfo = " << docinfo << " doc = " << docinfo->getDoc() << " docfor = " << docFor(docinfo->url().toLocalFile()); |
600 | + if ( docinfo->getDoc() != docFor(docinfo->url().toLocalFile()) ) kWarning() << "docinfo->getDoc() != docFor()"; |
601 | + } |
602 | + else { |
603 | + KILE_DEBUG() << "\tloadItem: no document generated"; |
604 | + TextInfo *docinfo = createTextDocumentInfo(m_ki->extensions()->determineDocumentType(item->url()), item->url()); |
605 | + item->setInfo(docinfo); |
606 | + |
607 | + if(!docFor(item->url())) { |
608 | + docinfo->detach(); |
609 | + KILE_DEBUG() << "\t\t\tdetached"; |
610 | + } |
611 | + } |
612 | + |
613 | + return view; |
614 | +} |
615 | + |
616 | +KTextEditor::View* Manager::loadText(KileDocument::Type type, const KUrl& url, const QString& encoding, |
617 | + bool create, |
618 | + const QString& mode, |
619 | + const QString& highlight, |
620 | + const QString& text, |
621 | + int index, |
622 | + const KUrl& baseDirectory) |
623 | +{ |
624 | + KILE_DEBUG() << "==loadText(" << url.url() << ")================="; |
625 | + //if doc already opened, update the structure view and return the view |
626 | + if(!url.isEmpty() && m_ki->isOpen(url)) { |
627 | + return m_ki->viewManager()->switchToTextView(url); |
628 | + } |
629 | + |
630 | + TextInfo *docinfo = createTextDocumentInfo(type, url, baseDirectory); |
631 | + KTextEditor::Document *doc = createDocument(url, docinfo, encoding, mode, highlight); |
632 | + |
633 | + m_ki->structureWidget()->clean(docinfo); |
634 | + |
635 | + if(!text.isEmpty()) { |
636 | + doc->setText(text); |
637 | + } |
638 | + |
639 | + //FIXME: use signal/slot |
640 | + if (doc && create) { |
641 | + return m_ki->viewManager()->createTextView(docinfo, index); |
642 | + } |
643 | + |
644 | + KILE_DEBUG() << "just after createView()"; |
645 | + KILE_DEBUG() << "\tdocinfo = " << docinfo << " doc = " << docinfo->getDoc() << " docfor = " << docFor(docinfo->url().toLocalFile()); |
646 | + |
647 | + return NULL; |
648 | +} |
649 | + |
650 | +//FIXME: template stuff should be in own class |
651 | +KTextEditor::View* Manager::loadTemplate(TemplateItem *sel) |
652 | +{ |
653 | + KILE_DEBUG() << "templateitem *sel = " << sel; |
654 | + QString text; |
655 | + |
656 | + if(!sel) { |
657 | + return NULL; |
658 | + } |
659 | + |
660 | + Locker lock(&m_autoSaveLock); |
661 | + if (sel->name() != KileTemplate::Manager::defaultEmptyTemplateCaption() |
662 | + && sel->name() != KileTemplate::Manager::defaultEmptyLaTeXTemplateCaption() |
663 | + && sel->name() != KileTemplate::Manager::defaultEmptyBibTeXTemplateCaption()) { |
664 | + if(!m_editor) { |
665 | + return NULL; |
666 | + } |
667 | + //create a new document to open the template in |
668 | + KTextEditor::Document *tempdoc = m_editor->createDocument(NULL); |
669 | + |
670 | + if (!tempdoc->openUrl(KUrl(sel->path()))) { |
671 | + KMessageBox::error(m_ki->mainWindow(), i18n("Could not find template: %1", sel->name()), i18n("File Not Found")); |
672 | + } |
673 | + else { |
674 | + //substitute templates variables |
675 | + text = tempdoc->text(); |
676 | + delete tempdoc; |
677 | + replaceTemplateVariables(text); |
678 | + } |
679 | + } |
680 | + |
681 | + KileDocument::Type type = sel->type(); |
682 | + //always set the base directory for scripts |
683 | + return createDocumentWithText(text, type, QString(), (type == KileDocument::Script ? m_ki->scriptManager()->getLocalScriptDirectory() : QString())); |
684 | +} |
685 | + |
686 | +KTextEditor::View* Manager::createDocumentWithText(const QString& text, KileDocument::Type type /* = KileDocument::Undefined */, const QString& /* extension */, const KUrl& baseDirectory) |
687 | +{ |
688 | + KTextEditor::View *view = loadText(type, KUrl(), QString(), true, QString(), QString(), text, -1, baseDirectory); |
689 | + if(view) { |
690 | + //FIXME this shouldn't be necessary!!! |
691 | + view->document()->setModified(true); |
692 | + newDocumentStatus(view->document()); |
693 | + } |
694 | + |
695 | + return view; |
696 | +} |
697 | + |
698 | +KTextEditor::View* Manager::createNewJScript() |
699 | +{ |
700 | + KTextEditor::View *view = createDocumentWithText(QString(), Script, "js", m_ki->scriptManager()->getLocalScriptDirectory()); |
701 | + emit(updateStructure(false, NULL)); |
702 | + emit(updateModeStatus()); |
703 | + return view; |
704 | +} |
705 | + |
706 | +KTextEditor::View* Manager::createNewLaTeXDocument() |
707 | +{ |
708 | + KTextEditor::View *view = createDocumentWithText(QString(), LaTeX); |
709 | + emit(updateStructure(false, NULL)); |
710 | + emit(updateModeStatus()); |
711 | + return view; |
712 | +} |
713 | + |
714 | +void Manager::replaceTemplateVariables(QString &line) |
715 | +{ |
716 | + line=line.replace("$$AUTHOR$$", KileConfig::author()); |
717 | + line=line.replace("$$DOCUMENTCLASSOPTIONS$$", KileConfig::documentClassOptions()); |
718 | + if (!KileConfig::templateEncoding().isEmpty()) { line=line.replace("$$INPUTENCODING$$", "\\usepackage["+ KileConfig::templateEncoding() +"]{inputenc}");} |
719 | + else { |
720 | + line = line.remove("$$INPUTENCODING$$"); |
721 | + } |
722 | +} |
723 | + |
724 | +void Manager::createTemplate() |
725 | +{ |
726 | + KTextEditor::View *view = m_ki->viewManager()->currentTextView(); |
727 | + if (view) { |
728 | + if (view->document()->isModified()) { |
729 | + KMessageBox::information(m_ki->mainWindow(),i18n("Please save the file first.")); |
730 | + return; |
731 | + } |
732 | + } |
733 | + else { |
734 | + KMessageBox::information(m_ki->mainWindow(),i18n("Open/create a document first.")); |
735 | + return; |
736 | + } |
737 | + |
738 | + KUrl url = view->document()->url(); |
739 | + KileDocument::Type type = m_ki->extensions()->determineDocumentType(url); |
740 | + |
741 | + if(type == KileDocument::Undefined || type == KileDocument::Text) { |
742 | + KMessageBox::information(m_ki->mainWindow(),i18n("A template for this type of document cannot be created.")); |
743 | + return; |
744 | + } |
745 | + |
746 | + ManageTemplatesDialog mtd(m_ki->templateManager(), url, i18n("Create Template From Document")); |
747 | + mtd.exec(); |
748 | +} |
749 | + |
750 | +void Manager::removeTemplate() |
751 | +{ |
752 | + ManageTemplatesDialog mtd(m_ki->templateManager(), i18n("Remove Template")); |
753 | + mtd.exec(); |
754 | +} |
755 | + |
756 | +void Manager::fileNew(KileDocument::Type type) |
757 | +{ |
758 | + NewFileWizard *nfw = new NewFileWizard(m_ki->templateManager(), type, m_ki->mainWindow()); |
759 | + if(nfw->exec()) { |
760 | + Locker lock(&m_autoSaveLock); |
761 | + KTextEditor::View *view = loadTemplate(nfw->getSelection()); |
762 | + if(view) { |
763 | + if(nfw->useWizard()) { |
764 | + emit(startWizard()); |
765 | + } |
766 | + emit(updateStructure(false, NULL)); |
767 | + emit(updateModeStatus()); |
768 | + } |
769 | + } |
770 | + delete nfw; |
771 | +} |
772 | + |
773 | +void Manager::fileNewScript() |
774 | +{ |
775 | + Locker lock(&m_autoSaveLock); |
776 | + fileNew(KileDocument::Script); |
777 | +} |
778 | + |
779 | +void Manager::fileNew(const KUrl& url) |
780 | +{ |
781 | + Locker lock(&m_autoSaveLock); |
782 | + //create an empty file |
783 | + QFile file(url.toLocalFile()); |
784 | + file.open(QIODevice::ReadWrite); |
785 | + file.close(); |
786 | + |
787 | + fileOpen(url, QString()); |
788 | +} |
789 | + |
790 | +void Manager::fileOpen() |
791 | +{ |
792 | + //determine the starting dir for the file dialog |
793 | + QString compileName = m_ki->getCompileName(); |
794 | + QString currentDir; |
795 | + if(QFileInfo(compileName).exists()) { |
796 | + currentDir = QFileInfo(compileName).absolutePath(); |
797 | + } |
798 | + else { |
799 | + currentDir = m_ki->fileSelector()->currentUrl().toLocalFile(); |
800 | + } |
801 | + |
802 | + // use a filter for fileOpen dialog |
803 | + Extensions *extensions = m_ki->extensions(); |
804 | + QString filter = extensions->latexDocumentFileFilter() + '\n' |
805 | + + extensions->latexPackageFileFilter() + '\n' |
806 | + + extensions->bibtexFileFilter() + '\n' |
807 | + + extensions->metapostFileFilter() + '\n' |
808 | + + "*|" + i18n("All Files"); |
809 | + |
810 | + // try to get the current encoding, this is kind of ugly ... |
811 | + QString encoding = m_ki->toolManager()->config()->group("Kate Document Defaults").readEntry("Encoding",""); |
812 | + |
813 | + //get the URLs |
814 | + KEncodingFileDialog::Result result = KEncodingFileDialog::getOpenUrlsAndEncoding(encoding, currentDir, filter, m_ki->mainWindow(), i18n("Open Files")); |
815 | + |
816 | + Locker lock(&m_autoSaveLock); |
817 | + //open them |
818 | + KUrl::List urls = result.URLs; |
819 | + for (KUrl::List::Iterator i=urls.begin(); i != urls.end(); ++i) { |
820 | + fileOpen(*i, result.encoding); |
821 | + } |
822 | +} |
823 | + |
824 | +void Manager::fileSelected(const KFileItem& file) |
825 | +{ |
826 | + Locker lock(&m_autoSaveLock); |
827 | + fileSelected(file.url()); |
828 | +} |
829 | + |
830 | +void Manager::fileSelected(const KileProjectItem * item) |
831 | +{ |
832 | + Locker lock(&m_autoSaveLock); |
833 | + fileOpen(item->url(), item->encoding()); |
834 | +} |
835 | + |
836 | +void Manager::fileSelected(const KUrl& url) |
837 | +{ |
838 | + Locker lock(&m_autoSaveLock); |
839 | + fileOpen(url, QString()); |
840 | +} |
841 | + |
842 | +void Manager::saveURL(const KUrl & url) |
843 | +{ |
844 | + Locker lock(&m_autoSaveLock); |
845 | + KTextEditor::Document *doc = docFor(url); |
846 | + if(doc) { |
847 | + doc->save(); |
848 | + } |
849 | +} |
850 | + |
851 | +void Manager::newDocumentStatus(KTextEditor::Document *doc) |
852 | +{ |
853 | + KILE_DEBUG() << "void Manager::newDocumentStatus(Kate::Document)" << endl; |
854 | + if(!doc) { |
855 | + return; |
856 | + } |
857 | + |
858 | + //sync terminal |
859 | + m_ki->texKonsole()->sync(); |
860 | + |
861 | + emit(documentModificationStatusChanged(doc, doc->isModified(), KTextEditor::ModificationInterface::OnDiskUnmodified)); |
862 | +} |
863 | + |
864 | +bool Manager::fileSaveAll(bool amAutoSaving, bool disUntitled) |
865 | +{ |
866 | + // this can occur when autosaving should take place when we |
867 | + // are still busy with it (KIO::NetAccess keeps the event loop running) |
868 | + if(m_currentlySavingAll) { |
869 | + return true; |
870 | + } |
871 | + m_currentlySavingAll = true; |
872 | + KTextEditor::View *view = NULL; |
873 | + QFileInfo fi; |
874 | + bool oneSaveFailed = false; |
875 | + KUrl url, backupUrl; |
876 | + |
877 | + KILE_DEBUG() << "===Kile::fileSaveAll(amAutoSaving = " << amAutoSaving << ",disUntitled = " << disUntitled <<")"; |
878 | + |
879 | + for(int i = 0; i < m_ki->viewManager()->textViewCount(); ++i) { |
880 | + view = m_ki->viewManager()->textView(i); |
881 | + |
882 | + if(view && view->document()->isModified()) { |
883 | + url = view->document()->url(); |
884 | + fi.setFile(url.toLocalFile()); |
885 | + |
886 | + if( (!amAutoSaving && !(disUntitled && url.isEmpty())) // DisregardUntitled is true and we have an untitled doc and don't autosave |
887 | + || (amAutoSaving && !url.isEmpty()) //don't save untitled documents when autosaving |
888 | + || (!amAutoSaving && !disUntitled) // both false, so we want to save everything |
889 | + ) |
890 | + { |
891 | + |
892 | + KILE_DEBUG() << "The files _" << autosaveWarnings.join(", ") << "_ have autosaveWarnings"; |
893 | + |
894 | + if(amAutoSaving) { |
895 | + if(!fi.isWritable()) { |
896 | + if(autosaveWarnings.contains(url.toLocalFile())) { |
897 | + KILE_DEBUG() << "File " << url.prettyUrl() << " is not writeable (again), trying next file"; |
898 | + continue; |
899 | + } |
900 | + else { |
901 | + autosaveWarnings.append(url.toLocalFile()); |
902 | + KILE_DEBUG() << "File " << url.prettyUrl() << " is not writeable (first time)"; |
903 | + } |
904 | + } |
905 | + else { |
906 | + autosaveWarnings.removeAll(url.toLocalFile()); |
907 | + } |
908 | + } |
909 | + if(amAutoSaving && fi.size() > 0) { // the size check ensures that we don't save empty files (to prevent something like #125809 in the future). |
910 | + KUrl backupUrl = KUrl(url.toLocalFile()+ ".backup"); |
911 | + |
912 | + // patch for secure permissions, slightly modified for kile by Thomas Braun, taken from #103331 |
913 | + |
914 | + // get the right permissions, start with safe default |
915 | + mode_t perms = 0600; |
916 | + KIO::UDSEntry fentry; |
917 | + if (KIO::NetAccess::stat (url, fentry, m_ki->mainWindow())) { |
918 | + KILE_DEBUG () << "stating successful: " << url.prettyUrl(); |
919 | + KFileItem item (fentry, url); |
920 | + perms = item.permissions(); |
921 | + } |
922 | + |
923 | + // first del existing file if any, than copy over the file we have |
924 | + // failure if a: the existing file could not be deleted, b: the file could not be copied |
925 | + if((!KIO::NetAccess::exists( backupUrl, false, m_ki->mainWindow()) |
926 | + || KIO::NetAccess::del( backupUrl, m_ki->mainWindow())) |
927 | + && KIO::NetAccess::file_copy(url, backupUrl, m_ki->mainWindow())) { |
928 | + KILE_DEBUG() << "backing up successful (" << url.prettyUrl() << " -> "<<backupUrl.prettyUrl() << ")"; |
929 | + } |
930 | + else { |
931 | + KILE_DEBUG() << "backing up failed (" << url.prettyUrl() << " -> " << backupUrl.prettyUrl() << ")"; |
932 | + m_ki->logWidget()->printMessage(KileTool::Error, |
933 | + i18n("The file %1 could not be saved, check the permissions and free disk space.", backupUrl.prettyUrl()), |
934 | + i18n("Autosave")); |
935 | + } |
936 | + } |
937 | + |
938 | + KILE_DEBUG() << "trying to save: " << url.toLocalFile(); |
939 | + bool saveResult = view->document()->documentSave(); |
940 | + fi.refresh(); |
941 | + |
942 | + if(!saveResult) { |
943 | + oneSaveFailed = true; |
944 | + m_ki->logWidget()->printMessage(KileTool::Error, |
945 | + i18n("Kile encountered problems while saving the file %1. Do you have enough free disk space left?", url.prettyUrl()), |
946 | + i18n("Saving")); |
947 | + } |
948 | + } |
949 | + } |
950 | + } |
951 | + |
952 | + /* |
953 | + This may look superfluos but actually it is not, in the case of multiple modified docs it ensures that the structure view keeps synchronized with the currentTextView |
954 | + And if we only have one masterdoc or none nothing goes wrong. |
955 | + */ |
956 | + emit(updateStructure(false, NULL)); |
957 | + m_currentlySavingAll = false; |
958 | + return !oneSaveFailed; |
959 | +} |
960 | + |
961 | +void Manager::fileOpen(const KUrl& url, const QString& encoding, int index) |
962 | +{ |
963 | + Locker lock(&m_autoSaveLock); |
964 | + KILE_DEBUG() << "==Kile::fileOpen=========================="; |
965 | + |
966 | + KILE_DEBUG() << "url is " << url.url(); |
967 | + const KUrl realurl = symlinkFreeURL(url); |
968 | + KILE_DEBUG() << "symlink free url is " << realurl.url(); |
969 | + |
970 | + bool isopen = m_ki->isOpen(realurl); |
971 | + if(isopen) { |
972 | + m_ki->viewManager()->switchToTextView(realurl); |
973 | + return; |
974 | + } |
975 | + |
976 | + KTextEditor::View *view = loadText(m_ki->extensions()->determineDocumentType(realurl), realurl, encoding, true, QString(), QString(), QString(), index); |
977 | + QList<KileProjectItem*> itemList = itemsFor(realurl); |
978 | + TextInfo *textInfo = textInfoForURL(realurl); |
979 | + |
980 | + for(QList<KileProjectItem*>::iterator it = itemList.begin(); it != itemList.end(); ++it) { |
981 | + (*it)->setInfo(textInfo); |
982 | + } |
983 | + |
984 | + if(itemList.isEmpty()) { |
985 | + emit addToProjectView(realurl); |
986 | + loadDocumentAndViewSettings(view->document()); |
987 | + } |
988 | + else if(view) { |
989 | + KileProjectItem *item = itemList.first(); |
990 | + view->setCursorPosition(KTextEditor::Cursor(item->lineNumber(),item->columnNumber())); |
991 | + item->loadDocumentAndViewSettings(); |
992 | + } |
993 | + |
994 | + emit(updateStructure(false, NULL)); |
995 | + emit(updateModeStatus()); |
996 | + // update undefined references in this file |
997 | + emit(updateReferences(textInfoFor(realurl.toLocalFile()))); |
998 | +} |
999 | + |
1000 | +bool Manager::fileSave(KTextEditor::View *view) |
1001 | +{ |
1002 | + Locker lock(&m_autoSaveLock); |
1003 | + if(!view) { |
1004 | + view = m_ki->viewManager()->currentTextView(); |
1005 | + } |
1006 | + if(!view) { |
1007 | + return false; |
1008 | + } |
1009 | + KUrl url = view->document()->url(); |
1010 | + if(url.isEmpty()) { // newly created document |
1011 | + return fileSaveAs(view); |
1012 | + } |
1013 | + else { |
1014 | + bool ret = view->document()->documentSave(); |
1015 | + emit(updateStructure(false, textInfoFor(view->document()))); |
1016 | + return ret; |
1017 | + } |
1018 | +} |
1019 | + |
1020 | +bool Manager::fileSaveAs(KTextEditor::View* view) |
1021 | +{ |
1022 | + Locker lock(&m_autoSaveLock); |
1023 | + if(!view) { |
1024 | + view = m_ki->viewManager()->currentTextView(); |
1025 | + } |
1026 | + if(!view) { |
1027 | + return false; |
1028 | + } |
1029 | + |
1030 | + KTextEditor::Document* doc = view->document(); |
1031 | + Q_ASSERT(doc); |
1032 | + KileDocument::TextInfo* info = textInfoFor(doc); |
1033 | + Q_ASSERT(info); |
1034 | + QString startDir = info->url().url(); |
1035 | + KUrl oldURL = info->url(); |
1036 | + if(startDir.isEmpty()) { |
1037 | + KUrl baseDirectory = info->getBaseDirectory(); |
1038 | + if(baseDirectory.isEmpty()) { |
1039 | + startDir = "kfiledialog:///KILE_LATEX_SAVE_DIR"; |
1040 | + } |
1041 | + else { |
1042 | + startDir = baseDirectory.url(); |
1043 | + } |
1044 | + } |
1045 | + |
1046 | + KILE_DEBUG() << "startDir is " << startDir; |
1047 | + |
1048 | + KEncodingFileDialog::Result result; |
1049 | + KUrl saveURL; |
1050 | + while(true) { |
1051 | + QString filter = info->getFileFilter() + "\n* |" + i18n("All Files"); |
1052 | + result = KEncodingFileDialog::getSaveUrlAndEncoding(doc->encoding(), startDir, filter, m_ki->mainWindow(), i18n("Save File")); |
1053 | + if(result.URLs.isEmpty() || result.URLs.first().isEmpty()) { |
1054 | + return false; |
1055 | + } |
1056 | + saveURL = result.URLs.first(); |
1057 | + if(info->getType() == KileDocument::LaTeX) { |
1058 | + saveURL = Info::makeValidTeXURL(saveURL, m_ki->mainWindow(), |
1059 | + m_ki->extensions()->isTexFile(saveURL), false); // don't check for file existence |
1060 | + } |
1061 | + if(KIO::NetAccess::exists(saveURL, true, m_ki->mainWindow())) { // check for writing possibility |
1062 | + int r = KMessageBox::warningContinueCancel(m_ki->mainWindow(), i18n("A file with the name \"%1\" exists already. Do you want to overwrite it?", saveURL.fileName()), i18n("Overwrite File?"), KGuiItem(i18n("&Overwrite"))); |
1063 | + if(r != KMessageBox::Continue) { |
1064 | + continue; |
1065 | + } |
1066 | + } |
1067 | + break; |
1068 | + } |
1069 | + doc->setEncoding(result.encoding); |
1070 | + if(!doc->saveAs(saveURL)) { |
1071 | + return false; |
1072 | + } |
1073 | + if(oldURL != saveURL) { |
1074 | + if(info->isDocumentTypePromotionAllowed()) { |
1075 | + recreateTextDocumentInfo(info); |
1076 | + info = textInfoFor(doc); |
1077 | + } |
1078 | + m_ki->structureWidget()->updateUrl(info); |
1079 | + emit addToRecentFiles(saveURL); |
1080 | + emit addToProjectView(doc->url()); |
1081 | + } |
1082 | + return true; |
1083 | +} |
1084 | + |
1085 | +void Manager::fileSaveCopyAs() |
1086 | +{ |
1087 | + Locker lock(&m_autoSaveLock); |
1088 | + KTextEditor::Document *doc= m_ki->activeTextDocument(); |
1089 | + KTextEditor::View *view = NULL; |
1090 | + if(doc) { |
1091 | + KileDocument::TextInfo *originalInfo = textInfoFor(doc); |
1092 | + |
1093 | + if(!originalInfo) { |
1094 | + return; |
1095 | + } |
1096 | + |
1097 | + view = createDocumentWithText(doc->text(),originalInfo->getType()); |
1098 | + |
1099 | + KileDocument::TextInfo *newInfo = textInfoFor(view->document()); |
1100 | + |
1101 | + if(originalInfo->url().isEmpty()) { // untitled doc |
1102 | + newInfo->setBaseDirectory(m_ki->fileSelector()->currentUrl().toLocalFile()); |
1103 | + } |
1104 | + else { |
1105 | + newInfo->setBaseDirectory(originalInfo->url().toLocalFile()); |
1106 | + } |
1107 | + |
1108 | + fileSaveAs(view); |
1109 | + |
1110 | + doc = view->document(); |
1111 | + if(doc && !doc->isModified()) { // fileSaveAs was successful |
1112 | + fileClose(doc); |
1113 | + } |
1114 | + } |
1115 | +} |
1116 | + |
1117 | +bool Manager::fileCloseAllOthers(KTextEditor::View *currentView) |
1118 | +{ |
1119 | + Locker lock(&m_autoSaveLock); |
1120 | + QAction *action = m_ki->mainWindow()->action("file_close_all_others"); |
1121 | + // the 'data' property can be set by the view manager |
1122 | + QVariant var = action->data(); |
1123 | + if(!currentView && var.isValid()) { |
1124 | + // the 'data' property for the relevant actions is cleared |
1125 | + // inside the view manager |
1126 | + currentView = var.value<KTextEditor::View*>(); |
1127 | + } |
1128 | + if(!currentView) { |
1129 | + currentView = m_ki->viewManager()->currentTextView(); |
1130 | + } |
1131 | + if(!currentView) { |
1132 | + return false; |
1133 | + } |
1134 | + |
1135 | + QList<KTextEditor::View*> viewList; |
1136 | + for(int i = 0; i < m_ki->viewManager()->textViewCount(); ++i) { |
1137 | + KTextEditor::View *view = m_ki->viewManager()->textView(i); |
1138 | + if(currentView == view) { |
1139 | + continue; |
1140 | + } |
1141 | + viewList.push_back(view); |
1142 | + |
1143 | + } |
1144 | + for(QList<KTextEditor::View*>::iterator it = viewList.begin(); |
1145 | + it != viewList.end(); ++it) { |
1146 | + if (!fileClose(*it)) { |
1147 | + return false; |
1148 | + } |
1149 | + } |
1150 | + return true; |
1151 | +} |
1152 | + |
1153 | +bool Manager::fileCloseAll() |
1154 | +{ |
1155 | + Locker lock(&m_autoSaveLock); |
1156 | + KTextEditor::View * view = m_ki->viewManager()->currentTextView(); |
1157 | + |
1158 | + //assumes one view per doc here |
1159 | + while(m_ki->viewManager()->textViewCount() > 0) { |
1160 | + view = m_ki->viewManager()->textView(0); |
1161 | + if (!fileClose(view->document())) { |
1162 | + return false; |
1163 | + } |
1164 | + } |
1165 | + return true; |
1166 | +} |
1167 | + |
1168 | +bool Manager::fileClose(const KUrl & url) |
1169 | +{ |
1170 | + KTextEditor::Document *doc = docFor(url); |
1171 | + if(!doc) { |
1172 | + return true; |
1173 | + } |
1174 | + else { |
1175 | + return fileClose(doc); |
1176 | + } |
1177 | +} |
1178 | + |
1179 | +bool Manager::fileClose(KTextEditor::View *view) |
1180 | +{ |
1181 | + QAction *action = m_ki->mainWindow()->action("file_close"); |
1182 | + // the 'data' property can be set by the view manager |
1183 | + QVariant var = action->data(); |
1184 | + if(!view && var.isValid()) { |
1185 | + view = var.value<KTextEditor::View*>(); |
1186 | + // the 'data' property for the relevant actions is cleared |
1187 | + // inside the view manager |
1188 | + } |
1189 | + if(!view) { |
1190 | + view = m_ki->viewManager()->currentTextView(); |
1191 | + } |
1192 | + if(!view) { |
1193 | + return false; |
1194 | + } |
1195 | + return fileClose(view->document()); |
1196 | +} |
1197 | + |
1198 | +bool Manager::fileClose(KTextEditor::Document *doc /* = 0L*/, bool closingproject /*= false*/) |
1199 | +{ |
1200 | + KILE_DEBUG() << "==Kile::fileClose=========================="; |
1201 | + |
1202 | + if(!doc) { |
1203 | + doc = m_ki->activeTextDocument(); |
1204 | + } |
1205 | + |
1206 | + if(!doc) { |
1207 | + return true; |
1208 | + } |
1209 | + |
1210 | + Locker lock(&m_autoSaveLock); |
1211 | + |
1212 | + //FIXME: remove from docinfo map, remove from dirwatch |
1213 | + KILE_DEBUG() << "doc->url().toLocalFile()=" << doc->url().toLocalFile(); |
1214 | + |
1215 | + const KUrl url = doc->url(); |
1216 | + |
1217 | + TextInfo *docinfo= textInfoFor(doc); |
1218 | + if(!docinfo) { |
1219 | + kWarning() << "no DOCINFO for " << url.url(); |
1220 | + return true; |
1221 | + } |
1222 | + bool inProject = false; |
1223 | + QList<KileProjectItem*> items = itemsFor(docinfo); |
1224 | + for(QList<KileProjectItem*>::iterator it = items.begin(); it != items.end(); ++it) { |
1225 | + KileProjectItem *item = *it; |
1226 | + |
1227 | + //FIXME: refactor here |
1228 | + if(item && doc) { |
1229 | + storeProjectItem(item, doc); |
1230 | + inProject = true; |
1231 | + } |
1232 | + } |
1233 | + |
1234 | + if(!inProject) { |
1235 | + KILE_DEBUG() << "not in project"; |
1236 | + saveDocumentAndViewSettings(doc); |
1237 | + } |
1238 | + |
1239 | + if(doc->closeUrl()) { |
1240 | + // docinfo may have been recreated from 'Untitled' doc to a named doc |
1241 | + if(url.isEmpty()) { |
1242 | + docinfo= textInfoFor(doc); |
1243 | + } |
1244 | + |
1245 | + if(KileConfig::cleanUpAfterClose()) { |
1246 | + cleanUpTempFiles(url, true); // yes we pass here url and not docinfo->url() |
1247 | + } |
1248 | + |
1249 | + //FIXME: use signal/slot |
1250 | + if( doc->views().count() > 0){ |
1251 | + m_ki->viewManager()->removeView(doc->views().first()); |
1252 | + } |
1253 | + //remove the decorations |
1254 | + |
1255 | + trashDoc(docinfo, doc); |
1256 | + m_ki->structureWidget()->clean(docinfo); |
1257 | + removeTextDocumentInfo(docinfo, closingproject); |
1258 | + |
1259 | + emit removeFromProjectView(url); |
1260 | + emit updateModeStatus(); |
1261 | + } |
1262 | + else { |
1263 | + return false; |
1264 | + } |
1265 | + |
1266 | + return true; |
1267 | +} |
1268 | + |
1269 | +void Manager::buildProjectTree(const KUrl & url) |
1270 | +{ |
1271 | + KileProject * project = projectFor(url); |
1272 | + |
1273 | + if (project) { |
1274 | + buildProjectTree(project); |
1275 | + } |
1276 | +} |
1277 | + |
1278 | +void Manager::buildProjectTree(KileProject *project) |
1279 | +{ |
1280 | + if(!project) { |
1281 | + project = activeProject(); |
1282 | + } |
1283 | + |
1284 | + if(!project) { |
1285 | + project = selectProject(i18n("Refresh Project Tree")); |
1286 | + } |
1287 | + |
1288 | + if (project) { |
1289 | + //TODO: update structure for all docs |
1290 | + project->buildProjectTree(); |
1291 | + } |
1292 | + else if (m_projects.count() == 0) { |
1293 | + KMessageBox::error(m_ki->mainWindow(), i18n("The current document is not associated to a project. Please activate a document that is associated to the project you want to build the tree for, then choose Refresh Project Tree again."),i18n( "Could Not Refresh Project Tree")); |
1294 | + } |
1295 | +} |
1296 | + |
1297 | +void Manager::projectNew() |
1298 | +{ |
1299 | + KileNewProjectDlg *dlg = new KileNewProjectDlg(m_ki->templateManager(), m_ki->extensions(), m_ki->mainWindow()); |
1300 | + |
1301 | + if (dlg->exec()) |
1302 | + { |
1303 | + Locker lock(&m_autoSaveLock); |
1304 | + KileProject *project = dlg->project(); |
1305 | + |
1306 | + //add the project file to the project |
1307 | + KileProjectItem *item = new KileProjectItem(project, project->url()); |
1308 | + item->setOpenState(false); |
1309 | + projectOpenItem(item); |
1310 | + |
1311 | + if(dlg->createNewFile()){ |
1312 | + QString filename = dlg->file(); |
1313 | + |
1314 | + //create the new document and fill it with the template |
1315 | + KTextEditor::View *view = loadTemplate(dlg->getSelection()); |
1316 | + |
1317 | + if(view) { |
1318 | + //derive the URL from the base url of the project |
1319 | + KUrl url = project->baseURL(); |
1320 | + url.addPath(filename); |
1321 | + |
1322 | + TextInfo *docinfo = textInfoFor(view->document()); |
1323 | + |
1324 | + //save the new file |
1325 | + view->document()->saveAs(url); |
1326 | + emit(documentModificationStatusChanged(view->document(), |
1327 | + false, KTextEditor::ModificationInterface::OnDiskUnmodified)); |
1328 | + |
1329 | + //add this file to the project |
1330 | + item = new KileProjectItem(project, url); |
1331 | + //project->add(item); |
1332 | + mapItem(docinfo, item); |
1333 | + |
1334 | + //docinfo->updateStruct(m_kwStructure->level()); |
1335 | + emit(updateStructure(false, docinfo)); |
1336 | + } |
1337 | + } |
1338 | + |
1339 | + project->buildProjectTree(); |
1340 | + //project->save(); |
1341 | + addProject(project); |
1342 | + emit(updateModeStatus()); |
1343 | + emit(addToRecentProjects(project->url())); |
1344 | + } |
1345 | +} |
1346 | + |
1347 | +void Manager::addProject(KileProject *project) |
1348 | +{ |
1349 | + Locker lock(&m_autoSaveLock); |
1350 | + KILE_DEBUG() << "==void Manager::addProject(const KileProject *project)=========="; |
1351 | + m_projects.append(project); |
1352 | + KILE_DEBUG() << "\tnow " << m_projects.count() << " projects"; |
1353 | + emit addToProjectView(project); |
1354 | + connect(project, SIGNAL(projectTreeChanged(const KileProject *)), this, SIGNAL(projectTreeChanged(const KileProject *))); |
1355 | +} |
1356 | + |
1357 | +KileProject* Manager::selectProject(const QString& caption) |
1358 | +{ |
1359 | + QStringList list; |
1360 | + for(QList<KileProject*>::iterator it = m_projects.begin(); it != m_projects.end(); ++it) { |
1361 | + list.append((*it)->name()); |
1362 | + } |
1363 | + |
1364 | + KileProject *project = NULL; |
1365 | + QString name; |
1366 | + if (list.count() > 1) { |
1367 | + KileListSelector *dlg = new KileListSelector(list, caption, i18n("Select Project"), m_ki->mainWindow()); |
1368 | + if (dlg->exec()) |
1369 | + { |
1370 | + name = list[dlg->currentItem()]; |
1371 | + } |
1372 | + delete dlg; |
1373 | + } |
1374 | + else if (list.count() == 0) { |
1375 | + return NULL; |
1376 | + } |
1377 | + else { |
1378 | + name = m_projects.first()->name(); |
1379 | + } |
1380 | + |
1381 | + project = projectFor(name); |
1382 | + |
1383 | + return project; |
1384 | +} |
1385 | + |
1386 | +void Manager::addToProject(const KUrl & url) |
1387 | +{ |
1388 | + Locker lock(&m_autoSaveLock); |
1389 | + KILE_DEBUG() << "===Kile::addToProject(const KUrl & url =" << url.url() << ")"; |
1390 | + |
1391 | + KileProject *project = selectProject(i18n("Add to Project")); |
1392 | + |
1393 | + if (project) { |
1394 | + addToProject(project, url); |
1395 | + } |
1396 | +} |
1397 | + |
1398 | +void Manager::addToProject(KileProject* project, const KUrl & url) |
1399 | +{ |
1400 | + Locker lock(&m_autoSaveLock); |
1401 | + const KUrl realurl = symlinkFreeURL(url); |
1402 | + QFileInfo fi(realurl.toLocalFile()); |
1403 | + |
1404 | + if (project->contains(realurl)) { |
1405 | + m_ki->logWidget()->printMessage(KileTool::Info, |
1406 | + i18n("The file %1 is already member of the project %2", realurl.fileName(), project->name()), |
1407 | + i18n("Add to Project")); |
1408 | + return; |
1409 | + } |
1410 | + else if(!fi.exists() || !fi.isReadable()) |
1411 | + { |
1412 | + m_ki->logWidget()->printMessage(KileTool::Info, |
1413 | + i18n("The file %1 can not be added because it does not exist or is not readable", realurl.fileName()), |
1414 | + i18n("Add to Project")); |
1415 | + return; |
1416 | + } |
1417 | + |
1418 | + KileProjectItem *item = new KileProjectItem(project, realurl); |
1419 | + item->setOpenState(m_ki->isOpen(realurl)); |
1420 | + projectOpenItem(item); |
1421 | + emit addToProjectView(item); |
1422 | + buildProjectTree(project); |
1423 | +} |
1424 | + |
1425 | +void Manager::removeFromProject(KileProjectItem *item) |
1426 | +{ |
1427 | + Locker lock(&m_autoSaveLock); |
1428 | + if (item && item->project()) { |
1429 | + KILE_DEBUG() << "\tprojecturl = " << item->project()->url().toLocalFile() << ", url = " << item->url().toLocalFile(); |
1430 | + |
1431 | + if (item->project()->url() == item->url()) { |
1432 | + KMessageBox::error(m_ki->mainWindow(), i18n("This file is the project file, which holds all the information about your project. As such, it cannot be removed from the project."), i18n("Cannot Remove File From Project")); |
1433 | + return; |
1434 | + } |
1435 | + |
1436 | + emit removeItemFromProjectView(item, m_ki->isOpen(item->url())); |
1437 | + |
1438 | + KileProject *project = item->project(); |
1439 | + project->remove(item); |
1440 | + |
1441 | + // update undefined references in all project files |
1442 | + updateProjectReferences(project); |
1443 | + project->buildProjectTree(); |
1444 | + } |
1445 | +} |
1446 | + |
1447 | +void Manager::projectOpenItem(KileProjectItem *item, bool openProjectItemViews) |
1448 | +{ |
1449 | + Locker lock(&m_autoSaveLock); |
1450 | + KILE_DEBUG() << "==Kile::projectOpenItem=========================="; |
1451 | + KILE_DEBUG() << "\titem:" << item->url().toLocalFile(); |
1452 | + |
1453 | + if (m_ki->isOpen(item->url())) { //remove item from projectview (this file was opened before as a normal file) |
1454 | + emit removeFromProjectView(item->url()); |
1455 | + } |
1456 | + |
1457 | + KTextEditor::View *view = loadItem(m_ki->extensions()->determineDocumentType(item->url()), item, QString(), openProjectItemViews); |
1458 | + if(item->getInfo()) { // make sure that the item has been parsed, even if it isn't shown |
1459 | + // this is necessary to identify the correct LaTeX root document (bug 233667) |
1460 | + m_ki->structureWidget()->update(item->getInfo()); |
1461 | + } |
1462 | + |
1463 | + if((!item->isOpen()) && !view && item->getInfo()) { //doc shouldn't be displayed, trash the doc |
1464 | + trashDoc(item->getInfo()); |
1465 | + } |
1466 | + else if(view) { |
1467 | + view->setCursorPosition(KTextEditor::Cursor(item->lineNumber(), item->columnNumber())); |
1468 | + item->loadDocumentAndViewSettings(); |
1469 | + } |
1470 | + |
1471 | + //oops, doc apparently was open while the project settings wants it closed, don't trash it the doc, update openstate instead |
1472 | + if ((!item->isOpen()) && view) { |
1473 | + item->setOpenState(true); |
1474 | + } |
1475 | +} |
1476 | + |
1477 | +KileProject* Manager::projectOpen(const KUrl & url, int step, int max, bool openProjectItemViews) |
1478 | +{ |
1479 | + Locker lock(&m_autoSaveLock); |
1480 | + KILE_DEBUG() << "==Kile::projectOpen=========================="; |
1481 | + KILE_DEBUG() << "\tfilename: " << url.fileName(); |
1482 | + |
1483 | + const KUrl realurl = symlinkFreeURL(url); |
1484 | + |
1485 | + if(m_ki->projectIsOpen(realurl)) { |
1486 | + if(m_progressDialog) { |
1487 | + m_progressDialog->hide(); |
1488 | + } |
1489 | + |
1490 | + KMessageBox::information(m_ki->mainWindow(), i18n("The project you tried to open is already opened. If you wanted to reload the project, close the project before you re-open it."),i18n("Project Already Open")); |
1491 | + return NULL; |
1492 | + } |
1493 | + |
1494 | + QFileInfo fi(realurl.toLocalFile()); |
1495 | + if(!fi.isReadable()) { |
1496 | + if(m_progressDialog) { |
1497 | + m_progressDialog->hide(); |
1498 | + } |
1499 | + |
1500 | + if (KMessageBox::warningYesNo(m_ki->mainWindow(), i18n("The project file for the project \"%1\" does not exist or is not readable. Remove this project from the recent projects list?", url.prettyUrl()), i18n("Could Not Load Project File")) == KMessageBox::Yes) { |
1501 | + emit(removeFromRecentProjects(realurl)); |
1502 | + } |
1503 | + return NULL; |
1504 | + } |
1505 | + |
1506 | + if(!m_progressDialog) { |
1507 | + createProgressDialog(); |
1508 | + } |
1509 | + |
1510 | + m_progressDialog->show(); |
1511 | + |
1512 | + KileProject *kp = new KileProject(realurl,m_ki->extensions()); |
1513 | + |
1514 | + if(kp->isInvalid()) { |
1515 | + if(m_progressDialog) { |
1516 | + m_progressDialog->hide(); |
1517 | + } |
1518 | + delete kp; |
1519 | + return NULL; |
1520 | + } |
1521 | + |
1522 | + emit(addToRecentProjects(realurl)); |
1523 | + |
1524 | + QList<KileProjectItem*> list = kp->items(); |
1525 | + |
1526 | + int project_steps = list.count() + 1; |
1527 | + m_progressDialog->progressBar()->setMaximum(project_steps * max); |
1528 | + project_steps *= step; |
1529 | + m_progressDialog->progressBar()->setValue(project_steps); |
1530 | + |
1531 | + // open the project files in the correct order |
1532 | + QVector<KileProjectItem*> givenPositionVector(list.count(), NULL); |
1533 | + QList<KileProjectItem*> notCorrectlyOrderedList; |
1534 | + for(QList<KileProjectItem*>::iterator it = list.begin(); it != list.end(); ++it) { |
1535 | + KileProjectItem *item = *it; |
1536 | + int order = item->order(); |
1537 | + |
1538 | + if(order >= 0 && order >= list.count()) { |
1539 | + order = -1; |
1540 | + } |
1541 | + if(!item->isOpen() || order < 0 || givenPositionVector[order] != NULL) { |
1542 | + notCorrectlyOrderedList.push_back(item); |
1543 | + } |
1544 | + else { |
1545 | + givenPositionVector[order] = item; |
1546 | + } |
1547 | + } |
1548 | + |
1549 | + QList<KileProjectItem*> orderedList; |
1550 | + for(int i = 0; i < givenPositionVector.size(); ++i) { |
1551 | + KileProjectItem *item = givenPositionVector[i]; |
1552 | + if(item) { |
1553 | + orderedList.push_back(item); |
1554 | + } |
1555 | + } |
1556 | + for(QList<KileProjectItem*>::iterator i = notCorrectlyOrderedList.begin(); i != notCorrectlyOrderedList.end(); ++i) { |
1557 | + orderedList.push_back(*i); |
1558 | + } |
1559 | + |
1560 | + unsigned int counter = 0; |
1561 | + for (QList<KileProjectItem*>::iterator i = orderedList.begin(); i != orderedList.end(); ++i) { |
1562 | + projectOpenItem(*i, openProjectItemViews); |
1563 | + m_progressDialog->progressBar()->setValue(counter + project_steps); |
1564 | + kapp->processEvents(); |
1565 | + ++counter; |
1566 | + } |
1567 | + |
1568 | + kp->buildProjectTree(); |
1569 | + addProject(kp); |
1570 | + |
1571 | + emit(updateStructure(false, NULL)); |
1572 | + emit(updateModeStatus()); |
1573 | + // update undefined references in all project files |
1574 | + updateProjectReferences(kp); |
1575 | + |
1576 | + if (step == (max - 1)) { |
1577 | + m_progressDialog->hide(); |
1578 | + } |
1579 | + |
1580 | + m_ki->viewManager()->switchToTextView(kp->lastDocument()); |
1581 | + |
1582 | + return kp; |
1583 | +} |
1584 | + |
1585 | +// as all labels are gathered in the project, we can check for unsolved references |
1586 | +void Manager::updateProjectReferences(KileProject *project) |
1587 | +{ |
1588 | + QList<KileProjectItem*> list = project->items(); |
1589 | + for(QList<KileProjectItem*>::iterator it = list.begin(); it != list.end(); ++it) { |
1590 | + emit(updateReferences((*it)->getInfo())); |
1591 | + } |
1592 | +} |
1593 | + |
1594 | +KileProject* Manager::projectOpen() |
1595 | +{ |
1596 | + KILE_DEBUG() << "==Kile::projectOpen=========================="; |
1597 | + KUrl url = KFileDialog::getOpenUrl( KileConfig::defaultProjectLocation(), i18n("*.kilepr|Kile Project Files\n*|All Files"), m_ki->mainWindow(), i18n("Open Project") ); |
1598 | + |
1599 | + if(!url.isEmpty()) { |
1600 | + return projectOpen(url); |
1601 | + } |
1602 | + else { |
1603 | + return NULL; |
1604 | + } |
1605 | +} |
1606 | + |
1607 | + |
1608 | +void Manager::projectSave(KileProject *project /* = 0 */) |
1609 | +{ |
1610 | + Locker lock(&m_autoSaveLock); |
1611 | + KILE_DEBUG() << "==Kile::projectSave=========================="; |
1612 | + if (!project) { |
1613 | + //find the project that corresponds to the active doc |
1614 | + project= activeProject(); |
1615 | + } |
1616 | + |
1617 | + if(!project) { |
1618 | + project = selectProject(i18n("Save Project")); |
1619 | + } |
1620 | + |
1621 | + if(project) { |
1622 | + QList<KileProjectItem*> list = project->items(); |
1623 | + KTextEditor::Document *doc = NULL; |
1624 | + KileProjectItem *item = NULL; |
1625 | + TextInfo *docinfo = NULL; |
1626 | + |
1627 | + // determine the order in which the project items are opened |
1628 | + QVector<KileProjectItem*> viewPositionVector(m_ki->viewManager()->getTabCount(), NULL); |
1629 | + for(QList<KileProjectItem*>::iterator i = list.begin(); i != list.end(); ++i) { |
1630 | + docinfo = (*i)->getInfo(); |
1631 | + if(docinfo) { |
1632 | + KTextEditor::View *view = m_ki->viewManager()->textView(docinfo); |
1633 | + if(view) { |
1634 | + int position = m_ki->viewManager()->getIndexOf(view); |
1635 | + if(position >= 0 && position < viewPositionVector.size()) { |
1636 | + viewPositionVector[position] = *i; |
1637 | + } |
1638 | + } |
1639 | + } |
1640 | + } |
1641 | + int position = 0; |
1642 | + for(int i = 0; i < viewPositionVector.size(); ++i) { |
1643 | + if(viewPositionVector[i] != NULL) { |
1644 | + viewPositionVector[i]->setOrder(position); |
1645 | + ++position; |
1646 | + } |
1647 | + } |
1648 | + |
1649 | + //update the open-state of the items |
1650 | + for (QList<KileProjectItem*>::iterator i = list.begin(); i != list.end(); ++i) { |
1651 | + item = *i; |
1652 | + KILE_DEBUG() << "\tsetOpenState(" << (*i)->url().toLocalFile() << ") to " << m_ki->isOpen(item->url()); |
1653 | + item->setOpenState(m_ki->isOpen(item->url())); |
1654 | + docinfo = item->getInfo(); |
1655 | + |
1656 | + if(docinfo) { |
1657 | + doc = docinfo->getDoc(); |
1658 | + } |
1659 | + if(doc) { |
1660 | + storeProjectItem(item, doc); |
1661 | + } |
1662 | + |
1663 | + doc = NULL; |
1664 | + docinfo = NULL; |
1665 | + } |
1666 | + |
1667 | + project->save(); |
1668 | + } |
1669 | + else { |
1670 | + KMessageBox::error(m_ki->mainWindow(), i18n("The current document is not associated to a project. Please activate a document that is associated to the project you want to save, then choose Save Project again."),i18n( "Could Determine Active Project")); |
1671 | + } |
1672 | +} |
1673 | + |
1674 | +void Manager::projectAddFiles(const KUrl & url) |
1675 | +{ |
1676 | + Locker lock(&m_autoSaveLock); |
1677 | + KileProject *project = projectFor(url); |
1678 | + |
1679 | + if (project) { |
1680 | + projectAddFiles(project,url); |
1681 | + } |
1682 | +} |
1683 | + |
1684 | +void Manager::projectAddFiles(KileProject *project,const KUrl & fileUrl) |
1685 | +{ |
1686 | + Locker lock(&m_autoSaveLock); |
1687 | + KILE_DEBUG() << "==Kile::projectAddFiles()=========================="; |
1688 | + if(project == 0) { |
1689 | + project = activeProject(); |
1690 | + } |
1691 | + |
1692 | + if(project == 0) { |
1693 | + project = selectProject(i18n("Add Files to Project")); |
1694 | + } |
1695 | + |
1696 | + if (project) { |
1697 | + QString currentDir; |
1698 | + if(fileUrl.isEmpty()) |
1699 | + currentDir=project->url().directory(); |
1700 | + else |
1701 | + currentDir=fileUrl.directory(); |
1702 | + |
1703 | + KILE_DEBUG() << "currentDir is " << currentDir; |
1704 | + KFileDialog *dlg = new KFileDialog(currentDir, i18n("*|All Files"), m_ki->mainWindow()); |
1705 | + dlg->setModal(true); |
1706 | + KPushButton* okButton = dlg->okButton(); |
1707 | + okButton->setText(i18n("Add")); |
1708 | + dlg->setCaption(i18n("Add Files")); |
1709 | + dlg->setMode(KFile::Files | KFile::ExistingOnly); |
1710 | + |
1711 | + if(dlg->exec()) { |
1712 | + KUrl::List urls = dlg->selectedUrls(); |
1713 | + for(int i=0; i < urls.count(); ++i) { |
1714 | + addToProject(project, urls[i]); |
1715 | + } |
1716 | + // update undefined references in all project files |
1717 | + updateProjectReferences(project); |
1718 | + } |
1719 | + delete dlg; |
1720 | + |
1721 | + //open them |
1722 | + } |
1723 | + else if (m_projects.count() == 0) { |
1724 | + KMessageBox::error(m_ki->mainWindow(), i18n("There are no projects opened. Please open the project you want to add files to, then choose Add Files again."),i18n( "Could Not Determine Active Project")); |
1725 | + } |
1726 | +} |
1727 | + |
1728 | +void Manager::toggleArchive(KileProjectItem *item) |
1729 | +{ |
1730 | + item->setArchive(!item->archive()); |
1731 | +} |
1732 | + |
1733 | +void Manager::projectOptions(const KUrl & url) |
1734 | +{ |
1735 | + KileProject *project = projectFor(url); |
1736 | + |
1737 | + if (project) { |
1738 | + projectOptions(project); |
1739 | + } |
1740 | +} |
1741 | + |
1742 | +void Manager::projectOptions(KileProject *project /* = 0*/) |
1743 | +{ |
1744 | + KILE_DEBUG() << "==Kile::projectOptions=========================="; |
1745 | + if(!project) { |
1746 | + project = activeProject(); |
1747 | + } |
1748 | + |
1749 | + if(!project) { |
1750 | + project = selectProject(i18n("Project Options For")); |
1751 | + } |
1752 | + |
1753 | + if (project) { |
1754 | + KILE_DEBUG() << "\t" << project->name(); |
1755 | + KileProjectOptionsDlg *dlg = new KileProjectOptionsDlg(project, m_ki->extensions(), m_ki->mainWindow()); |
1756 | + dlg->exec(); |
1757 | + } |
1758 | + else if (m_projects.count() == 0) { |
1759 | + KMessageBox::error(m_ki->mainWindow(), i18n("The current document is not associated to a project. Please activate a document that is associated to the project you want to modify, then choose Project Options again."),i18n( "Could Not Determine Active Project")); |
1760 | + } |
1761 | +} |
1762 | + |
1763 | +bool Manager::projectCloseAll() |
1764 | +{ |
1765 | + Locker lock(&m_autoSaveLock); |
1766 | + KILE_DEBUG() << "==Kile::projectCloseAll=========================="; |
1767 | + |
1768 | + for(QList<KileProject*>::iterator it = m_projects.begin(); it != m_projects.end(); ++it) { |
1769 | + if(!projectClose((*it)->url())) { |
1770 | + return false; |
1771 | + } |
1772 | + } |
1773 | + |
1774 | + return true; |
1775 | +} |
1776 | + |
1777 | +bool Manager::projectClose(const KUrl & url) |
1778 | +{ |
1779 | + Locker lock(&m_autoSaveLock); |
1780 | + KILE_DEBUG() << "==Kile::projectClose=========================="; |
1781 | + KileProject *project = 0; |
1782 | + |
1783 | + if (url.isEmpty()) { |
1784 | + project = activeProject(); |
1785 | + |
1786 | + if (!project) { |
1787 | + project = selectProject(i18n("Close Project")); |
1788 | + } |
1789 | + } |
1790 | + else { |
1791 | + project = projectFor(url); |
1792 | + } |
1793 | + |
1794 | + if(project) { |
1795 | + KILE_DEBUG() << "\tclosing:" << project->name(); |
1796 | + project->setLastDocument(m_ki->getName()); |
1797 | + |
1798 | + projectSave(project); |
1799 | + |
1800 | + QList<KileProjectItem*> list = project->items(); |
1801 | + |
1802 | + bool close = true; |
1803 | + KTextEditor::Document *doc = NULL; |
1804 | + TextInfo *docinfo = NULL; |
1805 | + for(QList<KileProjectItem*>::iterator it = list.begin(); it != list.end(); ++it) { |
1806 | + KileProjectItem *item = *it; |
1807 | + |
1808 | + doc = NULL; |
1809 | + docinfo = item->getInfo(); |
1810 | + if (docinfo) { |
1811 | + doc = docinfo->getDoc(); |
1812 | + } |
1813 | + else { |
1814 | + continue; |
1815 | + } |
1816 | + if (doc) { |
1817 | + KILE_DEBUG() << "\t\tclosing item " << doc->url().toLocalFile(); |
1818 | + bool r = fileClose(doc, true); |
1819 | + close = close && r; |
1820 | + if (!close) { |
1821 | + break; |
1822 | + } |
1823 | + } |
1824 | + else { |
1825 | + // we still need to delete the TextInfo object |
1826 | + removeTextDocumentInfo(docinfo, true); |
1827 | + } |
1828 | + } |
1829 | + |
1830 | + if (close) { |
1831 | + m_projects.removeAll(project); |
1832 | + emit removeFromProjectView(project); |
1833 | + delete project; |
1834 | + emit(updateModeStatus()); |
1835 | + return true; |
1836 | + } |
1837 | + else |
1838 | + return false; |
1839 | + } |
1840 | + else if (m_projects.count() == 0) |
1841 | + KMessageBox::error(m_ki->mainWindow(), i18n("The current document is not associated to a project. Please activate a document that is associated to the project you want to close, then choose Close Project again."),i18n( "Could Not Close Project")); |
1842 | + |
1843 | + return true; |
1844 | +} |
1845 | + |
1846 | +void Manager::storeProjectItem(KileProjectItem *item, KTextEditor::Document *doc) |
1847 | +{ |
1848 | + Locker lock(&m_autoSaveLock); |
1849 | + KILE_DEBUG() << "===Kile::storeProjectItem=============="; |
1850 | + KILE_DEBUG() << "\titem = " << item << ", doc = " << doc; |
1851 | + item->setEncoding(doc->encoding()); |
1852 | + item->setMode(doc->mode()); |
1853 | + item->setHighlight(doc->highlightingMode()); |
1854 | + uint l = 0, c = 0; |
1855 | + QList<KTextEditor::View*> viewList = doc->views(); |
1856 | + if(viewList.size() > 0) { |
1857 | + KTextEditor::View *view = static_cast<KTextEditor::View*>(viewList.first()); |
1858 | + |
1859 | + if (view) { |
1860 | + KTextEditor::Cursor cursor = view->cursorPosition(); |
1861 | + l = cursor.line(); |
1862 | + c = cursor.column(); |
1863 | + } |
1864 | + } |
1865 | + item->setLineNumber(l); |
1866 | + item->setColumnNumber(c); |
1867 | + item->saveDocumentAndViewSettings(); |
1868 | +} |
1869 | + |
1870 | +void Manager::cleanUpTempFiles(const KUrl &url, bool silent) |
1871 | +{ |
1872 | + Locker lock(&m_autoSaveLock); |
1873 | + KILE_DEBUG() << "===void Manager::cleanUpTempFiles(const KUrl " << url.toLocalFile() << ", bool " << silent << ")==="; |
1874 | + |
1875 | + if( url.isEmpty() ) |
1876 | + return; |
1877 | + |
1878 | + QStringList extlist; |
1879 | + QFileInfo fi(url.toLocalFile()); |
1880 | + const QStringList templist = KileConfig::cleanUpFileExtensions().split(' '); |
1881 | + const QString fileName = fi.fileName(); |
1882 | + const QString dirPath = fi.absolutePath(); |
1883 | + const QString baseName = fi.completeBaseName(); |
1884 | + |
1885 | + for (int i = 0; i < templist.count(); ++i) { |
1886 | + fi.setFile( dirPath + '/' + baseName + templist[i] ); |
1887 | + if(fi.exists()) { |
1888 | + extlist.append(templist[i]); |
1889 | + } |
1890 | + } |
1891 | + |
1892 | + if(!silent && fileName.isEmpty()) { |
1893 | + return; |
1894 | + } |
1895 | + |
1896 | + if (!silent && extlist.count() > 0) { |
1897 | + KILE_DEBUG() << "not silent"; |
1898 | + KileDialog::Clean *dialog = new KileDialog::Clean(m_ki->mainWindow(), fileName, extlist); |
1899 | + if(dialog->exec()) { |
1900 | + extlist = dialog->getCleanlist(); |
1901 | + } |
1902 | + else { |
1903 | + delete dialog; |
1904 | + return; |
1905 | + } |
1906 | + |
1907 | + delete dialog; |
1908 | + } |
1909 | + |
1910 | + if(extlist.count() == 0) { |
1911 | + m_ki->logWidget()->printMessage(KileTool::Warning, i18n("Nothing to clean for %1", fileName), |
1912 | + i18n("Clean")); |
1913 | + } |
1914 | + else { |
1915 | + for(int i = 0; i < extlist.count(); ++i) { |
1916 | + QFile file(dirPath + '/' + baseName + extlist[i]); |
1917 | + KILE_DEBUG() << "About to remove file = " << file.fileName(); |
1918 | + file.remove(); |
1919 | + } |
1920 | + m_ki->logWidget()->printMessage(KileTool::Info, |
1921 | + i18n("Cleaning %1: %2", fileName, extlist.join(" ")), |
1922 | + i18n("Clean")); |
1923 | + } |
1924 | +} |
1925 | + |
1926 | +void Manager::openDroppedURLs(QDropEvent *e) { |
1927 | + Locker lock(&m_autoSaveLock); |
1928 | + KUrl::List urls = KUrl::List::fromMimeData(e->mimeData()); |
1929 | + Extensions *extensions = m_ki->extensions(); |
1930 | + |
1931 | + for(KUrl::List::iterator i = urls.begin(); i != urls.end(); ++i) { |
1932 | + KUrl url = *i; |
1933 | + if(extensions->isProjectFile(url)) { |
1934 | + projectOpen(url); |
1935 | + } |
1936 | + else { |
1937 | + fileOpen(url); |
1938 | + } |
1939 | + } |
1940 | +} |
1941 | + |
1942 | +void Manager::reloadXMLOnAllDocumentsAndViews() |
1943 | +{ |
1944 | + for(QList<TextInfo*>::iterator it = m_textInfoList.begin(); it != m_textInfoList.end(); ++it) { |
1945 | + KTextEditor::Document *doc = (*it)->getDoc(); |
1946 | + // FIXME: 'doc' can be null, for example if it belongs to a project item |
1947 | + // which has been closed, but this should be improved in the sense |
1948 | + // that 'm_textInfoList' should only contain 'TextInfo' objects which |
1949 | + // contain valid pointers to 'KTextEditor::Document' objects. |
1950 | + if(!doc) { |
1951 | + continue; |
1952 | + } |
1953 | + doc->reloadXML(); |
1954 | + QList<KTextEditor::View*> views = doc->views(); |
1955 | + for(QList<KTextEditor::View*>::iterator viewIt = views.begin(); viewIt != views.end(); ++viewIt) { |
1956 | + (*viewIt)->reloadXML(); |
1957 | + } |
1958 | + } |
1959 | +} |
1960 | + |
1961 | +// Show all opened projects and switch to another one, if you want |
1962 | + |
1963 | +void Manager::projectShow() |
1964 | +{ |
1965 | + Locker lock(&m_autoSaveLock); |
1966 | + if(m_projects.count() <= 1) { |
1967 | + return; |
1968 | + } |
1969 | + |
1970 | + // select the new project |
1971 | + KileProject *project = selectProject(i18n("Switch Project")); |
1972 | + if(!project || project==activeProject()) { |
1973 | + return; |
1974 | + } |
1975 | + |
1976 | + // get last opened document |
1977 | + const KUrl lastdoc = project->lastDocument(); |
1978 | + KileProjectItem *docitem = (!lastdoc.isEmpty()) ? itemFor(lastdoc, project) : NULL; |
1979 | + |
1980 | + // if not, we search for the first opened tex file of this project |
1981 | + // if no file is opened, we take the first tex file mentioned in the list |
1982 | + KileProjectItem *first_texitem = NULL; |
1983 | + if(!docitem) { |
1984 | + QList<KileProjectItem*> list = project->items(); |
1985 | + for(QList<KileProjectItem*>::iterator it = list.begin(); it != list.end(); ++it) { |
1986 | + KileProjectItem *item = *it; |
1987 | + |
1988 | + QString itempath = item->path(); |
1989 | + |
1990 | + // called from KAction 'Show projects...': find the first opened |
1991 | + // LaTeX document or, if that fails, any other opened file |
1992 | + QStringList extlist = (m_ki->extensions()->latexDocuments() + ' ' + m_ki->extensions()->latexPackages()).split(' '); |
1993 | + for(QStringList::Iterator it=extlist.begin(); it!=extlist.end(); ++it) { |
1994 | + if(itempath.indexOf( (*it), -(*it).length() ) >= 0) { |
1995 | + if (m_ki->isOpen(item->url())) { |
1996 | + docitem = item; |
1997 | + break; |
1998 | + } |
1999 | + else if(!first_texitem) { |
2000 | + first_texitem = item; |
2001 | + } |
2002 | + } |
2003 | + } |
2004 | + if(docitem) { |
2005 | + break; |
2006 | + } |
2007 | + } |
2008 | + } |
2009 | + |
2010 | + // did we find one opened file or must we take the first entry |
2011 | + if(!docitem) { |
2012 | + if(!first_texitem) { |
2013 | + return; |
2014 | + } |
2015 | + docitem = first_texitem; |
2016 | + } |
2017 | + |
2018 | + // ok, we can switch to another project now |
2019 | + if (m_ki->isOpen(docitem->url())) { |
2020 | + m_ki->viewManager()->switchToTextView(docitem->url()); |
2021 | + } |
2022 | + else { |
2023 | + fileOpen(docitem->url(), docitem->encoding()); |
2024 | + } |
2025 | +} |
2026 | + |
2027 | +void Manager::projectRemoveFiles() |
2028 | +{ |
2029 | + Locker lock(&m_autoSaveLock); |
2030 | + QList<KileProjectItem*> itemsList = selectProjectFileItems(i18n("Select Files to Remove")); |
2031 | + if(itemsList.count() > 0) { |
2032 | + for(QList<KileProjectItem*>::iterator it = itemsList.begin(); it != itemsList.end(); ++it) { |
2033 | + removeFromProject(*it); |
2034 | + } |
2035 | + } |
2036 | +} |
2037 | + |
2038 | +void Manager::projectShowFiles() |
2039 | +{ |
2040 | + Locker lock(&m_autoSaveLock); |
2041 | + KileProjectItem *item = selectProjectFileItem( i18n("Select File") ); |
2042 | + if(item) { |
2043 | + if (item->type() == KileProjectItem::ProjectFile) { |
2044 | + dontOpenWarning(item, i18n("Show Project Files"), i18n("project configuration file")); |
2045 | + } |
2046 | + else if(item->type() == KileProjectItem::Image) { |
2047 | + dontOpenWarning(item, i18n("Show Project Files"), i18n("graphics file")); |
2048 | + } |
2049 | + else { // ok, we can switch to another file |
2050 | + if (m_ki->isOpen(item->url())) { |
2051 | + m_ki->viewManager()->switchToTextView(item->url()); |
2052 | + } |
2053 | + else { |
2054 | + fileOpen(item->url(), item->encoding() ); |
2055 | + } |
2056 | + } |
2057 | + } |
2058 | +} |
2059 | + |
2060 | +void Manager::projectOpenAllFiles() |
2061 | +{ |
2062 | + Locker lock(&m_autoSaveLock); |
2063 | + KileProject *project = selectProject(i18n("Select Project")); |
2064 | + if(project) { |
2065 | + projectOpenAllFiles(project->url()); |
2066 | + } |
2067 | +} |
2068 | + |
2069 | +void Manager::projectOpenAllFiles(const KUrl & url) |
2070 | +{ |
2071 | + Locker lock(&m_autoSaveLock); |
2072 | + KileProject* project; |
2073 | + KTextEditor::Document* doc = NULL; |
2074 | + |
2075 | + if(!url.isValid()) { |
2076 | + return; |
2077 | + } |
2078 | + project = projectFor(url); |
2079 | + |
2080 | + if(!project) |
2081 | + return; |
2082 | + |
2083 | + |
2084 | + if(m_ki->viewManager()->currentTextView()) { |
2085 | + doc = m_ki->viewManager()->currentTextView()->document(); |
2086 | + } |
2087 | + // we remember the actual view, so the user gets the same view back after opening |
2088 | + |
2089 | + QList<KileProjectItem*> list = project->items(); |
2090 | + for(QList<KileProjectItem*>::iterator it = list.begin(); it != list.end(); ++it) { |
2091 | + KileProjectItem *item = *it; |
2092 | + |
2093 | + if (item->type()==KileProjectItem::ProjectFile) { |
2094 | + dontOpenWarning( item, i18n("Open All Project Files"), i18n("project configuration file") ); |
2095 | + } |
2096 | + else if(item->type()==KileProjectItem::Image) { |
2097 | + dontOpenWarning( item, i18n("Open All Project Files"), i18n("graphics file") ); |
2098 | + } |
2099 | + else if(!m_ki->isOpen(item->url())) { |
2100 | + fileOpen(item->url(), item->encoding()); |
2101 | + } |
2102 | + } |
2103 | + |
2104 | + if(doc) { // we have a doc so switch back to original view |
2105 | + m_ki->viewManager()->switchToTextView(doc->url()); |
2106 | + } |
2107 | +} |
2108 | + |
2109 | +QStringList Manager::getProjectFiles() |
2110 | +{ |
2111 | + QStringList filelist; |
2112 | + |
2113 | + KileProject *project = activeProject(); |
2114 | + if ( project ) |
2115 | + { |
2116 | + QList<KileProjectItem*> list = project->items(); |
2117 | + for(QList<KileProjectItem*>::iterator it = list.begin(); it != list.end(); ++it) { |
2118 | + KileProjectItem *item = *it; |
2119 | + |
2120 | + if(item->type() != KileProjectItem::ProjectFile && item->type() != KileProjectItem::Image) { |
2121 | + filelist << item->url().toLocalFile(); |
2122 | + } |
2123 | + } |
2124 | + } |
2125 | + return filelist; |
2126 | +} |
2127 | + |
2128 | +void Manager::dontOpenWarning(KileProjectItem *item, const QString &action, const QString &filetype) |
2129 | +{ |
2130 | + m_ki->logWidget()->printMessage(KileTool::Info, |
2131 | + i18n("not opened: %1 (%2)", item->url().toLocalFile(), filetype), |
2132 | + action); |
2133 | +} |
2134 | + |
2135 | +KileProjectItem* Manager::selectProjectFileItem(const QString &label) |
2136 | +{ |
2137 | + // select a project |
2138 | + KileProject *project = selectProject(i18n("Select Project")); |
2139 | + if(!project) { |
2140 | + return NULL; |
2141 | + } |
2142 | + |
2143 | + // get a list of files |
2144 | + QStringList filelist; |
2145 | + QMap<QString, KileProjectItem*> map; |
2146 | + QList<KileProjectItem*> list = project->items(); |
2147 | + for(QList<KileProjectItem*>::iterator it = list.begin(); it != list.end(); ++it) { |
2148 | + KileProjectItem *item = *it; |
2149 | + |
2150 | + filelist << item->path(); |
2151 | + map[item->path()] = item; |
2152 | + } |
2153 | + |
2154 | + // select one of these files |
2155 | + KileProjectItem *item = NULL; |
2156 | + KileListSelector *dlg = new KileListSelector(filelist,i18n("Project Files"),label, m_ki->mainWindow()); |
2157 | + if(dlg->exec()) { |
2158 | + if(dlg->currentItem() >= 0) { |
2159 | + QString name = filelist[dlg->currentItem()]; |
2160 | + if(map.contains(name)) { |
2161 | + item = map[name]; |
2162 | + } |
2163 | + else { |
2164 | + KMessageBox::error(m_ki->mainWindow(), i18n("Could not determine the selected file."),i18n( "Project Error")); |
2165 | + } |
2166 | + } |
2167 | + } |
2168 | + delete dlg; |
2169 | + |
2170 | + return item; |
2171 | +} |
2172 | + |
2173 | +QList<KileProjectItem*> Manager::selectProjectFileItems(const QString &label) |
2174 | +{ |
2175 | + KileProject *project = selectProject(i18n("Select Project")); |
2176 | + if(!project) { |
2177 | + return QList<KileProjectItem*>(); |
2178 | + } |
2179 | + |
2180 | + QStringList filelist; |
2181 | + QMap<QString,KileProjectItem *> map; |
2182 | + |
2183 | + QList<KileProjectItem*> list = project->items(); |
2184 | + for(QList<KileProjectItem*>::iterator it = list.begin(); it != list.end(); ++it) { |
2185 | + KileProjectItem *item = *it; |
2186 | + |
2187 | + filelist << item->path(); |
2188 | + map[item->path()] = item; |
2189 | + } |
2190 | + |
2191 | + QList<KileProjectItem*> itemsList; |
2192 | + |
2193 | + KileListSelectorMultiple *dlg = new KileListSelectorMultiple(filelist, i18n("Project Files"), label, m_ki->mainWindow()); |
2194 | + if(dlg->exec()) { |
2195 | + if(dlg->currentItem() >= 0) { |
2196 | + QStringList selectedfiles = dlg->selected(); |
2197 | + for(QStringList::Iterator it = selectedfiles.begin(); it != selectedfiles.end(); ++it ){ |
2198 | + if(map.contains(*it)) { |
2199 | + itemsList.append(map[(*it)]); |
2200 | + } |
2201 | + else { |
2202 | + KMessageBox::error(m_ki->mainWindow(), i18n("Could not determine the selected file."), i18n( "Project Error")); |
2203 | + } |
2204 | + } |
2205 | + } |
2206 | + } |
2207 | + delete dlg; |
2208 | + |
2209 | + return itemsList; |
2210 | +} |
2211 | + |
2212 | +// add a new file to the project |
2213 | +// - only when there is an active project |
2214 | +// - if the file doesn't already belong to it (checked by addToProject) |
2215 | + |
2216 | +void Manager::projectAddFile(QString filename, bool graphics) |
2217 | +{ |
2218 | + Locker lock(&m_autoSaveLock); |
2219 | + KILE_DEBUG() << "===Kile::projectAddFile=============="; |
2220 | + KileProject *project = activeProject(); |
2221 | + if(!project) { |
2222 | + return; |
2223 | + } |
2224 | + |
2225 | + QFileInfo fi(filename); |
2226 | + if(!fi.exists()) { |
2227 | + if(graphics) { |
2228 | + return; |
2229 | + } |
2230 | + |
2231 | + // called from InputDialog after a \input- or \include command: |
2232 | + // - if the chosen file has an extension: accept |
2233 | + // - if not we add the default TeX extension: accept if it exists else reject |
2234 | + QString ext = fi.completeSuffix(); |
2235 | + if ( ! ext.isEmpty() ) |
2236 | + return; |
2237 | + |
2238 | + filename += m_ki->extensions()->latexDocumentDefault(); |
2239 | + if ( QFileInfo(filename).exists() ) |
2240 | + return; |
2241 | + } |
2242 | + |
2243 | + //ok, we have a project and an existing file |
2244 | + KILE_DEBUG() << "\tadd file: " << filename; |
2245 | + m_ki->viewManager()->updateStructure(false); |
2246 | + |
2247 | + KUrl url; |
2248 | + url.setPath(filename); |
2249 | + addToProject(project, url); |
2250 | +} |
2251 | + |
2252 | +const KUrl Manager::symlinkFreeURL(const KUrl& url) |
2253 | +{ |
2254 | +#ifdef Q_WS_WIN |
2255 | + //TODO: maybe actually do something here? Seems unncecessary given Windows' lack of symlinks though... |
2256 | + //Also: the else'd code below fails badly on Windows |
2257 | + return url; |
2258 | +#else |
2259 | + KILE_DEBUG() << "===symlinkFreeURL=="; |
2260 | + |
2261 | + if( !url.isLocalFile() ) |
2262 | + return url; |
2263 | + |
2264 | + QDir dir(url.directory()); |
2265 | + QString filename=url.toLocalFile(); // if the directory does not exist we return the old url (just to be sure) |
2266 | + |
2267 | + if(dir.exists()) |
2268 | + filename= dir.canonicalPath() + '/' + url.fileName(); |
2269 | + else |
2270 | + KILE_DEBUG() << "directory " << url.directory() << "does not exist"; |
2271 | + |
2272 | + return KUrl(filename); |
2273 | +#endif //def Q_WS_WIN |
2274 | +} |
2275 | + |
2276 | +void Manager::cleanupDocumentInfoForProjectItems(KileDocument::Info *info) |
2277 | +{ |
2278 | + QList<KileProjectItem*> itemsList = itemsFor(info); |
2279 | + for(QList<KileProjectItem*>::iterator it = itemsList.begin(); it != itemsList.end(); ++it) { |
2280 | + (*it)->setInfo(NULL); |
2281 | + } |
2282 | +} |
2283 | + |
2284 | +void Manager::createProgressDialog() |
2285 | +{ |
2286 | + m_progressDialog = new KileWidget::ProgressDialog(m_ki->mainWindow(), i18n("Opening Project...")); |
2287 | + m_progressDialog->setModal(true); |
2288 | + m_progressDialog->setAllowCancel(false); |
2289 | + m_progressDialog->setLabelText(i18n("Scanning project files...")); |
2290 | + m_progressDialog->setAutoClose(true); |
2291 | + m_progressDialog->setMinimumDuration(2000); |
2292 | + m_progressDialog->hide(); |
2293 | +} |
2294 | + |
2295 | +void Manager::loadDocumentAndViewSettings(KTextEditor::Document *document) |
2296 | +{ |
2297 | + KConfigGroup configGroup = configGroupForDocumentSettings(document); |
2298 | + if(!configGroup.exists()) { |
2299 | + return; |
2300 | + } |
2301 | +#if KDE_IS_VERSION(4,3,75) |
2302 | + KTextEditor::ParameterizedSessionConfigInterface *interface = qobject_cast<KTextEditor::ParameterizedSessionConfigInterface*>(document); |
2303 | + if(!interface) { |
2304 | + return; |
2305 | + } |
2306 | + interface->readParameterizedSessionConfig(configGroup, KTextEditor::ParameterizedSessionConfigInterface::SkipUrl); |
2307 | + |
2308 | + QList<KTextEditor::View*> viewList = document->views(); |
2309 | + int i = 0; |
2310 | + for(QList<KTextEditor::View*>::iterator it = viewList.begin(); it != viewList.end(); ++it) { |
2311 | + KTextEditor::View *view = *it; |
2312 | + KTextEditor::SessionConfigInterface *viewConfigInterface = qobject_cast<KTextEditor::SessionConfigInterface*>(view); |
2313 | + if(!interface) { |
2314 | + continue; |
2315 | + } |
2316 | + configGroup = configGroupForViewSettings(document, i); |
2317 | + viewConfigInterface->readSessionConfig(configGroup); |
2318 | + ++i; |
2319 | + } |
2320 | +#endif |
2321 | +} |
2322 | + |
2323 | +void Manager::saveDocumentAndViewSettings(KTextEditor::Document *document) |
2324 | +{ |
2325 | + KConfigGroup configGroup = configGroupForDocumentSettings(document); |
2326 | +#if KDE_IS_VERSION(4,3,75) |
2327 | + KUrl url = document->url(); |
2328 | + url.setPassword(""); // we don't want the password to appear in the configuration file |
2329 | + deleteDocumentAndViewSettingsGroups(url); |
2330 | + |
2331 | + KTextEditor::ParameterizedSessionConfigInterface *interface = qobject_cast<KTextEditor::ParameterizedSessionConfigInterface*>(document); |
2332 | + if(!interface) { |
2333 | + return; |
2334 | + } |
2335 | + interface->writeParameterizedSessionConfig(configGroup, KTextEditor::ParameterizedSessionConfigInterface::SkipUrl); |
2336 | + |
2337 | + QList<KTextEditor::View*> viewList = document->views(); |
2338 | + int i = 0; |
2339 | + for(QList<KTextEditor::View*>::iterator it = viewList.begin(); it != viewList.end(); ++it) { |
2340 | + KTextEditor::View *view = *it; |
2341 | + KTextEditor::SessionConfigInterface *viewConfigInterface = qobject_cast<KTextEditor::SessionConfigInterface*>(view); |
2342 | + if(!interface) { |
2343 | + continue; |
2344 | + } |
2345 | + configGroup = configGroupForViewSettings(document, i); |
2346 | + viewConfigInterface->writeSessionConfig(configGroup); |
2347 | + ++i; |
2348 | + } |
2349 | + // finally remove the config groups for the oldest documents that exceed MAX_NUMBER_OF_STORED_SETTINGS |
2350 | + configGroup = KGlobal::config()->group("Session Settings"); |
2351 | + KUrl::List urlList(configGroup.readEntry("Saved Documents", QStringList())); |
2352 | + urlList.removeAll(url); |
2353 | + urlList.push_front(url); |
2354 | + // remove excess elements |
2355 | + if(urlList.length() > MAX_NUMBER_OF_STORED_SETTINGS) { |
2356 | + int excessNumber = urlList.length() - MAX_NUMBER_OF_STORED_SETTINGS; |
2357 | + for(; excessNumber > 0; --excessNumber) { |
2358 | + KUrl url = urlList.takeLast(); |
2359 | + deleteDocumentAndViewSettingsGroups(url); |
2360 | + } |
2361 | + } |
2362 | + configGroup.writeEntry("Documents", url); |
2363 | + configGroup.writeEntry("Saved Documents", urlList.toStringList()); |
2364 | +#endif |
2365 | +} |
2366 | + |
2367 | +KConfigGroup Manager::configGroupForDocumentSettings(KTextEditor::Document *doc) const |
2368 | +{ |
2369 | + return KGlobal::config()->group(configGroupNameForDocumentSettings(doc->url())); |
2370 | +} |
2371 | + |
2372 | +QString Manager::configGroupNameForDocumentSettings(const KUrl& url) const |
2373 | +{ |
2374 | + KUrl url2 = url; |
2375 | + url2.setPassword(""); |
2376 | + return "Document-Settings,URL=" + url2.url(); |
2377 | +} |
2378 | + |
2379 | +KConfigGroup Manager::configGroupForViewSettings(KTextEditor::Document *doc, int viewIndex) const |
2380 | +{ |
2381 | + return KGlobal::config()->group(configGroupNameForViewSettings(doc->url(), viewIndex)); |
2382 | +} |
2383 | + |
2384 | +QString Manager::configGroupNameForViewSettings(const KUrl& url, int viewIndex) const |
2385 | +{ |
2386 | + KUrl url2 = url; |
2387 | + url2.setPassword(""); |
2388 | + return "View-Settings,View=" + QString::number(viewIndex) + ",URL=" + url2.url(); |
2389 | +} |
2390 | + |
2391 | +void Manager::deleteDocumentAndViewSettingsGroups(const KUrl& url) |
2392 | +{ |
2393 | + QString urlString = url.url(); |
2394 | + QStringList groupList = KGlobal::config()->groupList(); |
2395 | + for(QStringList::iterator i = groupList.begin(); i != groupList.end(); ++i) { |
2396 | + QString groupName = *i; |
2397 | + if(groupName.startsWith("Document-Settings") |
2398 | + || groupName.startsWith("View-Settings")) { |
2399 | + int urlIndex = groupName.indexOf("URL="); |
2400 | + if(urlIndex >= 0 && groupName.mid(urlIndex + 4) == urlString) { |
2401 | + KGlobal::config()->deleteGroup(groupName); |
2402 | + } |
2403 | + } |
2404 | + } |
2405 | +} |
2406 | + |
2407 | +} |
2408 | + |
2409 | +#include "kiledocmanager.moc" |
2410 | |
2411 | === modified file 'debian/changelog' |
2412 | --- debian/changelog 2012-04-16 00:46:18 +0000 |
2413 | +++ debian/changelog 2012-08-25 08:51:18 +0000 |
2414 | @@ -1,3 +1,10 @@ |
2415 | +kile (1:2.1.0-1ubuntu3) precise-updates; urgency=low |
2416 | + |
2417 | + * Fixed segfault on close when a project is open (LP: #994498). Patch by |
2418 | + Eugene Shalygin. |
2419 | + |
2420 | + -- Alessandro Menti <alessandro.menti@hotmail.it> Tue, 07 Aug 2012 19:52:40 +0200 |
2421 | + |
2422 | kile (1:2.1.0-1ubuntu2) precise; urgency=low |
2423 | |
2424 | * Add kubuntu_use_utf8.diff to prevent pulling in texlive-latex-extra |
2425 | |
2426 | === added file 'debian/patches/kile-fix-closing-994498.patch' |
2427 | --- debian/patches/kile-fix-closing-994498.patch 1970-01-01 00:00:00 +0000 |
2428 | +++ debian/patches/kile-fix-closing-994498.patch 2012-08-25 08:51:18 +0000 |
2429 | @@ -0,0 +1,31 @@ |
2430 | +Description: Fix crash when closing with a project file open |
2431 | + This patch fixes a segmentation fault that occurs when Kile is closed and |
2432 | + a project file is open (the stack trace shows QUrl::isEmpty at the top of |
2433 | + the stack in one of the threads). The original "iterator" is removed and |
2434 | + replaced by a more reliable access to the m_projects collection. |
2435 | + Upstream patch by Eugene Shalygin. |
2436 | +Author: Alessandro Menti <alessandro.menti@hotmail.it> |
2437 | +Bug-Ubuntu: https://bugs.launchpad.net/bugs/994498 |
2438 | +Origin: upstream, https://bugs.kde.org/attachment.cgi?id=66957 |
2439 | +Bug: https://bugs.kde.org/show_bug.cgi?id=289458 |
2440 | +Forwarded: not-needed |
2441 | + |
2442 | +--- kile-2.1.0.orig/src/kiledocmanager.cpp |
2443 | ++++ kile-2.1.0/src/kiledocmanager.cpp |
2444 | +@@ -1738,11 +1738,11 @@ bool Manager::projectCloseAll() |
2445 | + Locker lock(&m_autoSaveLock); |
2446 | + KILE_DEBUG() << "==Kile::projectCloseAll=========================="; |
2447 | + |
2448 | +- for(QList<KileProject*>::iterator it = m_projects.begin(); it != m_projects.end(); ++it) { |
2449 | +- if(!projectClose((*it)->url())) { |
2450 | +- return false; |
2451 | +- } |
2452 | +- } |
2453 | ++ while (m_projects.size()) { |
2454 | ++ if(!projectClose(m_projects.front()->url())) { |
2455 | ++ return false; |
2456 | ++ } |
2457 | ++ } |
2458 | + |
2459 | + return true; |
2460 | + } |
2461 | |
2462 | === modified file 'debian/patches/series' |
2463 | --- debian/patches/series 2012-04-16 00:46:18 +0000 |
2464 | +++ debian/patches/series 2012-08-25 08:51:18 +0000 |
2465 | @@ -3,3 +3,4 @@ |
2466 | kubuntu_01_improved_viewpart_warning.diff |
2467 | kubuntu_02_disable_embedded_kbibtex.diff |
2468 | kubuntu_use_utf8.diff |
2469 | +kile-fix-closing-994498.patch |
2470 | |
2471 | === modified file 'src/kiledocmanager.cpp' |
2472 | --- src/kiledocmanager.cpp 2011-06-11 14:55:19 +0000 |
2473 | +++ src/kiledocmanager.cpp 2012-08-25 08:51:18 +0000 |
2474 | @@ -1738,11 +1738,11 @@ |
2475 | Locker lock(&m_autoSaveLock); |
2476 | KILE_DEBUG() << "==Kile::projectCloseAll=========================="; |
2477 | |
2478 | - for(QList<KileProject*>::iterator it = m_projects.begin(); it != m_projects.end(); ++it) { |
2479 | - if(!projectClose((*it)->url())) { |
2480 | - return false; |
2481 | - } |
2482 | - } |
2483 | + while (m_projects.size()) { |
2484 | + if(!projectClose(m_projects.front()->url())) { |
2485 | + return false; |
2486 | + } |
2487 | + } |
2488 | |
2489 | return true; |
2490 | } |
I've uploaded a slightly modified version of this merge request to precise-proposed for processing by the SRU team. Thanks!