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