/*************************************************************************** * Copyright (c) 2012 Joe Dowsett * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ # include #endif #include "TaskOrthoViews.h" #include "ui_TaskOrthoViews.h" #include #include #include #include #include #include #include #include #include using namespace Gui; using namespace DrawingGui; using namespace std; #if 0 // needed for Qt's lupdate utility qApp->translate("QObject", "Front"); qApp->translate("QObject", "Back"); qApp->translate("QObject", "Right"); qApp->translate("QObject", "Left"); qApp->translate("QObject", "Top"); qApp->translate("QObject", "Bottom"); #endif QString number_to_name(int j) { char * temp[] = {"Front","Right","Back","Left","Top","Bottom"}; QString translated = QObject::tr(temp[j]); return translated; } void rotate_coords(float& x, float& y, int i) { float temp[4][2] = { { x, y}, {-y, x}, {-x,-y}, { y,-x} }; float t1 = temp[i][0]; float t2 = temp[i][1]; x = t1; y = t2; } void rotate_coords(int& x, int& y, int i) { int temp[4][2] = { { x, y}, {-y, x}, {-x,-y}, { y,-x} }; int t1 = temp[i][0]; int t2 = temp[i][1]; x = t1; y = t2; } orthoView::orthoView(std::string name, const char * targetpage, const char * sourcepart, Base::BoundBox3d partbox) { myname = name; mybox = partbox; orientation = 0; angle = 0; pageX = 0; pageY = 0; scale = 1; x = 0; y = 0; dir = 0; angle = 0; active = true; Command::doCommand(Command::Doc,"App.activeDocument().addObject('Drawing::FeatureViewPart','%s')",myname.c_str()); Command::doCommand(Command::Doc,"App.activeDocument().%s.Source = App.activeDocument().%s",myname.c_str(), sourcepart); Command::doCommand(Command::Doc,"App.activeDocument().%s.addObject(App.activeDocument().%s)",targetpage,myname.c_str()); Command::doCommand(Command::Doc,"App.activeDocument().%s.Direction = (1,0,0)",myname.c_str()); activate(false); } orthoView::~orthoView() { } void orthoView::deleteme() { Command::doCommand(Command::Doc,"App.activeDocument().removeObject('%s')", myname.c_str()); } void orthoView::activate(bool state) { if (state) { active = true; Command::doCommand(Command::Doc,"Gui.ActiveDocument.getObject('%s').Visibility = True", myname.c_str()); //Visibility doesn't seem to work, workaround (to counter any problems caused by active = false workaround): //setPos(); } else { active = false; Command::doCommand(Command::Doc,"Gui.ActiveDocument.getObject('%s').Visibility = False", myname.c_str()); //Visibility doesn't seem to work, workaround: Command::doCommand(Command::Doc,"App.activeDocument().%s.X = -10000", myname.c_str()); Command::doCommand(Command::Doc,"App.activeDocument().%s.Y = -10000", myname.c_str()); dir = 0; width = 0; height = 0; } } void orthoView::setDir(int i) { dir = i; int vx = (dir == 1) - (dir == 3); int vy = (dir == 0) - (dir == 2); int vz = (dir == 4) - (dir == 5); //drawings default to funny orientations for each view, line below calculates rotation to correct this //drawing will then be oriented correctly for it being primary view, setOrientation is used to modify this for secondary views. angle = -90*vx - 90*vy + (vz == -1)*180; calcCentre(); if (active) { Command::doCommand(Command::Doc,"App.activeDocument().%s.Direction = (%d,%d,%d)",myname.c_str(),vx,vy,vz); Command::doCommand(Command::Doc,"App.activeDocument().%s.Label = '%s'",myname.c_str(),number_to_name(i).toStdString().c_str()); } } void orthoView::setPos(float px, float py) { if (px != 0 && py !=0) { pageX = px; pageY = py; } float ox = pageX + x; float oy = pageY + y; if (active) { Command::doCommand(Command::Doc,"App.activeDocument().%s.X = %f", myname.c_str(), ox); Command::doCommand(Command::Doc,"App.activeDocument().%s.Y = %f", myname.c_str(), oy); } } void orthoView::setScale(float newScale) { scale = newScale; if (active) Command::doCommand(Command::Doc,"App.activeDocument().%s.Scale = %f",myname.c_str(), scale); calcCentre(); } void orthoView::setOrientation(int orient) { orientation = orient; if (active) Command::doCommand(Command::Doc,"App.activeDocument().%s.Rotation = %d", myname.c_str(), (90*orientation+angle)); calcCentre(); } void orthoView::calcCentre() { //the drawing view 'Position' refers to where the part origin should be on the page //we need to find the position of the centre of correct bounding box face relative to the part origin //this depends upon: // - which view (eg Front, Left, Top etc), given by 'dir' // - the scale of the drawing, since eg centre.x is the absolute point, while x is the distance on page. // - the orientation of the view on the page, will switch x/y as per a rotation. float cx = mybox.CalcCenter().x; float cy = mybox.CalcCenter().y; float cz = mybox.CalcCenter().z; float coords[6][2] = { {-cx, cz}, //front { cy, cz}, //right { cx, cz}, //back {-cy, cz}, //left {-cx, -cy}, //top {-cx, cy} //bottom }; x = coords[dir][0] * scale; y = coords[dir][1] * scale; rotate_coords(x,y,orientation); float dx = mybox.LengthX(); float dy = mybox.LengthY(); float dz = mybox.LengthZ(); float dims[6][2] = { {dx, dz}, //front {dy, dz}, //right {dx, dz}, //back {dy, dz}, //left {dx, dy}, //top {dx, dy} //bottom }; width = dims[dir][0]; height = dims[dir][1]; if (orientation % 2 == 1) { float temp = width; width = height; height = temp; } } void orthoView::hidden(int state) { if (state == 2) Command::doCommand(Command::Doc,"App.activeDocument().%s.ShowHiddenLines = True", myname.c_str()); else Command::doCommand(Command::Doc,"App.activeDocument().%s.ShowHiddenLines = False", myname.c_str()); } void orthoView::smooth(int state) { if (state == 2) Command::doCommand(Command::Doc,"App.activeDocument().%s.ShowSmoothLines = True", myname.c_str()); else Command::doCommand(Command::Doc,"App.activeDocument().%s.ShowSmoothLines = False", myname.c_str()); } /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// TaskOrthoViews::TaskOrthoViews(QWidget *parent) : ui(new Ui_TaskOrthoViews) { ui->setupUi(this); std::vector obj = Gui::Selection().getObjectsOfType(Part::Feature::getClassTypeId()); Base::BoundBox3d bbox; std::vector::iterator it = obj.begin(); bbox.Add(static_cast(*it)->Shape.getBoundingBox()); const char * part = obj.front()->getNameInDocument(); App::Document* doc = App::GetApplication().getActiveDocument(); std::vector pages = doc->getObjectsOfType(Drawing::FeaturePage::getClassTypeId()); std::string PageName = pages.front()->getNameInDocument(); const char * page = PageName.c_str(); App::DocumentObject * this_page = doc->getObject(page); std::string template_name = static_cast(this_page)->Template.getValue(); std::string name1 = doc->getUniqueObjectName("Ortho").c_str(); views[0] = new orthoView(name1, page, part, bbox); name1 = doc->getUniqueObjectName("Ortho").c_str(); views[1] = new orthoView(name1, page, part, bbox); name1 = doc->getUniqueObjectName("Ortho").c_str(); views[2] = new orthoView(name1, page, part, bbox); name1 = doc->getUniqueObjectName("Ortho").c_str(); views[3] = new orthoView(name1, page, part, bbox); margin = 10; pagesize(template_name); min_space = 15; // [x+2][y+2] c_boxes[0][2] = ui->cb02; //left most, x = -2, y = 0 c_boxes[1][1] = ui->cb11; c_boxes[1][2] = ui->cb12; c_boxes[1][3] = ui->cb13; c_boxes[2][0] = ui->cb20; //top most, x = 0, y = -2 c_boxes[2][1] = ui->cb21; c_boxes[2][2] = ui->cb22; //centre (primary view) checkbox x = y = 0. c_boxes[2][3] = ui->cb23; c_boxes[2][4] = ui->cb24; //bottom most, x = 0, y = 2 c_boxes[3][1] = ui->cb31; c_boxes[3][2] = ui->cb32; c_boxes[3][3] = ui->cb33; c_boxes[4][2] = ui->cb42; //right most, x = 2, y = 0 for (int i=0; i < 5; i++) for (int j=0; j < 5; j++) if ((abs(i-2) + abs(j-2)) < 3) //if i,j combination corresponds to valid check box, then proceed with: connect(c_boxes[i][j], SIGNAL(toggled(bool)), this, SLOT(cb_toggled(bool))); inputs[0] = ui->scale_0; inputs[1] = ui->x_1; inputs[2] = ui->y_2; inputs[3] = ui->spacing_h_3; inputs[4] = ui->spacing_v_4; for (int i=0; i < 5; i++) connect(inputs[i], SIGNAL(editingFinished()), this, SLOT(data_entered())); connect(ui->projection, SIGNAL(currentIndexChanged(int)), this, SLOT(projectionChanged(int))); connect(ui->rotate, SIGNAL(currentIndexChanged(int)), this, SLOT(setRotate(int))); connect(ui->smooth, SIGNAL(stateChanged(int)), this, SLOT(smooth(int))); connect(ui->hidden, SIGNAL(stateChanged(int)), this, SLOT(hidden(int))); connect(ui->auto_tog, SIGNAL(stateChanged(int)), this, SLOT(toggle_auto(int))); connect(ui->primary, SIGNAL(activated(int)), this, SLOT(setPrimary(int))); //these matrices contain information relating relative position on page to which view appears there, and in which orientation //first matrix is for front, right, back, left. Only needs to contain positions above and below primary since in positions horizontally //displaced, the view appearing there is simply found from the same f, r, b, l sequence. //thus [i][j][k], i values are which primary view (0-3), j is vertical displacement corresponding to (-2/+2, -1, 1) //then in k = 0 is the view number, k = 1 is the orientation (*90 clockwise) //second matrix is for primaries top (4), i=0 gives horizontal positions, i = 1 vertical ones //and bottom (5) i = 2 (horiz) and 3 (vert). //then j and k values as for first matrix. int temp1[4][3][2] = {{{2,2}, {4,0}, {5,0}}, //primary 0, secondary {direction, rotation} in y = -2, -1, 1 positions {{3,2}, {4,1}, {5,3}}, //primary 1, secondaries in y = 2 position duplicate y = -2 {{0,2}, {4,2}, {5,2}}, //primary 2, secondaries in horizontal positions x = -2, -1, 1, 2 {{1,2}, {4,3}, {5,1}}}; //primary 3, given by linear position from primary = (p + x) mod 4 int temp2[4][3][2] = {{{5,2}, {3,1}, {1,3}}, //primary 4, secondaries in horizontal x = -2, -1, 1 (x = 2 duplicates x = -2) {{5,0}, {2,2}, {0,0}}, //primary 4, vertical positions {{4,2}, {3,3}, {1,1}}, //primary 5, horizontal {{4,0}, {0,0}, {2,2}}}; //primary 5, vertical for (int i=0; i < 4; i++) for (int j=0; j < 3; j++) for (int k=0; k < 2; k++) //initialisation needs to be done this way (rather than initialise maps directly { map1[i][j][k] = temp1[i][j][k]; //in order to avoid compiler warning map2[i][j][k] = temp2[i][j][k]; } //initialise variables for (int i=0; i < 4; i++) for (int j=0; j < 4; j++) view_status[i][j] = 0; view_count = 0; primary = 0; rotate = 0; proj = 1; autoscale = 1; //below are calculated in case autodims is deselected before these values are initialised. float max_dim = max(max(bbox.LengthX(), bbox.LengthY()), bbox.LengthZ()); scale = min(pagewidth, pageheight)/(4*max_dim+5*min_space); horiz = scale*max_dim + min_space; vert = horiz; x_pos = pagewidth/2; y_pos = pageheight/2; data[0] = &scale; data[1] = &x_pos; data[2] = &y_pos; data[3] = &horiz; data[4] = | // Command::doCommand(Command::Doc,"#%d", map1[2][2][1]); } //end of constructor TaskOrthoViews::~TaskOrthoViews() { delete views[0]; delete views[1]; delete views[2]; delete views[3]; delete ui; } void TaskOrthoViews::changeEvent(QEvent *e) { if (e->type() == QEvent::LanguageChange) { ui->retranslateUi(this); } } void TaskOrthoViews::pagesize(std::string& page_template) { /********update num_templates when adding extra templates*******************/ const int num_templates = 2; std::string templates[num_templates] = {"A3_Landscape.svg", "A4_Landscape.svg"}; int dimensions[num_templates][3] = {{420,297,227},{297,210,153}}; //{width, full height, reduced height} measured from page edge. for (int i=0; i < num_templates; i++) { if (templates[i] == page_template) { pagewidth = dimensions[i][0] - 2*margin; pageh1 = dimensions[i][1] - 2*margin; pageh2 = dimensions[i][2] - margin; return; } } //matching template not found, read through template file for width & height info. //code below copied from FeaturePage.cpp Base::FileInfo fi(page_template); if (!fi.isReadable()) { fi.setFile(App::Application::getResourceDir() + "Mod/Drawing/Templates/" + fi.fileName()); if (!fi.isReadable()) //if so then really shouldn't have been able to get this far, but just in case... { pagewidth = 277; pageh1 = 190; pageh2 = 190; return; } } // open Template file std::string line; std::string temp_line; std::ifstream file (fi.filePath().c_str()); size_t found; bool done = false; try { while (!file.eof()) { getline (file,line); found = line.find("width="); if (found != std::string::npos) { temp_line = line.substr(7+found); sscanf (temp_line.c_str(), "%f", &pagewidth); pagewidth -= 2*margin; if (done) { file.close(); return; } else done = true; } found = line.find("height="); if (found != std::string::npos) { temp_line = line.substr(8+found); sscanf (temp_line.c_str(), "%f", &pageh1); pageh1 -= 2*margin; pageh2 = pageh1; if (done) { file.close(); return; } else done = true; } if (line.find("metadata") != std::string::npos) //give up if we meet a metadata tag break; } } catch (Standard_Failure) { } file.close(); //width/height not found?? fallback to A4 landscape simple: pagewidth = 277; pageh1 = 190; pageh2 = 190; } void TaskOrthoViews::autodims() { /************************************* calculate real size of views in layout *****************/ float w1 = 0, w2 = 0, h1 = 0, h2 = 0; int min_x = 0, min_y = 0; int max_x = 0, max_y = 0; w1 = views[0]->width; //w1,h1 are width/height of primary view h1 = views[0]->height; //w2 width of first view left/right of primary, h2 height of first view up/down for (int i = 0; i < 4; i++) { min_x = min(min_x, view_status[i][2]); min_y = min(min_y, view_status[i][3]); max_x = max(max_x, view_status[i][2]); max_y = max(max_y, view_status[i][3]); if (abs(view_status[i][2]) == 1 && abs(view_status[i][3]) == 0) w2 = views[i]->width; else if (abs(view_status[i][2]) == 0 && abs(view_status[i][3]) == 1) h2 = views[i]->height; } float width = (min_x == -2)*w1 + (min_x < 0)*w2 + w1 + (max_x > 0)*w2 + (max_x == 2) * w1; float height = (min_y == -2)*h1 + (min_y < 0)*h2 + h1 + (max_y > 0)*h2 + (max_y == 2) * h1; int wide = max_x - min_x + 1; //how many views wide / high? int high = max_y - min_y + 1; if (max_y > 0 && !c_boxes[3][3]->isChecked() && min_x == 0 && ((max_x == 1)*w2 > w1 || max_x == 2)) pageheight = pageh1; else pageheight = pageh2; /*************************************** calculate scale **************************************/ float working_scale = min((pagewidth - (wide + 1) * min_space) / width, (pageheight - (high + 1) * min_space) / height); //which gives the largest scale for which the min_space requirements can be met, but we want a 'sensible' scale, rather than 0.28457239... //eg if working_scale = 0.115, then we want to use 0.1, similarly 7.65 -> 5, and 76.5 -> 50 float exponent = floor(log10(working_scale)); //if working_scale = a * 10^b, what is b? working_scale *= pow(10, -exponent); //now find what 'a' is. float valid_scales[2][8] = {{1, 1.25, 2, 2.5, 3.75, 5, 7.5, 10}, //equate to 1:10, 1:8, 1:5, 1:4, 3:8, 1:2, 3:4, 1:1 {1, 1.5, 2, 3, 4, 5, 8, 10}}; //equate to 1:1, 3:2, 2:1, 3:1, 4:1, 5:1, 8:1, 10:1 int i = 0; while (valid_scales[(exponent>=0)][i] <= working_scale) //choose closest value smaller than 'a' from list. i += 1; //choosing top list if exponent -ve, bottom list for +ve exponent i -= 1; float chosen_scale = valid_scales[(exponent>=0)][i]; scale = chosen_scale * pow(10, exponent); //now have the appropriate scale, reapply the *10^b /************************************* calculate position of views on page ********************/ width *= scale; height *= scale; w1 *= scale; w2 *= scale; h1 *= scale; h2 *= scale; float space = min((pagewidth - width)/(wide + 1), (pageheight - height)/(high + 1)); vert = space + (h1 + h2)/2; //centre-centre spacing of views horiz = space + (w1 + w2)/2; float left = -min_x * horiz + (min_x == -1) * w2/2 + (min_x != -1) * w1/2; //width of layout left of primary centre float right = max_x * horiz + (max_x == 1) * w2/2 + (max_x != 1) * w1/2; // " " right " " float up = -min_y * vert + (min_y == -1) * h2/2 + (min_y != -1) * h1/2; float down = max_y * vert + (max_y == 1) * h2/2 + (max_y != 1) * h1/2; x_pos = pagewidth/2 + margin - (right-left)/2; y_pos = pageheight/2 + margin - (down-up)/2; x_pos = floor(x_pos * 10 + 0.5) / 10; //round to nearest tenth y_pos = floor(y_pos * 10 + 0.5) / 10; horiz = floor(horiz * 10 + 0.5) / 10; vert = floor(vert * 10 + 0.5) / 10; /************************************* update gui text boxes **********************************/ for (int i = 0; i < 5; i++) inputs[i]->setText(QString::number(*data[i])); } void TaskOrthoViews::compute() { if (autoscale) autodims(); for (int i = 0; i < 4; i++) { views[i]->setScale(scale); views[i]->setPos(x_pos + view_status[i][2] * horiz, y_pos + view_status[i][3] * vert); } Command::updateActive(); Command::commitCommand(); } void TaskOrthoViews::validate_cbs() { for (int i=0; i < 5; i++) { for (int j=0; j < 5; j++) { if ((abs(i-2) + abs(j-2)) < 3) { //if i,j combination corresponds to valid check box, then proceed with: if (view_count == 0) { c_boxes[i][j]->setEnabled(false); c_boxes[i][j]->setChecked(false); } else if (!c_boxes[i][j]->isChecked()) { //only questions boxes 'enableability' if it's not checked if (view_count == 4) { c_boxes[i][j]->setEnabled(false); //if there are four checked boxes then all others are disabled } else { if ((abs(i-2) + abs(j-2)) == 1) { //only true for boxes immediately up/down/left/right of centre c_boxes[i][j]->setEnabled(c_boxes[2][2]->isChecked()); //which are enabled if centre box is checked } else { int di = ((i-2) < 0) - ((i-2) > 0); //which direction is towards centre? int dj = ((j-2) < 0) - ((j-2) > 0); if (c_boxes[i+di][j]->isChecked() + c_boxes[i][j+dj]->isChecked() + (di == 0) + (dj == 0) == 2) { if (!((i == 2)*(j == 2))) //don't enable the centre one! /********temporary if statement here, remove the following if to renable 'diagonal' checkboxes *******/ if ((i-2) * (j-2) == 0) c_boxes[i][j]->setEnabled(true); //if this box's inner neighbour(s) are checked, then this one enabled } else c_boxes[i][j]->setEnabled(false); } } } } } } } void TaskOrthoViews::cb_toggled(bool toggle) { QString name = sender()->objectName().right(2); char letter = name.toStdString()[0]; int dx = letter - '0' - 2; letter = name.toStdString()[1]; int dy = letter - '0' - 2; int i = 0; if (toggle) { for (i = 0; i < 4; i++) { if (view_status[i][0] == 0) break; } int direction, rotation; view_data(dx, dy, direction, rotation); view_status[i][0] = 1; view_status[i][2] = dx; view_status[i][3] = dy; views[i]->activate(true); views[i]->setDir(direction); views[i]->setOrientation(rotation); view_count += 1; } else { if (abs(dx) == 1 || abs(dy == 1)) c_boxes[dx*2+2][dy*2+2]->setChecked(false); for (i = 0; i < 4; i++) { if (view_status[i][2] == dx && view_status[i][3] == dy) break; } views[i]->activate(false); view_status[i][0] = 0; view_status[i][2] = 0; view_status[i][3] = 0; view_count -= 1; } validate_cbs(); compute(); } void TaskOrthoViews::view_data(int x, int y, int & direction, int & rotation) { int arr_index; rotate_coords(x,y,(4-rotate)%4); x = x * proj; y = y * proj; if (primary < 4) { if (y == 0) { rotation = rotate; direction = (primary + x + 4) % 4; } else { arr_index = (y + 2 - (y > 0)) % 3; //maps (-2,-1,1,2) to (0,1,2,0) direction = map1[primary][arr_index][0]; rotation = (map1[primary][arr_index][1] + rotate) % 4; } } else { int offset = (y != 0); arr_index = (x == 0)*(y + 2 - (y > 0)) % 3 + (y == 0)*(x + 2 - (x > 0)) % 3; direction = map2[2*(primary == 5) + offset][arr_index][0]; rotation = (map2[2*(primary == 5) + offset][arr_index][1] + rotate) % 4; } } void TaskOrthoViews::projectionChanged(int index) { proj = 2*(0.5-index); //gives -1 for 1st angle and 1 for 3rd updateSecondaries(); compute(); } void TaskOrthoViews::setRotate(int r) { rotate = r; views[0]->setOrientation(rotate); updateSecondaries(); compute(); } void TaskOrthoViews::updateSecondaries() { int direction, rotation; int dx, dy; for (int i = 1; i < 4; i++) if (view_status[i][0] == 1) { dx = view_status[i][2]; dy = view_status[i][3]; view_data(dx, dy, direction, rotation); views[i]->setDir(direction); views[i]->setOrientation(rotation); } } void TaskOrthoViews::setPrimary(int dir) { if (dir == 0) { for (int i = 0; i < 4; i++) { views[i]->activate(false); view_status[i][0] = 0; } view_count = 0; c_boxes[2][2]->setChecked(false); } else { c_boxes[2][2]->setChecked(true); view_count += (view_count == 0); primary = dir-1; view_status[0][0] = 1; views[0]->setDir(primary); views[0]->setOrientation(rotate); views[0]->activate(true); updateSecondaries(); compute(); } validate_cbs(); } void TaskOrthoViews::hidden(int i) { views[0]->hidden(i); views[1]->hidden(i); views[2]->hidden(i); views[3]->hidden(i); Command::updateActive(); Command::commitCommand(); } void TaskOrthoViews::smooth(int i) { views[0]->smooth(i); views[1]->smooth(i); views[2]->smooth(i); views[3]->smooth(i); Command::updateActive(); Command::commitCommand(); } void TaskOrthoViews::toggle_auto(int i) { if (i == 2) //auto scale switched on { autoscale = true; ui->label_4->setEnabled(false); ui->label_5->setEnabled(false); ui->label_6->setEnabled(false); for (int j = 0; j < 5; j++) inputs[j]->setEnabled(false); //disable user input boxes compute(); } else { autoscale = false; ui->label_4->setEnabled(true); ui->label_5->setEnabled(true); ui->label_6->setEnabled(true); for (int j = 0; j < 5; j++) inputs[j]->setEnabled(true); //enable user input boxes } } void TaskOrthoViews::data_entered() { Command::doCommand(Command::Doc,"#1"); bool ok; QString name = sender()->objectName().right(1); char letter = name.toStdString()[0]; int index = letter - '0'; float value = inputs[index]->text().toFloat(&ok); if (ok) *data[index] = value; else { inputs[index]->setText(QString::number(*data[index])); return; } compute(); Command::doCommand(Command::Doc,"#2"); } bool TaskOrthoViews::user_input() { //if user presses return, this is intercepted by FreeCAD which interprets it as activating the 'OK' button //if return was pressed in a text box though, we don't want it to do 'OK', so check to see if a text box has been modified. bool modified = false; for (int i = 0; i < 5; i++) { modified = inputs[i]->isModified(); //has input box been modified? if (modified) { inputs[i]->setModified(false); //reset modified flag break; //stop checking } } return modified; } void TaskOrthoViews::clean_up(bool keep) { if (keep) //user ok-ed the drawing { if (!views[0]->active) views[0]->deleteme(); if (!views[1]->active) views[1]->deleteme(); if (!views[2]->active) views[2]->deleteme(); if (!views[3]->active) views[3]->deleteme(); } else //user cancelled the drawing { views[0]->deleteme(); views[1]->deleteme(); views[2]->deleteme(); views[3]->deleteme(); } } //************************************************************************** //************************************************************************** // TaskDialog //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TaskDlgOrthoViews::TaskDlgOrthoViews() : TaskDialog() { widget = new TaskOrthoViews(); taskbox = new Gui::TaskView::TaskBox( Gui::BitmapFactory().pixmap("actions/drawing-orthoviews"), widget->windowTitle(), true, 0); taskbox->groupLayout()->addWidget(widget); Content.push_back(taskbox); } TaskDlgOrthoViews::~TaskDlgOrthoViews() { } //==== calls from the TaskView =============================================================== void TaskDlgOrthoViews::open() { } void TaskDlgOrthoViews::clicked(int) { } bool TaskDlgOrthoViews::accept() { bool check = widget->user_input(); if (!check) widget->clean_up(true); return !check; } bool TaskDlgOrthoViews::reject() { widget->clean_up(false); return true; } #include "moc_TaskOrthoViews.cpp"