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
10 // JLH = James L. Hammons <jlhamm@acm.org>
13 // --- ---------- -----------------------------------------------------------
14 // JLH 05/21/2010 Added this text. :-)
15 // JLH 06/02/2010 Changed all references of this class from RS_Graphic to
16 // Drawing, as that makes it more clear that this is what it
17 // is (a CAD drawing, not a bitmap).
23 #include "rs_fileio.h"
29 * Default constructor.
31 Drawing::Drawing(RS_EntityContainer * parent): RS_Document(parent), layerList(),
37 settings.beginGroup("Defaults");
38 setUnit(RS_Units::stringToUnit(settings.value("Unit", "None").toString()));
41 RS2::Unit unit = getUnit();
43 if (unit == RS2::Inch)
45 addVariable("$DIMASZ", 0.1, 40);
46 addVariable("$DIMEXE", 0.05, 40);
47 addVariable("$DIMEXO", 0.025, 40);
48 addVariable("$DIMGAP", 0.025, 40);
49 addVariable("$DIMTXT", 0.1, 40);
53 addVariable("$DIMASZ", RS_Units::convert(2.5, RS2::Millimeter, unit), 40);
54 addVariable("$DIMEXE", RS_Units::convert(1.25, RS2::Millimeter, unit), 40);
55 addVariable("$DIMEXO", RS_Units::convert(0.625, RS2::Millimeter, unit), 40);
56 addVariable("$DIMGAP", RS_Units::convert(0.625, RS2::Millimeter, unit), 40);
57 addVariable("$DIMTXT", RS_Units::convert(2.5, RS2::Millimeter, unit), 40);
70 /** @return RS2::EntityGraphic */
71 /*virtual*/ RS2::EntityType Drawing::rtti() const
73 return RS2::EntityGraphic;
77 * Counts the entities on the given layer.
79 unsigned long int Drawing::countLayerEntities(RS_Layer * layer)
85 for(RS_Entity * t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone))
87 if (t->getLayer()!=NULL && t->getLayer()->getName()==layer->getName())
97 /*virtual*/ RS_LayerList * Drawing::getLayerList()
102 /*virtual*/ RS_BlockList * Drawing::getBlockList()
108 * Clears all layers, blocks and entities of this graphic.
109 * A default layer (0) is created.
111 void Drawing::newDoc()
113 RS_DEBUG->print("Drawing::newDoc");
120 addLayer(new RS_Layer("0"));
121 //addLayer(new RS_Layer("ByBlock"));
127 * Saves this graphic with the current filename and settings.
133 RS_DEBUG->print("Drawing::save");
134 RS_DEBUG->print(" file: %s", filename.toLatin1().data());
135 RS_DEBUG->print(" format: %d", (int)formatType);
137 RS_DEBUG->print(" export...");
138 ret = RS_FILEIO->fileExport(*this, filename, formatType);
143 layerList.setModified(false);
144 blockList.setModified(false);
147 RS_DEBUG->print("Drawing::save ok");
153 * Saves this graphic with the given filename and current settings.
155 bool Drawing::saveAs(const QString & filename, RS2::FormatType type)
157 RS_DEBUG->print("Drawing::saveAs");
159 this->filename = filename;
160 this->formatType = type;
166 * Loads the given fils into this graphic.
168 bool Drawing::open(const QString &filename, RS2::FormatType type)
170 RS_DEBUG->print("Drawing::open(%s)", filename.toLatin1().data());
174 this->filename = filename;
180 ret = RS_FILEIO->fileImport(*this, filename, type);
183 layerList.setModified(false);
184 blockList.setModified(false);
186 //cout << *((Drawing*)graphic);
187 //calculateBorders();
189 RS_DEBUG->print("Drawing::open(%s): OK", filename.toLatin1().data());
194 // Wrappers for Layer functions:
195 void Drawing::clearLayers()
200 uint Drawing::countLayers() const
202 return layerList.count();
205 RS_Layer * Drawing::layerAt(uint i)
207 return layerList.at(i);
210 void Drawing::activateLayer(const QString & name)
212 layerList.activate(name);
215 void Drawing::activateLayer(RS_Layer * layer)
217 layerList.activate(layer);
220 RS_Layer * Drawing::getActiveLayer()
222 return layerList.getActive();
225 /*virtual*/ void Drawing::addLayer(RS_Layer * layer)
227 layerList.add(layer);
231 * Removes the given layer and undoes all entities on it.
233 /*virtual*/ void Drawing::removeLayer(RS_Layer * layer)
235 if (layer != NULL && layer->getName() != "0")
237 // remove all entities on that layer:
240 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
242 if (e->getLayer() != NULL && e->getLayer()->getName() == layer->getName())
244 e->setUndoState(true);
252 // remove all entities in blocks that are on that layer:
253 for(uint bi=0; bi<blockList.count(); bi++)
255 RS_Block * blk = blockList.at(bi);
259 for(RS_Entity * e=blk->firstEntity(RS2::ResolveNone); e!=NULL; e=blk->nextEntity(RS2::ResolveNone))
261 if (e->getLayer() != NULL && e->getLayer()->getName() == layer->getName())
263 e->setUndoState(true);
271 layerList.remove(layer);
275 /*virtual*/ void Drawing::editLayer(RS_Layer * layer, const RS_Layer & source)
277 layerList.edit(layer, source);
280 RS_Layer * Drawing::findLayer(const QString & name)
282 return layerList.find(name);
285 void Drawing::toggleLayer(const QString & name)
287 layerList.toggle(name);
290 void Drawing::toggleLayer(RS_Layer * layer)
292 layerList.toggle(layer);
295 void Drawing::toggleLayerLock(RS_Layer * layer)
297 layerList.toggleLock(layer);
300 void Drawing::freezeAllLayers(bool freeze)
302 layerList.freezeAll(freeze);
305 void Drawing::addLayerListListener(RS_LayerListListener * listener)
307 layerList.addListener(listener);
310 void Drawing::removeLayerListListener(RS_LayerListListener * listener)
312 layerList.removeListener(listener);
315 // Wrapper for block functions:
317 void Drawing::clearBlocks()
322 uint Drawing::countBlocks()
324 return blockList.count();
327 RS_Block * Drawing::blockAt(uint i)
329 return blockList.at(i);
332 void Drawing::activateBlock(const QString & name)
334 blockList.activate(name);
337 void Drawing::activateBlock(RS_Block * block)
339 blockList.activate(block);
342 RS_Block * Drawing::getActiveBlock()
344 return blockList.getActive();
347 /*virtual*/ bool Drawing::addBlock(RS_Block * block, bool notify/*= true*/)
349 return blockList.add(block, notify);
352 /*virtual*/ void Drawing::addBlockNotification()
354 blockList.addNotification();
357 /*virtual*/ void Drawing::removeBlock(RS_Block * block)
359 blockList.remove(block);
362 RS_Block * Drawing::findBlock(const QString & name)
364 return blockList.find(name);
367 QString Drawing::newBlockName()
369 return blockList.newName();
372 void Drawing::toggleBlock(const QString & name)
374 blockList.toggle(name);
377 void Drawing::toggleBlock(RS_Block * block)
379 blockList.toggle(block);
382 void Drawing::freezeAllBlocks(bool freeze)
384 blockList.freezeAll(freeze);
387 void Drawing::addBlockListListener(RS_BlockListListener * listener)
389 blockList.addListener(listener);
392 void Drawing::removeBlockListListener(RS_BlockListListener * listener)
394 blockList.removeListener(listener);
397 // Wrappers for variable functions:
398 void Drawing::clearVariables()
400 variableDict.clear();
403 int Drawing::countVariables()
405 return variableDict.count();
408 void Drawing::addVariable(const QString & key, const Vector & value, int code)
410 variableDict.add(key, value, code);
413 void Drawing::addVariable(const QString & key, const QString & value, int code)
415 variableDict.add(key, value, code);
418 void Drawing::addVariable(const QString & key, int value, int code)
420 variableDict.add(key, value, code);
423 void Drawing::addVariable(const QString & key, double value, int code)
425 variableDict.add(key, value, code);
428 Vector Drawing::getVariableVector(const QString & key, const Vector & def)
430 return variableDict.getVector(key, def);
433 QString Drawing::getVariableString(const QString & key, const QString & def)
435 return variableDict.getString(key, def);
438 int Drawing::getVariableInt(const QString & key, int def)
440 return variableDict.getInt(key, def);
443 double Drawing::getVariableDouble(const QString & key, double def)
445 return variableDict.getDouble(key, def);
448 void Drawing::removeVariable(const QString & key)
450 variableDict.remove(key);
453 //Q3Dict<RS_Variable> & getVariableDict()
454 QMultiHash<QString, RS_Variable *> & Drawing::getVariableDict()
456 return variableDict.getVariableDict();
460 * @return true if the grid is switched on (visible).
462 bool Drawing::isGridOn()
464 int on = getVariableInt("$GRIDMODE", 1);
469 * Enables / disables the grid.
471 void Drawing::setGridOn(bool on)
473 addVariable("$GRIDMODE", (int)on, 70);
477 * Sets the unit of this graphic to 'u'
479 void Drawing::setUnit(RS2::Unit u)
481 setPaperSize(RS_Units::convert(getPaperSize(), getUnit(), u));
483 addVariable("$INSUNITS", (int)u, 70);
489 * Gets the unit of this graphic
491 RS2::Unit Drawing::getUnit()
493 return (RS2::Unit)getVariableInt("$INSUNITS", 0);
498 * @return The linear format type for this document.
499 * This is determined by the variable "$LUNITS".
501 RS2::LinearFormat Drawing::getLinearFormat()
503 int lunits = getVariableInt("$LUNITS", 2);
513 return RS2::Scientific;
517 return RS2::Engineering;
521 return RS2::Architectural;
525 return RS2::Fractional;
533 * @return The linear precision for this document.
534 * This is determined by the variable "$LUPREC".
536 int Drawing::getLinearPrecision()
538 return getVariableInt("$LUPREC", 4);
542 * @return The angle format type for this document.
543 * This is determined by the variable "$AUNITS".
545 RS2::AngleFormat Drawing::getAngleFormat()
547 int aunits = getVariableInt("$AUNITS", 0);
553 return RS2::DegreesDecimal;
557 return RS2::DegreesMinutesSeconds;
561 return RS2::Gradians;
569 return RS2::Surveyors;
573 return RS2::DegreesDecimal;
577 * @return The linear precision for this document.
578 * This is determined by the variable "$LUPREC".
580 int Drawing::getAnglePrecision()
582 return getVariableInt("$AUPREC", 4);
586 * @return The insertion point of the drawing into the paper space.
587 * This is the distance from the lower left paper edge to the zero
588 * point of the drawing. DXF: $PINSBASE.
590 Vector Drawing::getPaperInsertionBase()
592 return getVariableVector("$PINSBASE", Vector(0.0,0.0));
596 * Sets the PINSBASE variable.
598 void Drawing::setPaperInsertionBase(const Vector & p)
600 addVariable("$PINSBASE", p, 10);
604 * @return Paper size in graphic units.
606 Vector Drawing::getPaperSize()
608 Vector def = RS_Units::convert(Vector(210.0, 297.0), RS2::Millimeter, getUnit());
610 Vector v1 = getVariableVector("$PLIMMIN", Vector(0.0, 0.0));
611 Vector v2 = getVariableVector("$PLIMMAX", def);
617 * Sets a new paper size.
619 void Drawing::setPaperSize(const Vector & s)
621 addVariable("$PLIMMIN", Vector(0.0, 0.0), 10);
622 addVariable("$PLIMMAX", s, 10);
626 * @return Paper format.
627 * This is determined by the variables "$PLIMMIN" and "$PLIMMAX".
629 * @param landscape will be set to true for landscape and false for portrait if not NULL.
631 RS2::PaperFormat Drawing::getPaperFormat(bool * landscape)
633 Vector size = RS_Units::convert(getPaperSize(), getUnit(), RS2::Millimeter);
635 if (landscape != NULL)
636 *landscape = (size.x > size.y);
638 return RS_Units::paperSizeToFormat(size);
642 * Sets the paper format to the given format.
644 void Drawing::setPaperFormat(RS2::PaperFormat f, bool landscape)
646 Vector size = RS_Units::paperFormatToSize(f);
655 if (f != RS2::Custom)
656 setPaperSize(RS_Units::convert(size, RS2::Millimeter, getUnit()));
660 * @return Paper space scaling (DXF: $PSVPSCALE).
662 double Drawing::getPaperScale()
666 ret = getVariableDouble("$PSVPSCALE", 1.0);
675 * Sets a new scale factor for the paper space.
677 void Drawing::setPaperScale(double s)
679 addVariable("$PSVPSCALE", s, 40);
683 * Centers drawing on page. Affects DXF variable $PINSBASE.
685 void Drawing::centerToPage()
687 Vector size = getPaperSize();
688 double scale = getPaperScale();
689 Vector pinsbase = (size - getSize() * scale) / 2.0 - getMin() * scale;
690 setPaperInsertionBase(pinsbase);
694 * Fits drawing on page. Affects DXF variable $PINSBASE.
696 void Drawing::fitToPage()
698 double border = RS_Units::convert(25.0, RS2::Millimeter, getUnit());
699 Vector ps = getPaperSize() - Vector(border, border);
700 Vector s = getSize();
701 double fx = RS_MAXDOUBLE;
702 double fy = RS_MAXDOUBLE;
703 //double factor = 1.0;
705 //ps = RS_Units::convert(ps, getUnit(), RS2::Millimeter);
707 if (fabs(s.x) > 1.0e-6)
710 if (fabs(s.y) > 1.0e-6)
713 setPaperScale(std::min(fx, fy));
718 * @retval true The document has been modified since it was last saved.
719 * @retval false The document has not been modified since it was last saved.
721 /*virtual*/ bool Drawing::isModified() const
723 return modified || layerList.isModified() || blockList.isModified();
727 * Sets the documents modified status to 'm'.
729 /*virtual*/ void Drawing::setModified(bool m)
732 layerList.setModified(m);
733 blockList.setModified(m);
737 RS_CamData & Drawing::getCamData()
742 void Drawing::setCamData(const RS_CamData & d)
749 * Dumps the entities to stdout.
751 std::ostream & operator<<(std::ostream & os, Drawing & g)
753 os << "--- Drawing: \n";
754 os << "---" << *g.getLayerList() << "\n";
755 os << "---" << *g.getBlockList() << "\n";
756 os << "---" << (RS_Undo&)g << "\n";
757 os << "---" << (RS_EntityContainer&)g << "\n";