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