1 /****************************************************************************
2 **
3 ** This file is part of the LibreCAD project, a 2D CAD program
4 **
5 ** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
6 ** Copyright (C) 2011 Rallaz (rallazz@gmail.com)
7 **
8 **
9 ** This file is free software; you can redistribute it and/or modify
10 ** it under the terms of the GNU General Public License as published by
11 ** the Free Software Foundation; either version 2 of the License, or
12 ** (at your option) any later version.
13 **
14 ** This program is distributed in the hope that it will be useful,
15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ** GNU General Public License for more details.
18 **
19 ** You should have received a copy of the GNU General Public License
20 ** along with this program; if not, write to the Free Software
21 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 **
23 ** This copyright notice MUST APPEAR in all copies of the script!
24 **
25 **********************************************************************/
26 
27 #include "doc_plugin_interface.h"
28 #include <QEventLoop>
29 #include <QList>
30 #include <QInputDialog>
31 #include <QFileInfo>
32 #include "rs_graphicview.h"
33 #include "rs_actioninterface.h"
34 #include "rs_eventhandler.h"
35 #include "rs_actionselect.h"
36 #include "rs_arc.h"
37 #include "rs_circle.h"
38 #include "rs_line.h"
39 #include "rs_point.h"
40 #include "rs_mtext.h"
41 #include "rs_text.h"
42 #include "rs_layer.h"
43 #include "rs_image.h"
44 #include "rs_block.h"
45 #include "rs_insert.h"
46 #include "rs_polyline.h"
47 #include "rs_ellipse.h"
48 #include "rs_polyline.h"
49 #include "lc_splinepoints.h"
50 #include "lc_undosection.h"
51 #include "intern/qc_actiongetpoint.h"
52 #include "intern/qc_actiongetselect.h"
53 #include "intern/qc_actiongetent.h"
54 #include "rs_math.h"
55 #include "rs_debug.h"
56 // #include <QDebug>
57 
convLTW()58 convLTW::convLTW(){
59 //    QHash<int, QString> lType;
60     lType.insert(RS2::LineByLayer, "BYLAYER");
61     lType.insert(RS2::LineByBlock, "BYBLOCK");
62     lType.insert(RS2::SolidLine, "SolidLine");
63     lType.insert(RS2::DotLine, "DotLine");
64     lType.insert(RS2::DotLine2, "DotLine2");
65     lType.insert(RS2::DotLineX2, "DotLineX2");
66     lType.insert(RS2::DashLine, "DashLine");
67     lType.insert(RS2::DashLine2, "DashLine2");
68     lType.insert(RS2::DashLineX2, "DashLineX2");
69     lType.insert(RS2::DashDotLine, "DashDotLine");
70     lType.insert(RS2::DashDotLine2, "DashDotLine2");
71     lType.insert(RS2::DashDotLineX2, "DashDotLineX2");
72     lType.insert(RS2::DivideLine, "DivideLine");
73     lType.insert(RS2::DivideLine2, "DivideLine2");
74     lType.insert(RS2::DivideLineX2, "DivideLineX2");
75     lType.insert(RS2::CenterLine, "CenterLine");
76     lType.insert(RS2::CenterLine2, "CenterLine2");
77     lType.insert(RS2::CenterLineX2, "CenterLineX2");
78     lType.insert(RS2::BorderLine, "BorderLine");
79     lType.insert(RS2::BorderLine2, "BorderLine");
80     lType.insert(RS2::BorderLineX2, "BorderLine");
81 
82     lWidth.insert(RS2::Width00, "0.00mm");
83     lWidth.insert(RS2::Width01, "0.05mm");
84     lWidth.insert(RS2::Width02, "0.09mm");
85     lWidth.insert(RS2::Width03, "0.13mm");
86     lWidth.insert(RS2::Width04, "0.15mm");
87     lWidth.insert(RS2::Width05, "0.18mm");
88     lWidth.insert(RS2::Width06, "0.20mm");
89     lWidth.insert(RS2::Width07, "0.25mm");
90     lWidth.insert(RS2::Width08, "0.30mm");
91     lWidth.insert(RS2::Width09, "0.35mm");
92     lWidth.insert(RS2::Width10, "0.40mm");
93     lWidth.insert(RS2::Width11, "0.50mm");
94     lWidth.insert(RS2::Width12, "0.53mm");
95     lWidth.insert(RS2::Width13, "0.60mm");
96     lWidth.insert(RS2::Width14, "0.70mm");
97     lWidth.insert(RS2::Width15, "0.80mm");
98     lWidth.insert(RS2::Width16, "0.90mm");
99     lWidth.insert(RS2::Width17, "1.00mm");
100     lWidth.insert(RS2::Width18, "1.06mm");
101     lWidth.insert(RS2::Width19, "1.20mm");
102     lWidth.insert(RS2::Width20, "1.40mm");
103     lWidth.insert(RS2::Width21, "1.58mm");
104     lWidth.insert(RS2::Width22, "2.00mm");
105     lWidth.insert(RS2::Width23, "2.11mm");
106     lWidth.insert(RS2::WidthByLayer, "BYLAYER");
107     lWidth.insert(RS2::WidthByBlock, "BYBLOCK");
108     lWidth.insert(RS2::WidthDefault, "BYDEFAULT");
109 }
110 
lt2str(enum RS2::LineType lt)111 QString convLTW::lt2str(enum RS2::LineType lt){
112     return lType.value(lt, "BYLAYER");
113 }
lw2str(enum RS2::LineWidth lw)114 QString convLTW::lw2str(enum RS2::LineWidth lw){
115     return lWidth.value(lw, "BYDEFAULT");
116 }
str2lt(QString s)117 enum RS2::LineType convLTW::str2lt(QString s){
118     return lType.key(s, RS2::LineByLayer);
119 }
str2lw(QString w)120 enum RS2::LineWidth convLTW::str2lw(QString w){
121     return lWidth.key(w, RS2::WidthDefault);
122 }
intColor2str(int col)123 QString convLTW::intColor2str(int col){
124     switch (col) {
125     case -1:
126         return "BYLAYER";
127         break;
128     case -2:
129         return "BYBLOCK";
130         break;
131     default:
132         return QString::number(col >> 16) + ", " + QString::number((col >> 8)& 0xFF) + ", " + QString::number(col & 0xFF);
133         break;
134     }
135 }
136 
137 
138 convLTW Converter;
139 
140 
Plugin_Entity(RS_Entity * ent,Doc_plugin_interface * d)141 Plugin_Entity::Plugin_Entity(RS_Entity* ent, Doc_plugin_interface* d):
142     entity(ent)
143   ,hasContainer(true)
144   ,dpi(d)
145 {
146 }
147 
148 /*RS_EntityContainer* parent,
149                  const RS_LineData& d*/
Plugin_Entity(RS_EntityContainer * parent,enum DPI::ETYPE type)150 Plugin_Entity::Plugin_Entity(RS_EntityContainer* parent, enum DPI::ETYPE type){
151     hasContainer = false;
152 	dpi = nullptr;
153 	entity = nullptr;
154     switch (type) {
155     case DPI::POINT:
156 		entity = new RS_Point(parent, RS_PointData(RS_Vector(0,0)));
157         break;
158     case DPI::LINE:
159 		entity = new RS_Line{parent, {}, {}};
160         break;
161 /*    case DPI::CONSTRUCTIONLINE:
162         entity = new RS_ConstructionLine();
163         break;*/
164     case DPI::CIRCLE:
165         entity = new RS_Circle(parent, RS_CircleData());
166         break;
167     case DPI::ARC:
168         entity = new RS_Arc(parent, RS_ArcData());
169         break;
170     case DPI::ELLIPSE:
171 		entity = new RS_Ellipse{parent,
172 		{{0.,0.}, {0.,0.},0.,0.,0.,false}};
173         break;
174     case DPI::IMAGE:
175         entity = new RS_Image(parent, RS_ImageData());
176         break;
177 /*    case DPI::OVERLAYBOX:
178         entity = new RS_OverlayBox();
179         break;
180     case DPI::SOLID:
181         entity = new RS_Solid();
182         break;*/
183     case DPI::MTEXT:
184         entity = new RS_MText(parent, RS_MTextData());
185         break;
186     case DPI::TEXT:
187         entity = new RS_Text(parent, RS_TextData());
188         break;
189 /*    case DPI::INSERT:
190         entity = new RS_Insert();
191         break;*/
192     case DPI::POLYLINE:
193         entity = new RS_Polyline(parent, RS_PolylineData());
194         break;
195 /*    case DPI::SPLINE:
196         entity = new RS_Spline();
197         break;
198     case DPI::HATCH:
199         entity = new RS_Hatch();
200         break;
201     case DPI::DIMLEADER:
202         entity = new RS_Leader();
203         break;
204     case DPI::DIMALIGNED:
205         entity = new RS_DimAligned();
206         break;
207     case DPI::DIMLINEAR:
208         entity = new RS_DimLinear();
209         break;
210     case DPI::DIMRADIAL:
211         entity = new RS_DimRadial();
212         break;
213     case DPI::DIMDIAMETRIC:
214         entity = new RS_DimDiametric();
215         break;
216     case DPI::DIMANGULAR:
217         entity = new RS_DimAngular();
218         break;*/
219     default:
220         break;
221     }
222 }
223 
~Plugin_Entity()224 Plugin_Entity::~Plugin_Entity() {
225     if(!hasContainer)
226         delete entity;
227 }
228 
getData(QHash<int,QVariant> * data)229 void Plugin_Entity::getData(QHash<int, QVariant> *data){
230 	if (!entity) return;
231     RS2::EntityType et = entity->rtti();
232     data->insert(DPI::EID, (qulonglong)entity->getId());
233     data->insert(DPI::LAYER, entity->getLayer()->getName() );
234     data->insert(DPI::LTYPE, Converter.lt2str(entity->getPen(false).getLineType()) );
235     data->insert(DPI::LWIDTH, Converter.lw2str(entity->getPen(false).getWidth()) );
236     data->insert(DPI::COLOR, entity->getPen(false).getColor().toIntColor() );
237     data->insert(DPI::VISIBLE, (entity->isVisible()) ? 1 : 0 );
238     switch (et) {
239     //atomicEntity
240     case RS2::EntityLine: {
241         data->insert(DPI::ETYPE, DPI::LINE);
242         RS_LineData d = static_cast<RS_Line*>(entity)->getData();
243         data->insert(DPI::STARTX, d.startpoint.x );
244         data->insert(DPI::STARTY, d.startpoint.y );
245         data->insert(DPI::ENDX, d.endpoint.x );
246         data->insert(DPI::ENDY, d.endpoint.y );
247         break;}
248     case RS2::EntityPoint: {
249         data->insert(DPI::ETYPE, DPI::POINT);
250         RS_PointData d = static_cast<RS_Point*>(entity)->getData();
251         data->insert(DPI::STARTX, d.pos.x );
252         data->insert(DPI::STARTY, d.pos.y );
253         break; }
254     case RS2::EntityArc: {
255         data->insert(DPI::ETYPE, DPI::ARC);
256         RS_ArcData d = static_cast<RS_Arc*>(entity)->getData();
257         data->insert(DPI::STARTX, d.center.x );
258         data->insert(DPI::STARTY, d.center.y );
259         data->insert(DPI::RADIUS, d.radius );
260         data->insert(DPI::STARTANGLE, d.angle1 );
261         data->insert(DPI::ENDANGLE, d.angle2 );
262         data->insert(DPI::REVERSED, d.reversed );
263         break;}
264     case RS2::EntityCircle: {
265         data->insert(DPI::ETYPE, DPI::CIRCLE);
266         RS_CircleData d = static_cast<RS_Circle*>(entity)->getData();
267         data->insert(DPI::STARTX, d.center.x );
268         data->insert(DPI::STARTY, d.center.y );
269         data->insert(DPI::RADIUS, d.radius );
270         break;}
271     case RS2::EntityEllipse: {
272         data->insert(DPI::ETYPE, DPI::ELLIPSE);
273 //        RS_EllipseData d = static_cast<RS_Ellipse*>(entity)->getData();
274         RS_Ellipse *dd = static_cast<RS_Ellipse*>(entity);
275         data->insert(DPI::STARTX, dd->getCenter().x );//10
276         data->insert(DPI::STARTY, dd->getCenter().y );//20
277         data->insert(DPI::ENDX, dd->getMajorP().x );//11 endpoint major axis x
278         data->insert(DPI::ENDY, dd->getMajorP().y );//21 endpoint major axis y
279         data->insert(DPI::HEIGHT, dd->getRatio() );//40 major/minor axis ratio
280         data->insert(DPI::STARTANGLE, dd->getAngle1() );
281         data->insert(DPI::ENDANGLE, dd->getAngle2() );
282         data->insert(DPI::REVERSED, dd->isReversed() );
283         break;}
284     case RS2::EntitySolid: //TODO
285         //Only used in dimensions ?
286         data->insert(DPI::ETYPE, DPI::SOLID);
287         break;
288     case RS2::EntityConstructionLine:
289         //Unused ?
290         data->insert(DPI::ETYPE, DPI::CONSTRUCTIONLINE);
291         break;
292     case RS2::EntityImage: {
293         data->insert(DPI::ETYPE, DPI::IMAGE);
294         RS_ImageData d = static_cast<RS_Image*>(entity)->getData();
295         data->insert(DPI::STARTX, d.insertionPoint.x );
296         data->insert(DPI::STARTY, d.insertionPoint.y );
297         data->insert(DPI::ENDX, d.uVector.x );
298         data->insert(DPI::ENDY, d.uVector.y );
299         data->insert(DPI::VVECTORX, d.vVector.x );
300         data->insert(DPI::VVECTORY, d.vVector.y );
301         data->insert(DPI::SIZEU, d.size.x );
302         data->insert(DPI::SIZEV, d.size.y );
303         data->insert(DPI::BLKNAME, d.file );
304         break;}
305     case RS2::EntityOverlayBox:
306         //Unused ?
307         data->insert(DPI::ETYPE, DPI::OVERLAYBOX);
308         break;
309 //EntityContainer
310     case RS2::EntityInsert: {
311         data->insert(DPI::ETYPE, DPI::INSERT);
312         RS_InsertData d = static_cast<RS_Insert*>(entity)->getData();
313         data->insert(DPI::STARTX, d.insertionPoint.x );
314         data->insert(DPI::STARTY, d.insertionPoint.y );
315         data->insert(DPI::BLKNAME, d.name );
316         data->insert(DPI::STARTANGLE, d.angle );
317         data->insert(DPI::XSCALE, d.scaleFactor.x );
318         data->insert(DPI::YSCALE, d.scaleFactor.y );
319         break;}
320     case RS2::EntityMText: {
321         data->insert(DPI::ETYPE, DPI::MTEXT);
322         RS_MTextData d = static_cast<RS_MText*>(entity)->getData();
323         data->insert(DPI::STARTX, d.insertionPoint.x );
324         data->insert(DPI::STARTY, d.insertionPoint.y );
325         data->insert(DPI::STARTANGLE, d.angle );
326         data->insert(DPI::HEIGHT, d.height );
327         data->insert(DPI::TEXTCONTENT, d.text );
328         break;}
329     case RS2::EntityText: {
330         data->insert(DPI::ETYPE, DPI::TEXT);
331         RS_TextData d = static_cast<RS_Text*>(entity)->getData();
332         data->insert(DPI::STARTX, d.insertionPoint.x );
333         data->insert(DPI::STARTY, d.insertionPoint.y );
334         data->insert(DPI::STARTANGLE, d.angle );
335         data->insert(DPI::HEIGHT, d.height );
336         data->insert(DPI::TEXTCONTENT, d.text );
337         break;}
338     case RS2::EntityHatch:
339         data->insert(DPI::ETYPE, DPI::HATCH);
340         break;
341     case RS2::EntitySpline:
342         data->insert(DPI::ETYPE, DPI::SPLINE);
343         break;
344 	case RS2::EntitySplinePoints:
345 		data->insert(DPI::ETYPE, DPI::SPLINEPOINTS);
346 		break;
347     case RS2::EntityPolyline:
348         data->insert(DPI::ETYPE, DPI::POLYLINE);
349         data->insert(DPI::CLOSEPOLY, static_cast<RS_Polyline*>(entity)->isClosed() );
350         break;
351     case RS2::EntityVertex:
352         data->insert(DPI::ETYPE, DPI::UNKNOWN);
353         break;
354     case RS2::EntityDimAligned:
355         data->insert(DPI::ETYPE, DPI::DIMALIGNED);
356         break;
357     case RS2::EntityDimLinear:
358         data->insert(DPI::ETYPE, DPI::DIMLINEAR);
359         break;
360     case RS2::EntityDimRadial:
361         data->insert(DPI::ETYPE, DPI::DIMRADIAL);
362         break;
363     case RS2::EntityDimDiametric:
364         data->insert(DPI::ETYPE, DPI::DIMDIAMETRIC);
365         break;
366     case RS2::EntityDimAngular:
367         data->insert(DPI::ETYPE, DPI::DIMANGULAR);
368         break;
369     case RS2::EntityDimLeader:
370         data->insert(DPI::ETYPE, DPI::DIMLEADER);
371         break;
372     case RS2::EntityUnknown:
373     default:
374         data->insert(DPI::ETYPE, DPI::UNKNOWN);
375         break;
376     }
377 }
378 
updateData(QHash<int,QVariant> * data)379 void Plugin_Entity::updateData(QHash<int, QVariant> *data){
380 	if (!entity) return;
381     RS_Entity *ec= entity;
382     if(hasContainer && dpi) {
383         ec = entity->clone();
384     }
385     QHash<int, QVariant> hash = *data;
386     QString str;
387     RS_Vector vec;
388     RS_Pen epen = ec->getPen();
389 //    double num;
390     if (hash.contains(DPI::LAYER)) {
391         str = (hash.take(DPI::LAYER)).toString();
392         ec->setLayer(str);
393     }
394     if (hash.contains(DPI::LTYPE)) {
395         str = (hash.take(DPI::LTYPE)).toString();
396         epen.setLineType( Converter.str2lt(str) );
397     }
398     if (hash.contains(DPI::LWIDTH)) {
399         str = (hash.take(DPI::LWIDTH)).toString();
400         epen.setWidth( Converter.str2lw(str) );
401     }
402     if (hash.contains(DPI::COLOR)) {
403         int co = hash.take(DPI::COLOR).toInt();
404         RS_Color color;// = hash.take(DPI::COLOR).value<QColor>();
405         color.fromIntColor(co);
406         epen.setColor(color);
407     }
408     ec->setPen(epen);
409 
410     RS2::EntityType et = ec->rtti();
411     switch (et) {
412     //atomicEntity
413     case RS2::EntityLine: {
414         vec = static_cast<RS_Line*>(ec)->getStartpoint();
415         if (hash.contains(DPI::STARTX)) {
416             vec.x = (hash.take(DPI::STARTX)).toDouble();
417         }
418         if (hash.contains(DPI::STARTY)) {
419             vec.y = (hash.take(DPI::STARTY)).toDouble();
420         }
421         static_cast<RS_Line*>(ec)->setStartpoint(vec);
422         vec = static_cast<RS_Line*>(ec)->getEndpoint();
423         if (hash.contains(DPI::ENDX)) {
424             vec.x = (hash.take(DPI::ENDX)).toDouble();
425         }
426         if (hash.contains(DPI::ENDY)) {
427             vec.y = (hash.take(DPI::ENDY)).toDouble();
428         }
429         static_cast<RS_Line*>(ec)->setEndpoint(vec);
430         break;}
431     case RS2::EntityPoint: {
432         vec = static_cast<RS_Point*>(ec)->getPos();
433         if (hash.contains(DPI::STARTX)) {
434             vec.x = (hash.take(DPI::STARTX)).toDouble();
435         }
436         if (hash.contains(DPI::STARTY)) {
437             vec.y = (hash.take(DPI::STARTY)).toDouble();
438         }
439         static_cast<RS_Point*>(ec)->setPos(vec);
440         break; }
441     case RS2::EntityArc: {
442         RS_Arc *arc = static_cast<RS_Arc*>(ec);
443         vec = arc->getCenter();
444         if (hash.contains(DPI::STARTX)) {
445             vec.x = (hash.take(DPI::STARTX)).toDouble();
446         }
447         if (hash.contains(DPI::STARTY)) {
448             vec.y = (hash.take(DPI::STARTY)).toDouble();
449         }
450         arc->setCenter(vec);
451         if (hash.contains(DPI::RADIUS)) {
452             arc->setRadius( (hash.take(DPI::RADIUS)).toDouble() );
453         }
454         if (hash.contains(DPI::STARTANGLE)) {
455              arc->setAngle1( (hash.take(DPI::STARTANGLE)).toDouble() );
456            vec.y = (hash.take(DPI::STARTANGLE)).toDouble();
457         }
458         if (hash.contains(DPI::ENDANGLE)) {
459             arc->setAngle2( (hash.take(DPI::ENDANGLE)).toDouble() );
460         }
461         break;}
462     case RS2::EntityCircle: {
463         RS_Circle *cir = static_cast<RS_Circle*>(ec);
464         vec = cir->getCenter();
465         if (hash.contains(DPI::STARTX)) {
466             vec.x = (hash.take(DPI::STARTX)).toDouble();
467         }
468         if (hash.contains(DPI::STARTY)) {
469             vec.y = (hash.take(DPI::STARTY)).toDouble();
470         }
471         cir->setCenter(vec);
472         if (hash.contains(DPI::RADIUS)) {
473             cir->setRadius( (hash.take(DPI::RADIUS)).toDouble() );
474         }
475         break;}
476     case RS2::EntityEllipse: {
477         RS_Ellipse *ellipse = static_cast<RS_Ellipse*>(ec);
478         vec = ellipse->getCenter();
479         if (hash.contains(DPI::STARTX)) {
480             vec.x = (hash.take(DPI::STARTX)).toDouble();
481         }
482         if (hash.contains(DPI::STARTY)) {
483             vec.y = (hash.take(DPI::STARTY)).toDouble();
484         }
485         ellipse->setCenter(vec);
486 
487         vec = ellipse->getMajorP();
488         if (hash.contains(DPI::ENDX)) {
489             vec.x = (hash.take(DPI::ENDX)).toDouble();
490         }
491         if (hash.contains(DPI::ENDY)) {
492             vec.y = (hash.take(DPI::ENDY)).toDouble();
493         }
494         ellipse->setMajorP(vec);
495 
496         if (hash.contains(DPI::STARTANGLE)) {
497             ellipse->setAngle1((hash.take(DPI::STARTANGLE)).toDouble());
498         }
499         if (hash.contains(DPI::ENDANGLE)) {
500             ellipse->setAngle2((hash.take(DPI::ENDANGLE)).toDouble());
501         }
502         if (hash.contains(DPI::HEIGHT)) {
503             ellipse->setRatio((hash.take(DPI::HEIGHT)).toDouble());
504         }
505         if (hash.contains(DPI::REVERSED)) {
506             ellipse->setReversed( (hash.take(DPI::REVERSED)).toBool());
507         }
508         break;}
509     case RS2::EntitySolid: //TODO
510         //Only used in dimensions ?
511         break;
512     case RS2::EntityConstructionLine:
513         //Unused ?
514         break;
515     case RS2::EntityImage: {
516         RS_Image *img = static_cast<RS_Image*>(ec);
517         vec = img->getInsertionPoint();
518         if (hash.contains(DPI::STARTX)) {
519             vec.x = (hash.take(DPI::STARTX)).toDouble();
520         }
521         if (hash.contains(DPI::STARTY)) {
522             vec.y = (hash.take(DPI::STARTY)).toDouble();
523         }
524         img->setInsertionPoint(vec);
525         if (hash.contains(DPI::BLKNAME)) {
526             img->setFile( (hash.take(DPI::BLKNAME)).toString() );
527         }
528         vec = img->getUVector();
529         RS_Vector vec2 = img->getVVector();
530         RS_Vector vec3(img->getWidth(),img->getHeight());
531         if (hash.contains(DPI::ENDX)) {
532             vec.x = (hash.take(DPI::ENDX)).toDouble();
533         }
534         if (hash.contains(DPI::ENDY)) {
535             vec.y = (hash.take(DPI::ENDY)).toDouble();
536         }
537         if (hash.contains(DPI::VVECTORX)) {
538             vec2.x = (hash.take(DPI::VVECTORX)).toDouble();
539         }
540         if (hash.contains(DPI::VVECTORY)) {
541             vec2.y = (hash.take(DPI::VVECTORY)).toDouble();
542         }
543         if (hash.contains(DPI::SIZEU)) {
544             vec3.x = (hash.take(DPI::SIZEU)).toDouble();
545         }
546         if (hash.contains(DPI::SIZEV)) {
547             vec3.y = (hash.take(DPI::SIZEV)).toDouble();
548         }
549         img->updateData(vec3, vec, vec2);
550         break;}
551     case RS2::EntityOverlayBox:
552         //Unused ?
553         break;
554 //EntityContainer
555     case RS2::EntityInsert: {
556         break;}
557     case RS2::EntityMText: {
558         RS_MText *txt = static_cast<RS_MText*>(ec);
559         bool move = false;
560         vec = txt->getInsertionPoint();
561         if (hash.contains(DPI::STARTX)) {
562             vec.x = (hash.take(DPI::STARTX)).toDouble() - vec.x;
563             move = true;
564         } else vec.x = 0;
565         if (hash.contains(DPI::STARTY)) {
566             vec.y = (hash.take(DPI::STARTY)).toDouble() - vec.y;
567             move = true;
568         } else vec.y = 0;
569         if (move)
570             txt->move(vec);
571         if (hash.contains(DPI::TEXTCONTENT)) {
572             txt->setText( (hash.take(DPI::TEXTCONTENT)).toString() );
573         }
574         if (hash.contains(DPI::STARTANGLE)) {
575             txt->setAngle( (hash.take(DPI::STARTANGLE)).toDouble() );
576         }
577         if (hash.contains(DPI::HEIGHT)) {
578             txt->setHeight( (hash.take(DPI::HEIGHT)).toDouble() );
579         }
580         break;}
581     case RS2::EntityText: {
582         RS_Text *txt = static_cast<RS_Text*>(ec);
583         bool move = false;
584         vec = txt->getInsertionPoint();
585         if (hash.contains(DPI::STARTX)) {
586             vec.x = (hash.take(DPI::STARTX)).toDouble() - vec.x;
587             move = true;
588         } else vec.x = 0;
589         if (hash.contains(DPI::STARTY)) {
590             vec.y = (hash.take(DPI::STARTY)).toDouble() - vec.y;
591             move = true;
592         } else vec.y = 0;
593         if (move)
594             txt->move(vec);
595         if (hash.contains(DPI::TEXTCONTENT)) {
596             txt->setText( (hash.take(DPI::TEXTCONTENT)).toString() );
597         }
598         if (hash.contains(DPI::STARTANGLE)) {
599             txt->setAngle( (hash.take(DPI::STARTANGLE)).toDouble() );
600         }
601         if (hash.contains(DPI::HEIGHT)) {
602             txt->setHeight( (hash.take(DPI::HEIGHT)).toDouble() );
603         }
604         break;}
605     case RS2::EntityHatch:
606         break;
607     case RS2::EntitySpline:
608         break;
609     case RS2::EntityPolyline: {
610         RS_Polyline *pl = static_cast<RS_Polyline*>(ec);
611         if (hash.take(DPI::CLOSEPOLY).toBool()) {
612             pl->setClosed(true);
613         }else{
614             pl->setClosed(false);
615         }
616         break;}
617     case RS2::EntityVertex:
618         break;
619     case RS2::EntityDimAligned:
620         break;
621     case RS2::EntityDimLinear:
622         break;
623     case RS2::EntityDimRadial:
624         break;
625     case RS2::EntityDimDiametric:
626         break;
627     case RS2::EntityDimAngular:
628         break;
629     case RS2::EntityDimLeader:
630         break;
631     case RS2::EntityUnknown:
632     default:
633         break;
634     }
635     ec->update();
636     if(hasContainer && dpi)
637         this->dpi->updateEntity(entity, ec);
638 }
639 
getPolylineData(QList<Plug_VertexData> * data)640 void Plugin_Entity::getPolylineData(QList<Plug_VertexData> *data){
641 	if (!entity) return;
642     RS2::EntityType et = entity->rtti();
643     if (et != RS2::EntityPolyline) return;
644     RS_Polyline *l = static_cast<RS_Polyline*>(entity);
645 
646     RS_Entity* nextEntity = 0;
647 	RS_AtomicEntity* ae = nullptr;
648     RS_Entity* v = l->firstEntity(RS2::ResolveNone);
649     double bulge=0.0;
650 //bad polyline without vertex
651 	if (!v) return;
652 
653 //First polyline vertex
654     if (v->rtti() == RS2::EntityArc) {
655         bulge = ((RS_Arc*)v)->getBulge();
656     }
657     ae = (RS_AtomicEntity*)v;
658     data->append(Plug_VertexData(QPointF(ae->getStartpoint().x,
659                                          ae->getStartpoint().y),bulge));
660 
661 	for (v=l->firstEntity(RS2::ResolveNone); v; v=nextEntity) {
662 		nextEntity = l->nextEntity(RS2::ResolveNone);
663         bulge = 0.0;
664         if (!v->isAtomic()) {
665             continue;
666         }
667         ae = (RS_AtomicEntity*)v;
668 
669         if (nextEntity) {
670             if (nextEntity->rtti()==RS2::EntityArc) {
671                 bulge = ((RS_Arc*)nextEntity)->getBulge();
672             }
673         }
674 
675 		if (!l->isClosed() || nextEntity) {
676             data->append(Plug_VertexData(QPointF(ae->getEndpoint().x,
677                                          ae->getEndpoint().y),bulge));
678         }
679     }
680 
681 }
682 
updatePolylineData(QList<Plug_VertexData> * data)683 void Plugin_Entity::updatePolylineData(QList<Plug_VertexData> *data){
684 	if (!entity) return;
685     RS2::EntityType et = entity->rtti();
686     if (et != RS2::EntityPolyline) return;
687     if (data->size()<2) return; //At least two vertex
688     RS_Vector vec(false);
689     RS_Polyline *pl = static_cast<RS_Polyline*>(entity);
690 //    vec.x = data->at(0).point.x();
691 //    vec.y = data->at(0).point.y();
692     pl->clear();
693     pl->setEndpoint(vec);
694     pl->setStartpoint(vec);
695     vec.valid = true;
696     for (int i = 0; i < data->size(); ++i) {
697         vec.x = data->at(i).point.x();
698         vec.y = data->at(i).point.y();
699         pl->addVertex(vec, data->at(i).bulge );
700     }
701 
702 
703 }
704 
move(QPointF offset)705 void Plugin_Entity::move(QPointF offset){
706     RS_Entity *ne = entity->clone();
707     ne->move( RS_Vector(offset.x(), offset.y()) );
708     bool ok = dpi->addToUndo(entity, ne);
709     //if doc interface fails to handle for undo only modify original entity
710     if (!ok){
711         entity->move( RS_Vector(offset.x(), offset.y()) );
712         delete ne;
713     } else
714         this->entity = ne;
715 }
716 
moveRotate(QPointF const & offset,QPointF const & center,double angle)717 void Plugin_Entity::moveRotate(QPointF const& offset, QPointF const& center, double angle)
718 {
719 	RS_Entity *ne = entity->clone();
720 	ne->move( RS_Vector(offset.x(), offset.y()) );
721 	ne->rotate( RS_Vector(center.x(), center.y()) , angle);
722 	bool ok = dpi->addToUndo(entity, ne);
723 	//if doc interface fails to handle for undo only modify original entity
724 	if (!ok){
725 		entity->move( RS_Vector(offset.x(), offset.y()) );
726 		entity->rotate( RS_Vector(center.x(), center.y()) , angle);
727 		delete ne;
728 	} else
729 		this->entity = ne;
730 }
731 
rotate(QPointF center,double angle)732 void Plugin_Entity::rotate(QPointF center, double angle){
733     RS_Entity *ne = entity->clone();
734     ne->rotate( RS_Vector(center.x(), center.y()) , angle);
735     bool ok = dpi->addToUndo(entity, ne);
736     //if doc interface fails to handle for undo only modify original entity
737     if (!ok){
738         entity->rotate( RS_Vector(center.x(), center.y()) , angle);
739         delete ne;
740     } else
741         this->entity = ne;
742 }
743 
scale(QPointF center,QPointF factor)744 void Plugin_Entity::scale(QPointF center, QPointF factor){
745     RS_Entity *ne = entity->clone();
746     ne->scale( RS_Vector(center.x(), center.y()),
747                 RS_Vector(factor.x(), factor.y()) );
748     bool ok = dpi->addToUndo(entity, ne);
749     //if doc interface fails to handle for undo only modify original entity
750     if (!ok){
751         entity->scale( RS_Vector(center.x(), center.y()),
752                     RS_Vector(factor.x(), factor.y()) );
753         delete ne;
754     } else
755         this->entity = ne;
756 }
757 
intColor2str(int color)758 QString Plugin_Entity::intColor2str(int color){
759     return Converter.intColor2str(color);
760 }
761 
Doc_plugin_interface(RS_Document * d,RS_GraphicView * gv,QWidget * parent)762 Doc_plugin_interface::Doc_plugin_interface(RS_Document *d, RS_GraphicView* gv, QWidget* parent):
763 doc(d)
764 ,docGr(doc->getGraphic())
765 ,gView(gv)
766 ,main_window(parent)
767 {
768 }
769 
addToUndo(RS_Entity * current,RS_Entity * modified)770 bool Doc_plugin_interface::addToUndo(RS_Entity* current, RS_Entity* modified){
771     if (doc) {
772         doc->addEntity(modified);
773         LC_UndoSection undo(doc);
774         if (current->isSelected())
775             current->setSelected(false);
776         current->changeUndoState();
777         undo.addUndoable(current);
778         undo.addUndoable(modified);
779         return true;
780     } else
781 		RS_DEBUG->print("Doc_plugin_interface::addToUndo: currentContainer is nullptr");
782     return false;
783 }
784 
updateView()785 void Doc_plugin_interface::updateView(){
786     doc->setSelected(false);
787     gView->getContainer()->calculateBorders();
788     gView->redraw();
789 }
790 
addPoint(QPointF * start)791 void Doc_plugin_interface::addPoint(QPointF *start){
792 
793     RS_Vector v1(start->x(), start->y());
794     if (doc) {
795         RS_Point* entity = new RS_Point(doc, RS_PointData(v1));
796         doc->addEntity(entity);
797         LC_UndoSection undo(doc);
798         undo.addUndoable(entity);
799     } else
800 		RS_DEBUG->print("Doc_plugin_interface::addPoint: currentContainer is nullptr");
801 }
802 
addLine(QPointF * start,QPointF * end)803 void Doc_plugin_interface::addLine(QPointF *start, QPointF *end){
804 
805     RS_Vector v1(start->x(), start->y());
806     RS_Vector v2(end->x(), end->y());
807     if (doc) {
808 		RS_Line* entity = new RS_Line{doc, v1, v2};
809         doc->addEntity(entity);
810         LC_UndoSection undo(doc);
811         undo.addUndoable(entity);
812     } else
813 		RS_DEBUG->print("Doc_plugin_interface::addLine: currentContainer is nullptr");
814 }
815 
addMText(QString txt,QString sty,QPointF * start,double height,double angle,DPI::HAlign ha,DPI::VAlign va)816 void Doc_plugin_interface::addMText(QString txt, QString sty, QPointF *start,
817             double height, double angle, DPI::HAlign ha,  DPI::VAlign va){
818 
819     RS_Vector v1(start->x(), start->y());
820     if (doc) {
821         double width = 100.0;
822 
823         RS_MTextData::VAlign valign = static_cast <RS_MTextData::VAlign>(va);
824         RS_MTextData::HAlign halign = static_cast <RS_MTextData::HAlign>(ha);
825         RS_MTextData d(v1, height, width, valign, halign,
826                   RS_MTextData::ByStyle, RS_MTextData::Exact, 0.0,
827                   txt, sty, angle, RS2::Update);
828         RS_MText* entity = new RS_MText(doc, d);
829 
830         doc->addEntity(entity);
831         LC_UndoSection undo(doc);
832         undo.addUndoable(entity);
833     } else
834 		RS_DEBUG->print("Doc_plugin_interface::addMtext: currentContainer is nullptr");
835 }
836 
addText(QString txt,QString sty,QPointF * start,double height,double angle,DPI::HAlign ha,DPI::VAlign va)837 void Doc_plugin_interface::addText(QString txt, QString sty, QPointF *start,
838             double height, double angle, DPI::HAlign ha,  DPI::VAlign va){
839 
840     RS_Vector v1(start->x(), start->y());
841     if (doc) {
842         double width = 1.0;
843 
844         RS_TextData::VAlign valign = static_cast <RS_TextData::VAlign>(va);
845         RS_TextData::HAlign halign = static_cast <RS_TextData::HAlign>(ha);
846         RS_TextData d(v1, v1, height, width, valign, halign,
847                   RS_TextData::None, txt, sty, angle, RS2::Update);
848         RS_Text* entity = new RS_Text(doc, d);
849 
850         doc->addEntity(entity);
851         LC_UndoSection undo(doc);
852         undo.addUndoable(entity);
853     } else
854 		RS_DEBUG->print("Doc_plugin_interface::addText: currentContainer is nullptr");
855 }
856 
addCircle(QPointF * start,qreal radius)857 void Doc_plugin_interface::addCircle(QPointF *start, qreal radius){
858     if (doc) {
859         RS_Vector v(start->x(), start->y());
860         RS_CircleData d(v, radius);
861         RS_Circle* entity = new RS_Circle(doc, d);
862 
863         doc->addEntity(entity);
864         LC_UndoSection undo(doc);
865         undo.addUndoable(entity);
866     } else
867 		RS_DEBUG->print("Doc_plugin_interface::addCircle: currentContainer is nullptr");
868 }
869 
addArc(QPointF * start,qreal radius,qreal a1,qreal a2)870 void Doc_plugin_interface::addArc(QPointF *start, qreal radius, qreal a1, qreal a2){
871     if (doc) {
872         RS_Vector v(start->x(), start->y());
873         RS_ArcData d(v, radius,
874 				 RS_Math::deg2rad(a1),
875 				 RS_Math::deg2rad(a2),
876                  false);
877         RS_Arc* entity = new RS_Arc(doc, d);
878         doc->addEntity(entity);
879         LC_UndoSection undo(doc);
880         undo.addUndoable(entity);
881     } else
882 		RS_DEBUG->print("Doc_plugin_interface::addArc: currentContainer is nullptr");
883 }
884 
addEllipse(QPointF * start,QPointF * end,qreal ratio,qreal a1,qreal a2)885 void Doc_plugin_interface::addEllipse(QPointF *start, QPointF *end, qreal ratio, qreal a1, qreal a2){
886     if (doc) {
887         RS_Vector v1(start->x(), start->y());
888         RS_Vector v2(end->x(), end->y());
889 
890 		RS_EllipseData ed{v1, v2, ratio, a1, a2, false};
891         RS_Ellipse* entity = new RS_Ellipse(doc, ed);
892 
893         doc->addEntity(entity);
894         LC_UndoSection undo(doc);
895         undo.addUndoable(entity);
896     } else
897 		RS_DEBUG->print("Doc_plugin_interface::addEllipse: currentContainer is nullptr");
898 }
899 
addLines(std::vector<QPointF> const & points,bool closed)900 void Doc_plugin_interface::addLines(std::vector<QPointF> const& points, bool closed)
901 {
902     if (doc) {
903         RS_LineData data;
904 
905         LC_UndoSection undo(doc);
906         data.endpoint=RS_Vector(points.front().x(), points.front().y());
907 
908         for(size_t i=1; i<points.size(); ++i){
909             data.startpoint=data.endpoint;
910             data.endpoint=RS_Vector(points[i].x(), points[i].y());
911             RS_Line* line=new RS_Line(doc, data);
912             doc->addEntity(line);
913             undo.addUndoable(line);
914         }
915         if(closed){
916             data.startpoint=data.endpoint;
917             data.endpoint=RS_Vector(points.front().x(), points.front().y());
918             RS_Line* line=new RS_Line(doc, data);
919             doc->addEntity(line);
920             undo.addUndoable(line);
921         }
922     } else
923 		RS_DEBUG->print("%s: currentContainer is nullptr", __func__);
924 }
925 
addPolyline(std::vector<Plug_VertexData> const & points,bool closed)926 void Doc_plugin_interface::addPolyline(std::vector<Plug_VertexData> const& points, bool closed)
927 {
928     if (doc) {
929         RS_PolylineData data;
930         if(closed)
931             data.setFlag(RS2::FlagClosed);
932         RS_Polyline* entity = new RS_Polyline(doc, data);
933 
934         for(auto const& pt: points){
935             entity->addVertex(RS_Vector(pt.point.x(), pt.point.y()), pt.bulge);
936         }
937 
938         doc->addEntity(entity);
939         LC_UndoSection undo(doc);
940         undo.addUndoable(entity);
941     } else
942 		RS_DEBUG->print("%s: currentContainer is nullptr", __func__);
943 }
944 
addSplinePoints(std::vector<QPointF> const & points,bool closed)945 void Doc_plugin_interface::addSplinePoints(std::vector<QPointF> const& points, bool closed)
946 {
947     if (doc) {
948         LC_SplinePointsData data(closed, false); //cut = false
949         for(auto const& pt: points){
950             data.splinePoints.emplace_back(RS_Vector(pt.x(), pt.y()));
951         }
952 
953         LC_SplinePoints* entity = new LC_SplinePoints(doc, data);
954 
955         doc->addEntity(entity);
956         LC_UndoSection undo(doc);
957         undo.addUndoable(entity);
958     } else
959 		RS_DEBUG->print("%s: currentContainer is nullptr", __func__);
960 }
961 
addImage(int handle,QPointF * start,QPointF * uvr,QPointF * vvr,int w,int h,QString name,int br,int con,int fade)962 void Doc_plugin_interface::addImage(int handle, QPointF *start, QPointF *uvr, QPointF *vvr,
963                                     int w, int h, QString name, int br, int con, int fade){
964     if (doc) {
965         RS_Vector ip(start->x(), start->y());
966         RS_Vector uv(uvr->x(), uvr->y());
967         RS_Vector vv(vvr->x(), vvr->y());
968         RS_Vector size(w, h);
969 
970         RS_Image* image =
971             new RS_Image(
972                 doc,
973 				RS_ImageData(handle /*QString(data.ref.c_str()).toInt(nullptr, 16)*/,
974                          ip, uv, vv,
975                          size,
976                          name,
977                          br,
978                          con,
979                          fade));
980 
981         doc->addEntity(image);
982         LC_UndoSection undo(doc);
983         undo.addUndoable(image);
984     } else
985 		RS_DEBUG->print("Doc_plugin_interface::addImage: currentContainer is nullptr");
986 }
987 
addInsert(QString name,QPointF ins,QPointF scale,qreal rot)988 void Doc_plugin_interface::addInsert(QString name, QPointF ins, QPointF scale, qreal rot){
989     if (doc) {
990         RS_Vector ip(ins.x(), ins.y());
991         RS_Vector sp(scale.x(), scale.y());
992 
993         RS_InsertData id(name, ip, sp, rot, 1, 1, RS_Vector(0.0, 0.0));
994         RS_Insert* entity = new RS_Insert(doc, id);
995 
996         doc->addEntity(entity);
997         LC_UndoSection undo(doc);
998         undo.addUndoable(entity);
999     } else
1000 		RS_DEBUG->print("Doc_plugin_interface::addInsert: currentContainer is nullptr");
1001 }
1002 
1003 /*TODO RLZ: add undo support in this method*/
addBlockfromFromdisk(QString fullName)1004 QString Doc_plugin_interface::addBlockfromFromdisk(QString fullName){
1005 	if (fullName.isEmpty() || !doc)
1006 		return nullptr;
1007     RS_BlockList* blockList = doc->getBlockList();
1008 	if (!blockList)
1009 		return nullptr;
1010 
1011     QFileInfo fi(fullName);
1012     QString s = fi.completeBaseName();
1013 
1014 	QString name = blockList->newName(s);
1015 
1016     if (fi.isReadable()) {
1017         RS_BlockData d(name, RS_Vector(0,0), false);
1018         RS_Block *b = new RS_Block(doc, d);
1019         RS_Graphic g;
1020         if (!g.open(fi.absoluteFilePath(), RS2::FormatUnknown)) {
1021             RS_DEBUG->print(RS_Debug::D_WARNING,
1022                             "Doc_plugin_interface::addBlockfromFromdisk: Cannot open file: %s");
1023             delete b;
1024 			return nullptr;
1025         }
1026         RS_LayerList* ll = g.getLayerList();
1027         for (unsigned int i = 0; i<ll->count(); i++){
1028             RS_Layer* nl = ll->at(i)->clone();
1029             docGr->addLayer(nl);
1030         }
1031         RS_BlockList* bl = g.getBlockList();
1032         for (int i = 0; i<bl->count(); i++){
1033             RS_Block* nb = (RS_Block*)bl->at(i)->clone();
1034             docGr->addBlock(nb);
1035         }
1036         for (unsigned int i = 0; i<g.count(); i++){
1037             RS_Entity* e = g.entityAt(i)->clone();
1038             e->reparent(b);
1039             b->addEntity(e);
1040         }
1041         docGr->addBlock(b);
1042         return name;
1043 
1044     } else {
1045 		return nullptr;
1046     }
1047 }
1048 
addEntity(Plug_Entity * handle)1049 void Doc_plugin_interface::addEntity(Plug_Entity *handle){
1050     if (doc) {
1051         RS_Entity *ent = (reinterpret_cast<Plugin_Entity*>(handle))->getEnt();
1052 		if (ent) {
1053             doc->addEntity(ent);
1054             LC_UndoSection undo(doc);
1055             undo.addUndoable(ent);
1056         }
1057     } else
1058 		RS_DEBUG->print("Doc_plugin_interface::addEntity: currentContainer is nullptr");
1059 }
1060 
1061 /*newEntity not added into graphic, then not needed undo support*/
newEntity(enum DPI::ETYPE type)1062 Plug_Entity *Doc_plugin_interface::newEntity( enum DPI::ETYPE type){
1063     Plugin_Entity *e = new Plugin_Entity(doc, type);
1064     if( !(e->isValid()) ) {
1065         delete e;
1066 		return nullptr;
1067     }
1068     return  reinterpret_cast<Plug_Entity*>(e);
1069 }
1070 
1071 /*TODO RLZ: add undo support in this method*/
removeEntity(Plug_Entity * ent)1072 void Doc_plugin_interface::removeEntity(Plug_Entity *ent){
1073     RS_Entity *e = (reinterpret_cast<Plugin_Entity*>(ent))->getEnt();
1074     if (doc && e) {
1075         LC_UndoSection undo(doc);
1076         e->setSelected(false);
1077         e->changeUndoState();
1078         undo.addUndoable(e);
1079 
1080         gView->redraw(RS2::RedrawDrawing);
1081     }
1082 }
1083 
updateEntity(RS_Entity * org,RS_Entity * newe)1084 void Doc_plugin_interface::updateEntity(RS_Entity *org, RS_Entity *newe){
1085     if (doc) {
1086         LC_UndoSection undo(doc);
1087         doc->addEntity(newe);
1088         undo.addUndoable(newe);
1089         undo.addUndoable(org);
1090         org->setUndoState(true);
1091     } else
1092 		RS_DEBUG->print("Doc_plugin_interface::addEntity: currentContainer is nullptr");
1093 }
1094 
1095 /*TODO RLZ: add undo support in the remaining methods*/
setLayer(QString name)1096 void Doc_plugin_interface::setLayer(QString name){
1097     RS_LayerList* listLay = doc->getLayerList();
1098     RS_Layer *lay = listLay->find(name);
1099 	if (!lay) {
1100         lay = new RS_Layer(name);
1101         docGr->addLayer(lay);
1102     }
1103     listLay->activate(lay, true);
1104 }
1105 
getCurrentLayer()1106 QString Doc_plugin_interface::getCurrentLayer(){
1107     return docGr->getActiveLayer()->getName();
1108 }
1109 
getAllLayer()1110 QStringList Doc_plugin_interface::getAllLayer(){
1111     QStringList listName;
1112     RS_LayerList* listLay = doc->getLayerList();
1113     for (unsigned int i = 0; i < listLay->count(); ++i) {
1114          listName << listLay->at(i)->getName();
1115      }
1116     return listName;
1117 }
1118 
getAllBlocks()1119 QStringList Doc_plugin_interface::getAllBlocks(){
1120     QStringList listName;
1121     RS_BlockList* listBlk = doc->getBlockList();
1122     for (int i = 0; i < listBlk->count(); ++i) {
1123          listName << listBlk->at(i)->getName();
1124      }
1125     return listName;
1126 }
1127 
deleteLayer(QString name)1128 bool Doc_plugin_interface::deleteLayer(QString name){
1129     RS_Layer* layer = docGr->findLayer(name);
1130 	if (layer) {
1131         docGr->removeLayer(layer);
1132         return true;
1133     }
1134     return false;
1135 }
1136 
getCurrentLayerProperties(int * c,DPI::LineWidth * w,DPI::LineType * t)1137 void Doc_plugin_interface::getCurrentLayerProperties(int *c, DPI::LineWidth *w, DPI::LineType *t){
1138     RS_Pen pen = docGr->getActiveLayer()->getPen();
1139     *c = pen.getColor().toIntColor();
1140 //    RS_Color col = pen.getColor();
1141 //    c->setRgb(col.red(), col.green(), col.blue());
1142     *w = static_cast<DPI::LineWidth>(pen.getWidth());
1143     *t = static_cast<DPI::LineType>(pen.getLineType());
1144 }
1145 
getCurrentLayerProperties(int * c,QString * w,QString * t)1146 void Doc_plugin_interface::getCurrentLayerProperties(int *c, QString *w, QString *t){
1147     RS_Pen pen = docGr->getActiveLayer()->getPen();
1148     *c = pen.getColor().toIntColor();
1149 //    RS_Color col = pen.getColor();
1150 //    c->setRgb(col.red(), col.green(), col.blue());
1151     w->clear();
1152     w->append(Converter.lw2str(pen.getWidth()));
1153     t->clear();
1154     t->append(Converter.lt2str(pen.getLineType()));
1155 }
1156 
setCurrentLayerProperties(int c,DPI::LineWidth w,DPI::LineType t)1157 void Doc_plugin_interface::setCurrentLayerProperties(int c, DPI::LineWidth w, DPI::LineType t){
1158     RS_Layer* layer = docGr->getActiveLayer();
1159 	if (layer) {
1160         RS_Color co;
1161         co.fromIntColor(c);
1162         RS_Pen pen(co, static_cast<RS2::LineWidth>(w), static_cast<RS2::LineType>(t));
1163 //        RS_Pen pen(RS_Color(c), static_cast<RS2::LineWidth>(w), static_cast<RS2::LineType>(t));
1164         layer->setPen(pen);
1165     }
1166 }
1167 
setCurrentLayerProperties(int c,QString const & w,QString const & t)1168 void Doc_plugin_interface::setCurrentLayerProperties(int c, QString const& w,
1169 													 QString const& t){
1170     RS_Layer* layer = docGr->getActiveLayer();
1171 	if (layer) {
1172         RS_Color co;
1173         co.fromIntColor(c);
1174         RS_Pen pen(co, Converter.str2lw(w), Converter.str2lt(t));
1175 //        RS_Pen pen(RS_Color(c), Converter.str2lw(w), Converter.str2lt(t));
1176         layer->setPen(pen);
1177     }
1178 }
1179 
getPoint(QPointF * point,const QString & message,QPointF * base)1180 bool Doc_plugin_interface::getPoint(QPointF *point, const QString& message,
1181 									QPointF *base){
1182     bool status = false;
1183     QC_ActionGetPoint* a = new QC_ActionGetPoint(*doc, *gView);
1184     if (a) {
1185         if (!(message.isEmpty()) ) a->setMessage(message);
1186         gView->killAllActions();
1187         gView->setCurrentAction(a);
1188         if (base) a->setBasepoint(base);
1189         QEventLoop ev;
1190         while (!a->isCompleted()) {
1191             ev.processEvents ();
1192             if (!gView->getEventHandler()->hasAction())
1193                 break;
1194         }
1195         if (a->isCompleted() && !a->wasCanceled())
1196         {
1197             a->getPoint(point);
1198             status = true;
1199         }
1200         //RLZ: delete QC_ActionGetPoint. Investigate how to kill only this action
1201         gView->killAllActions();
1202     }
1203     return status;
1204 }
1205 
getEnt(const QString & message)1206 Plug_Entity *Doc_plugin_interface::getEnt(const QString& message){
1207     QC_ActionGetEnt* a = new QC_ActionGetEnt(*doc, *gView);
1208     if (a) {
1209         if (!(message.isEmpty()) )
1210             a->setMessage(message);
1211         gView->killAllActions();
1212         gView->setCurrentAction(a);
1213         QEventLoop ev;
1214         while (!a->isCompleted())
1215         {
1216             ev.processEvents ();
1217             if (!gView->getEventHandler()->hasAction())
1218                 break;
1219         }
1220     }
1221     Plug_Entity *e = reinterpret_cast<Plug_Entity*>(a->getSelected(this));
1222     a->finish();
1223     gView->killAllActions();
1224     return e;
1225 }
1226 
getSelect(QList<Plug_Entity * > * sel,const QString & message)1227 bool Doc_plugin_interface::getSelect(QList<Plug_Entity *> *sel, const QString& message){
1228     bool status = false;
1229     QC_ActionGetSelect* a = new QC_ActionGetSelect(*doc, *gView);
1230     if (a) {
1231         if (!(message.isEmpty()) )
1232             a->setMessage(message);
1233         gView->killAllActions();
1234         gView->setCurrentAction(a);
1235         QEventLoop ev;
1236         while (!a->isCompleted())
1237         {
1238             ev.processEvents ();
1239             if (!gView->getEventHandler()->hasAction())
1240                 break;
1241         }
1242         // qDebug() << "getSelect: passed event loop";
1243     }
1244 //    check if a are cancelled by the user issue #349
1245     RS_EventHandler* eh = gView->getEventHandler();
1246     if (eh && eh->isValid(a) ) {
1247         a->getSelected(sel, this);
1248         status = true;
1249     }
1250     gView->killAllActions();
1251     return status;
1252 
1253 }
1254 
getAllEntities(QList<Plug_Entity * > * sel,bool visible)1255 bool Doc_plugin_interface::getAllEntities(QList<Plug_Entity *> *sel, bool visible){
1256     bool status = false;
1257 
1258 	for(auto e: *doc){
1259 
1260         if (e->isVisible() || !visible) {
1261             Plugin_Entity *pe = new Plugin_Entity(e, this);
1262             sel->append(reinterpret_cast<Plug_Entity*>(pe));
1263         }
1264     }
1265     status = true;
1266     return status;
1267 }
1268 
getVariableInt(const QString & key,int * num)1269 bool Doc_plugin_interface::getVariableInt(const QString& key, int *num){
1270     if( (*num = docGr->getVariableInt(key, 0)) )
1271         return true;
1272     else
1273         return false;
1274 }
1275 
getVariableDouble(const QString & key,double * num)1276 bool Doc_plugin_interface::getVariableDouble(const QString& key, double *num){
1277     if( (*num = docGr->getVariableDouble(key, 0.0)) )
1278         return true;
1279     else
1280         return false;
1281 }
1282 
addVariable(const QString & key,int value,int code)1283 bool Doc_plugin_interface::addVariable(const QString& key, int value, int code){
1284     docGr->addVariable(key, value, code);
1285     if (key.startsWith("$DIM"))
1286         doc->updateDimensions(true);
1287     return true;
1288 }
1289 
addVariable(const QString & key,double value,int code)1290 bool Doc_plugin_interface::addVariable(const QString& key, double value, int code){
1291    docGr->addVariable(key, value, code);
1292    if (key.startsWith("$DIM"))
1293        doc->updateDimensions(true);
1294    return true;
1295 }
1296 
getInt(int * num,const QString & message,const QString & title)1297 bool Doc_plugin_interface::getInt(int *num, const QString& message, const QString& title){
1298     bool ok;
1299     QString msg, tit;
1300     if ( message.isEmpty() )
1301         msg = QObject::tr("enter an integer number");
1302     else
1303         msg = message;
1304     if ( title.isEmpty() )
1305         tit = QObject::tr("LibreCAD query");
1306     else
1307         tit = title;
1308 
1309     int data = QInputDialog::getInt(main_window, tit, msg, 0, -2147483647, 2147483647, 1, &ok);
1310 
1311     if (ok)
1312         *num = data;
1313     return ok;
1314 }
getReal(qreal * num,const QString & message,const QString & title)1315 bool Doc_plugin_interface::getReal(qreal *num, const QString& message, const QString& title){
1316     bool ok;
1317     QString msg, tit;
1318     if ( message.isEmpty() )
1319         msg = QObject::tr("enter a number");
1320     else
1321         msg = message;
1322     if ( title.isEmpty() )
1323         tit = QObject::tr("LibreCAD query");
1324     else
1325         tit = title;
1326 
1327     double data = QInputDialog::getDouble(main_window, tit, msg, 0, -2147483647, 2147483647, 4, &ok);
1328     if (ok )
1329         *num = data;
1330     return ok;
1331 }
getString(QString * txt,const QString & message,const QString & title)1332 bool Doc_plugin_interface::getString(QString *txt, const QString& message, const QString& title){
1333     bool ok;
1334     QString msg, tit;
1335     if ( message.isEmpty() )
1336         msg = QObject::tr("enter text");
1337     else
1338         msg = message;
1339     if ( title.isEmpty() )
1340         tit = QObject::tr("LibreCAD query");
1341     else
1342         tit = title;
1343 
1344     QString text = QInputDialog::getText(main_window, tit,msg, QLineEdit::Normal,
1345                                          QString(), &ok);
1346     if (ok && !text.isEmpty()) {
1347         txt->clear();
1348         txt->append(text);
1349     }
1350     return ok;
1351 }
1352 
realToStr(const qreal num,const int units,const int prec)1353 QString Doc_plugin_interface::realToStr(const qreal num, const int units, const int prec){
1354     RS2::LinearFormat lf;
1355     int pr = prec;
1356     if (pr == 0)
1357         pr = docGr->getLinearPrecision();
1358 
1359     switch (units){
1360     case 0:
1361         lf = docGr->getLinearFormat();
1362         break;
1363     case 1:
1364         lf = RS2::Scientific;
1365         break;
1366     case 3:
1367         lf = RS2::Engineering;
1368         break;
1369     case 4:
1370         lf = RS2::Architectural;
1371         break;
1372     case 5:
1373         lf = RS2::Fractional;
1374         break;
1375     case 6:
1376         lf = RS2::ArchitecturalMetric;
1377         break;
1378     default:
1379         lf = RS2::Decimal;
1380     }
1381 
1382     QString msg = RS_Units::formatLinear(num,RS2::None,lf,pr);
1383     return msg;
1384 }
1385