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