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