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