]> Shamusworld >> Repos - architektonas/blob - src/mainapp/mdiwindow.cpp
GPL compliance check...
[architektonas] / src / mainapp / mdiwindow.cpp
1 // mdiwindow.cpp
2 //
3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // Portions copyright (C) 2001-2003 RibbonSoft
7 // Copyright (C) 2010 Underground Software
8 // See the README and GPLv2 files for licensing and warranty information
9 //
10 // JLH = James L. Hammons <jlhamm@acm.org>
11 //
12 // Who  When        What
13 // ---  ----------  -----------------------------------------------------------
14 // JLH  05/17/2010  Added this text. :-)
15 //
16
17 #include "mdiwindow.h"
18
19 #include "drawing.h"
20 #include "rs_eventhandler.h"
21 #include "exitdialog.h"
22 #include "qg_filedialog.h"
23 #include "qg_graphicview.h"
24
25 // Class variable
26 int MDIWindow::idCounter = 0;
27
28 /**
29  * Constructor.
30  *
31  * @param doc Pointer to an existing document of NULL if a new
32  *   document shall be created for this window.
33  * @param parent Parent widget. Usually a workspace.
34  */
35 MDIWindow::MDIWindow(RS_Document * doc, QWidget * parent, const char * name/*= NULL*/,
36         Qt::WindowFlags wflags/*= Qt::WDestructiveClose*/):
37         QMdiSubWindow(parent, Qt::SubWindow), owner(false), forceClosing(false)
38 #warning "!!! wflags is ignored !!!"
39 {
40 //This warning is most likely coming from the QMdiSubWindow() constructor above...
41 #warning "QWidget::setMinimumSize: (/QMdi::ControlLabel) Negative sizes (-1,-1) are not possible"
42         initDoc(doc);
43         initView();
44         id = idCounter++;
45         parentWindow = NULL;
46
47 //not using this anymore
48 #if 0
49         if (document)
50         {
51                 if (document->getLayerList())
52                         // Link the graphic view to the layer widget
53                         document->getLayerList()->addListener(graphicView);
54
55                 if (document->getBlockList())
56                         // Link the graphic view to the block widget
57                         document->getBlockList()->addListener(graphicView);
58         }
59 #endif
60
61 //hm.
62         setFocus(/*Qt::StrongFocus*/);
63 }
64
65 /**
66  * Destructor.
67  *
68  * Deletes the document associated with this window.
69  */
70 MDIWindow::~MDIWindow()
71 {
72 #if 0
73         if (document->getLayerList())
74                 document->getLayerList()->removeListener(graphicView);
75
76         if (document->getBlockList())
77                 document->getBlockList()->removeListener(graphicView);
78 #endif
79
80         if (owner && document)
81                 delete document;
82
83         document = NULL;
84 }
85
86 /**
87  * Adds another MDI window to the list of known windows that
88  * depend on this one. This can be another view or a view for
89  * a particular block.
90  */
91 void MDIWindow::addChildWindow(MDIWindow * w)
92 {
93     RS_DEBUG->print("RS_MDIWindow::addChildWindow()");
94
95     childWindows.append(w);
96     w->setParentWindow(this);
97
98     RS_DEBUG->print("children: %d", childWindows.count());
99 }
100
101 /**
102  * Removes a child window.
103  *
104  * @see addChildWindow
105  */
106 void MDIWindow::removeChildWindow(MDIWindow * w)
107 {
108     RS_DEBUG->print("RS_MDIWindow::removeChildWindow()");
109
110 //    bool suc = childWindows.remove(w);
111     bool suc = childWindows.removeOne(w);
112     RS_DEBUG->print("successfully removed child window: %d", (int)suc);
113
114     RS_DEBUG->print("children: %d", childWindows.count());
115 }
116
117 /**
118  * @return pointer to the print preview of this drawing or NULL.
119  */
120 MDIWindow * MDIWindow::getPrintPreview()
121 {
122     for(uint i=0; i<childWindows.count(); ++i)
123         {
124         if (childWindows.at(i)->getGraphicView()->isPrintPreview())
125                         return childWindows.at(i);
126     }
127
128         return NULL;
129 }
130
131 /**
132  * closes this MDI window.
133  *
134  * @param force Disable cancel button (demo versions)
135  * @param ask Ask user before closing.
136  */
137 bool MDIWindow::closeMDI(bool force, bool ask)
138 {
139         // should never happen:
140         if (!document)
141                 return true;
142
143         bool ret = false;
144         bool isBlock = (parentWindow != NULL);
145
146         // This is a block and we don't need to ask the user for closing
147         // since it's still available in the parent drawing after closing.
148         if (isBlock)
149         {
150                 RS_DEBUG->print("  closing block");
151                 // tell parent window we're not here anymore.
152                 if (parentWindow)
153                 {
154                         RS_DEBUG->print("    notifying parent about closing this window");
155                         parentWindow->removeChildWindow(this);
156                 }
157
158                 emit(signalClosing());
159                 ret = true;
160         }
161         // This is a graphic document. ask user for closing.
162         else if (!ask || slotFileClose(force))
163         {
164                 RS_DEBUG->print("  closing graphic");
165                 // close all child windows:
166                 bool done;
167
168                 while (!childWindows.isEmpty())
169                 {
170                         MDIWindow * child = childWindows.takeFirst();
171
172                         if (child)
173                                 child->close();
174                 }
175
176                 emit(signalClosing());
177                 ret = true;
178         }
179         // User decided not to close graphic document:
180         else
181         {
182                 ret = false;
183         }
184
185         return (ret || force);
186 }
187
188 /**
189  * Called by Qt when the user closes this MDI window.
190  */
191 void MDIWindow::closeEvent(QCloseEvent * ce)
192 {
193     RS_DEBUG->print("MDIWindow::closeEvent begin");
194
195     if (closeMDI(false, !forceClosing))
196         ce->accept();
197     else
198         ce->ignore();
199
200     RS_DEBUG->print("MDIWindow::closeEvent end");
201 }
202
203 /**
204  * Init the document.
205  *
206  * @param type Document type. RS:EntityGraphic or RS2::EntityBlock
207  * @param container Entity container to be used as document or NULL
208  * if a new document should be created.
209  */
210 void MDIWindow::initDoc(RS_Document * doc)
211 {
212         RS_DEBUG->print("MDIWindow::initDoc()");
213
214         if (!doc)
215         {
216                 document = new Drawing();
217                 document->newDoc();
218                 owner = true;
219         }
220         else
221         {
222                 document = doc;
223                 owner = false;
224         }
225 }
226
227 /**
228  * Init the view.
229  */
230 void MDIWindow::initView()
231 {
232         RS_DEBUG->print("MDIWindow::initView()");
233
234 //      graphicView = new QC_GraphicView(document, this);
235         graphicView = new QG_GraphicView(document, this);
236         setWidget(graphicView);
237         graphicView->setFocus();
238 }
239
240 /**
241  * Called when the current pen (color, style, width) has changed.
242  * Sets the active pen for the document in this MDI window.
243  */
244 void MDIWindow::slotPenChanged(RS_Pen pen)
245 {
246         RS_DEBUG->print("MDIWindow::slotPenChanged() begin");
247
248         if (document)
249                 document->setActivePen(pen);
250
251         RS_DEBUG->print("MDIWindow::slotPenChanged() end");
252 }
253
254 /**
255  * Creates a new empty document in this MDI window.
256  */
257 void MDIWindow::slotFileNew()
258 {
259         RS_DEBUG->print("MDIWindow::slotFileNew begin");
260
261         if (document && graphicView)
262         {
263                 document->newDoc();
264                 graphicView->redraw();
265         }
266
267         RS_DEBUG->print("MDIWindow::slotFileNew end");
268 }
269
270 /**
271  * Opens the given file in this MDI window.
272  */
273 bool MDIWindow::slotFileOpen(const QString & fileName, RS2::FormatType type)
274 {
275         RS_DEBUG->print("MDIWindow::slotFileOpen");
276         bool ret = false;
277
278         if (document != NULL && !fileName.isEmpty())
279         {
280                 document->newDoc();
281                 ret = document->open(fileName, type);
282
283                 if (ret)
284                 {
285                         //QString message=tr("Loaded document: ")+fileName;
286                         //statusBar()->message(message, 2000);
287
288                         RS_DEBUG->print("MDIWindow::slotFileOpen: autoZoom");
289                         graphicView->zoomAuto(false);
290                         RS_DEBUG->print("MDIWindow::slotFileOpen: autoZoom: OK");
291                 }
292                 else
293                 {
294                         RS_DEBUG->print("MDIWindow::slotFileOpen: failed");
295                 }
296         }
297         else
298         {
299                 RS_DEBUG->print("MDIWindow::slotFileOpen: cancelled");
300                 //statusBar()->message(tr("Opening aborted"), 2000);
301         }
302
303         RS_DEBUG->print("MDIWindow::slotFileOpen: OK");
304
305         return ret;
306 }
307
308 /**
309  * Saves the current file.
310  *
311  * @return true if the file was saved successfully.
312  *         false if the file could not be saved or the document
313  *         is invalid.
314  */
315 bool MDIWindow::slotFileSave(bool & cancelled)
316 {
317         RS_DEBUG->print("MDIWindow::slotFileSave()");
318         bool ret = false;
319         cancelled = false;
320
321         if (document)
322         {
323                 if (document->getFilename().isEmpty())
324                         ret = slotFileSaveAs(cancelled);
325                 else
326                 {
327                         QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
328                         ret = document->save();
329                         QApplication::restoreOverrideCursor();
330                 }
331         }
332
333         return ret;
334 }
335
336 /**
337  * Saves the current file. The user is asked for a new filename
338  * and format.
339  *
340  * @return true if the file was saved successfully or the user cancelled.
341  *         false if the file could not be saved or the document
342  *         is invalid.
343  */
344 bool MDIWindow::slotFileSaveAs(bool & cancelled)
345 {
346         RS_DEBUG->print("MDIWindow::slotFileSaveAs");
347         bool ret = false;
348         cancelled = false;
349         RS2::FormatType t = RS2::FormatDXF;
350
351         QString fn = QG_FileDialog::getSaveFileName(this, &t);
352
353         if (document != NULL && !fn.isEmpty())
354         {
355                 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
356                 ret = document->saveAs(fn, t);
357                 QApplication::restoreOverrideCursor();
358         }
359         else
360         {
361                 // cancel is not an error - returns true
362                 ret = true;
363                 cancelled = true;
364         }
365
366         return ret;
367 }
368
369 /**
370  * Requests the closing of this MDI window.
371  *
372  * @param force Force closing by disabling the cancel button (for demo versions).
373  */
374 bool MDIWindow::slotFileClose(bool force)
375 {
376         RS_DEBUG->print("MDIWindow::slotFileClose()");
377
378         bool succ = true;
379         int exit = 0;
380
381         if (document && document->isModified())
382         {
383                 ExitDialog dlg(this);
384                 dlg.setForce(force);
385
386                 if (document->getFilename().isEmpty())
387                         dlg.setText(tr("Do you really want to close the drawing?"));
388                 else
389                 {
390                         QString fn = document->getFilename();
391
392                         if (fn.length() > 50)
393                                 fn = QString("%1...%2").arg(fn.left(24)).arg(fn.right(24));
394
395                         dlg.setText(tr("Do you really want to close the file\n%1?").arg(fn));
396                 }
397
398                 dlg.setTitle(tr("Closing Drawing"));
399
400                 bool again;
401                 bool cancelled;
402
403                 do
404                 {
405                         again = false;
406                         exit = dlg.exec();
407
408                         switch (exit)
409                         {
410                         case 0: // cancel
411                                 succ = false;
412                                 break;
413                         case 1: // leave
414                                 succ = true;
415                                 break;
416                         case 2: // save
417                                 succ = slotFileSave(cancelled);
418                                 again = !succ || cancelled;
419                                 break;
420                         case 3: // save as
421                                 succ = slotFileSaveAs(cancelled);
422                                 again = !succ || cancelled;
423                                 break;
424                         default:
425                                 break;
426                         }
427                 }
428                 while (again);
429         }
430         else
431         {
432                 succ = true;
433         }
434
435         return succ;
436 }
437
438 void MDIWindow::slotFilePrint()
439 {
440         RS_DEBUG->print("MDIWindow::slotFilePrint");
441
442         //statusBar()->message(tr("Printing..."));
443         QPrinter printer;
444
445 //      if (printer.setup(this))
446         QPrintDialog dialog(&printer, this);
447
448         if (dialog.exec())
449         {
450                 QPainter painter;
451                 painter.begin(&printer);
452
453                 ///////////////////////////////////////////////////////////////////
454                 // TODO: Define printing by using the QPainter methods here
455
456                 painter.end();
457         }
458
459         //statusBar()->message(tr("Ready."));
460 }
461
462 /** @return Pointer to graphic view */
463 //QC_GraphicView * MDIWindow::getGraphicView()
464 QG_GraphicView * MDIWindow::getGraphicView()
465 {
466         return graphicView;
467 }
468
469 /** @return Pointer to document */
470 RS_Document * MDIWindow::getDocument()
471 {
472         return document;
473 }
474
475 /** @return Pointer to graphic or NULL */
476 Drawing * MDIWindow::getGraphic()
477 {
478         return document->getGraphic();
479 }
480
481 /** @return Pointer to current event handler */
482 RS_EventHandler * MDIWindow::getEventHandler()
483 {
484         if (graphicView)
485                 return graphicView->getEventHandler();
486         else
487                 return NULL;
488 }
489
490 /**
491  * Sets the parent window that will be notified if this
492  */
493 void MDIWindow::setParentWindow(MDIWindow * p)
494 {
495         RS_DEBUG->print("setParentWindow");
496         parentWindow = p;
497 }
498
499 /**
500  * @return The MDI window id.
501  */
502 int MDIWindow::getId()
503 {
504         return id;
505 }
506
507 void MDIWindow::setForceClosing(bool on)
508 {
509         forceClosing = on;
510 }
511
512 /**
513  * Streams some info about an MDI window to stdout.
514  */
515 std::ostream & operator<<(std::ostream & os, MDIWindow & w)
516 {
517         os << "MDIWindow[" << w.getId() << "]:\n";
518
519         if (w.parentWindow)
520                 os << "  parentWindow: " << w.parentWindow->getId() << "\n";
521         else
522                 os << "  parentWindow: NULL\n";
523
524         for(uint i=0; i<w.childWindows.count(); ++i)
525                 os << "  childWindow[" << i << "]: " << w.childWindows.at(i)->getId() << "\n";
526
527         return os;
528 }