diff --git a/src/Mod/Drawing/App/FeatureViewPart.cpp b/src/Mod/Drawing/App/FeatureViewPart.cpp
index c1d7527dad86..ec100db5791f 100644
--- a/src/Mod/Drawing/App/FeatureViewPart.cpp
+++ b/src/Mod/Drawing/App/FeatureViewPart.cpp
@@ -194,7 +194,7 @@ App::DocumentObjectExecReturn *FeatureViewPart::execute(void)
bool smooth = ShowSmoothLines.getValue();
try {
- ProjectionAlgos Alg(ProjectionAlgos::invertY(shape),Dir);
+ ProjectionAlgos Alg(shape,Dir);
result << "" << endl
<< output.exportEdges(H)
<< "" << endl;
@@ -169,14 +178,15 @@ std::string ProjectionAlgos::getSVG(ExtractionType type, double scale, double to
if (!HO.IsNull() && (type & WithHidden)) {
double width = hiddenscale;
BRepMesh::Mesh(HO,tolerance);
- result << "" << endl
<< output.exportEdges(HO)
<< "" << endl;
@@ -184,13 +194,14 @@ std::string ProjectionAlgos::getSVG(ExtractionType type, double scale, double to
if (!VO.IsNull()) {
double width = scale;
BRepMesh::Mesh(VO,tolerance);
- result << "" << endl
<< output.exportEdges(VO)
<< "" << endl;
@@ -198,13 +209,14 @@ std::string ProjectionAlgos::getSVG(ExtractionType type, double scale, double to
if (!V.IsNull()) {
double width = scale;
BRepMesh::Mesh(V,tolerance);
- result << "" << endl
<< output.exportEdges(V)
<< "" << endl;
@@ -212,13 +224,14 @@ std::string ProjectionAlgos::getSVG(ExtractionType type, double scale, double to
if (!V1.IsNull() && (type & WithSmooth)) {
double width = scale;
BRepMesh::Mesh(V1,tolerance);
- result << "" << endl
<< output.exportEdges(V1)
<< "" << endl;
@@ -226,14 +239,15 @@ std::string ProjectionAlgos::getSVG(ExtractionType type, double scale, double to
if (!H1.IsNull() && (type & WithSmooth) && (type & WithHidden)) {
double width = hiddenscale;
BRepMesh::Mesh(H1,tolerance);
- result << "" << endl
<< output.exportEdges(H1)
<< "" << endl;
@@ -247,7 +261,7 @@ std::string ProjectionAlgos::getDXF(ExtractionType type, double scale, double to
{
std::stringstream result;
DXFOutput output;
-
+
result << "0" << endl
<< "SECTION" << endl
@@ -257,9 +271,9 @@ std::string ProjectionAlgos::getDXF(ExtractionType type, double scale, double to
if (!H.IsNull() && (type & WithHidden)) {
//float width = 0.15f/scale;
BRepMesh::Mesh(H,tolerance);
- result //<< " *
+ * Copyright (c) 2014 Joe Dowsett *
* *
* This file is part of the FreeCAD CAx development system. *
* *
@@ -22,814 +22,924 @@
#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;
+#ifndef PI
+ #define PI 3.14159265358979323846 /* pi */
+#endif
+
#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");
+ qApp->translate("QObject", "Make axonometric...");
+ qApp->translate("QObject", "Edit axonometric settings...");
+ qApp->translate("QObject", "Make orthographic");
#endif
-QString number_to_name(int j)
+
+
+void pagesize(string & page_template, int dims[4], int block[4])
{
- char * temp[] = {"Front","Right","Back","Left","Top","Bottom","Axonometric"};
- QString translated = QObject::tr(temp[j]);
- return translated;
+ dims[0] = 10; // default to A4_Landscape with 10mm margins
+ dims[1] = 10;
+ dims[2] = 287;
+ dims[3] = 200;
+
+ block[0] = block[1] = 0; // default to no title block
+ block[2] = block[3] = 0;
+
+ int t0, t1, t2, t3 = 0;
+
+ //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...
+ return;
+ }
+
+ // open Template file
+ string line;
+ ifstream file (fi.filePath().c_str());
+
+ try
+ {
+ while (!file.eof())
+ {
+ getline (file,line);
+
+ if (line.find(""
+ getline (file,line);
+
+ if (line.find(""
+
+ break;
+ }
+
+ if (line.find("metadata") != string::npos) //give up if we meet a metadata tag
+ break;
+ }
+ }
+ catch (Standard_Failure)
+ { }
+
+ file.close();
+
+ if (t3 != 0)
+ {
+ block[2] = t2 - t0; // block width
+ block[3] = t3 - t1; // block height
+
+ if (t0 <= dims[0]) // title block on left
+ block[0] = -1;
+ else if (t2 >= dims[2]) // title block on right
+ block[0] = 1;
+
+ if (t1 <= dims[1]) // title block at top
+ block[1] = 1;
+ else if (t3 >= dims[3]) // title block at bottom
+ block[1] = -1;
+ }
+
+ dims[2] -= dims[0]; // width
+ dims[3] -= dims[1]; // height
}
-void rotate_coords(float& x, float& y, int i)
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+orthoview::orthoview(App::Document * parent, App::DocumentObject * part, App::DocumentObject * page, Base::BoundBox3d * partbox)
{
- float temp[4][2] =
- {
- { x, y},
- {-y, x},
- {-x,-y},
- { y,-x}
- };
+ parent_doc = parent;
+ myname = parent_doc->getUniqueObjectName("Ortho");
- float t1 = temp[i][0];
- float t2 = temp[i][1];
- x = t1;
- y = t2;
+ cx = partbox->CalcCenter().x;
+ cy = partbox->CalcCenter().y;
+ cz = partbox->CalcCenter().z;
+
+ this_view = static_cast (parent_doc->addObject("Drawing::FeatureViewPart", myname.c_str()));
+ static_cast(page)->addObject(this_view);
+ this_view->Source.setValue(part);
+
+ pageX = 0;
+ pageY = 0;
+ scale = 1;
+
+ rel_x = 0;
+ rel_y = 0;
+ ortho = true;
+ auto_scale = true;
}
-void rotate_coords(int& x, int& y, int i)
+
+orthoview::~orthoview()
{
- int temp[4][2] =
- {
- { x, y},
- {-y, x},
- {-x,-y},
- { y,-x}
- };
+}
+
+
+void orthoview::set_data(int r_x, int r_y)
+{
+ rel_x = r_x;
+ rel_y = r_y;
+
+ char label[15];
+ sprintf(label, "Ortho_%i_%i", rel_x, rel_y); // label name for view, based on relative position
- int t1 = temp[i][0];
- int t2 = temp[i][1];
- x = t1;
- y = t2;
+ this_view->Label.setValue(label);
+ ortho = ((rel_x * rel_y) == 0);
}
-void rotate_coords(float & x, float & y, float angle)
+
+void orthoview::deleteme()
{
- float tx = x * cos(angle) - y * sin(angle);
- y = x * sin(angle) + y * cos(angle);
- x = tx;
+ parent_doc->remObject(myname.c_str());
}
-float dot(float * r, float * z)
+
+void orthoview::setPos(float px, float py)
{
- return ( r[0]*z[0] + r[1]*z[1] + r[2]*z[2]);
+ if (px != 0 && py !=0)
+ {
+ pageX = px;
+ pageY = py;
+ }
+
+ float ox = pageX - scale * x;
+ float oy = pageY + scale * y;
+
+ this_view->X.setValue(ox);
+ this_view->Y.setValue(oy);
}
-void cross(float * r, float * n, float * p)
+
+void orthoview::setScale(float newScale)
{
- p[0] = r[1]*n[2] - r[2]*n[1];
- p[1] = r[2]*n[0] - r[0]*n[2];
- p[2] = r[0]*n[1] - r[1]*n[0];
+ scale = newScale;
+ this_view->Scale.setValue(scale);
}
-void project(float * r, float * n, float * p)
+
+float orthoview::getScale()
{
- // for r projected onto plane perpendicular to n
- // r x n is perpendicular to r and n (.: lies on plane)
- // then n x (r x n) is perpendicular to that and to n, is the projection
- float c[3];
- cross(r, n, c);
- cross(n, c, p);
+ return scale;
}
-void normalise(float * r)
+
+void orthoview::calcCentre()
{
- float m = 1/sqrt(r[0]*r[0] + r[1]*r[1] + r[2]*r[2]);
- r[0] *= m;
- r[1] *= m;
- r[2] *= m;
+ x = X_dir.X() * cx + X_dir.Y() * cy + X_dir.Z() * cz;
+ y = Y_dir.X() * cx + Y_dir.Y() * cy + Y_dir.Z() * cz;
}
+void orthoview::hidden(bool state)
+{
+ this_view->ShowHiddenLines.setValue(state);
+}
+
+void orthoview::smooth(bool state)
+{
+ this_view->ShowSmoothLines.setValue(state);
+}
-orthoView::orthoView(std::string name, const char * targetpage, const char * sourcepart, Base::BoundBox3d partbox)
+void orthoview::set_projection(gp_Ax2 cs)
{
- myname = name;
- mybox = partbox;
+ gp_Ax2 actual_cs;
+ gp_Dir actual_X;
- orientation = 0;
- angle = 0;
- pageX = 0;
- pageY = 0;
- scale = 1;
- x = 0;
- y = 0;
- dir = 0;
- active = true;
- axo = false;
+ // coord system & directions for desired projection
+ X_dir = cs.XDirection();
+ Y_dir = cs.YDirection();
+ Z_dir = cs.Direction();
+
+ // coord system of created view - same code as used in projection algos
+ actual_cs = gp_Ax2(gp_Pnt(0,0,0), gp_Dir(Z_dir.X(),Z_dir.Y(),Z_dir.Z()));
+ actual_X = actual_cs.XDirection();
- 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());
+ // angle between desired projection and actual projection
+ float rotation = X_dir.Angle(actual_X);
- activate(false);
+ if (rotation != 0 && abs(PI - rotation) > 0.05)
+ if (!Z_dir.IsEqual(actual_X.Crossed(X_dir), 0.05))
+ rotation = -rotation;
+
+ calcCentre();
+
+ this_view->Direction.setValue(Z_dir.X(), Z_dir.Y(), Z_dir.Z());
+ this_view->Rotation.setValue(180 * rotation / PI);
}
-orthoView::~orthoView()
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+OrthoViews::OrthoViews(const char * pagename, const char * partname)
{
+ page_name = pagename;
+ part_name = partname;
+
+ parent_doc = App::GetApplication().getActiveDocument();
+
+ part = parent_doc->getObject(partname);
+ bbox.Add(static_cast(part)->Shape.getBoundingBox());
+
+ page = parent_doc->getObject(pagename);
+ load_page();
+
+ min_space = 15; // should be preferenced
+
+ min_r_x = max_r_x = 0;
+ min_r_y = max_r_y = 0;
+
+ rotate_coeff = 1;
+ smooth = false;
+ hidden = false;
+ autodims = true;
}
-void orthoView::deleteme()
+OrthoViews::~OrthoViews()
{
- Command::doCommand(Command::Doc,"App.activeDocument().removeObject('%s')", myname.c_str());
+ for (int i = views.size() - 1; i >= 0; i--)
+ delete views[i];
+
+ page->recompute();
}
-void orthoView::activate(bool state)
+void OrthoViews::load_page()
{
- if (state)
+ string template_name = static_cast(page)->Template.getValue();
+ pagesize(template_name, large, block);
+ page_dims = large;
+
+ // process page dims for title block data
+ if (block[0] != 0)
{
- 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();
+ title = true;
+
+ // max vertical space avoiding title block
+ small_v[1] = large[1]; // y margin same as large page
+ small_v[3] = large[3]; // y size same as large page
+ small_v[2] = large[2] - block[2]; // x width same as large width - block width
+ if (block[0] == -1)
+ {
+ small_v[0] = large[0] + block[2]; // x margin same as large + block width
+ horiz = &min_r_x;
+ }
+ else
+ {
+ small_v[0] = large[0]; // x margin same as large
+ horiz = &max_r_x;
+ }
+
+ // max horizontal space avoiding title block
+ small_h[0] = large[0];
+ small_h[2] = large[2];
+ small_h[3] = large[3] - block[3];
+ if (block[1] == 1)
+ {
+ small_h[1] = large[1] + block[3];
+ vert = &max_r_y;
+ }
+ else
+ {
+ small_h[1] = large[1];
+ vert = &min_r_y;
+ }
}
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;
- }
+ title = false;
}
-void orthoView::setDir(int i)
+void OrthoViews::calc_layout_size() // calculate the real world size of given view layout, assuming no space
{
- axo = false;
- dir = i;
- int vx = (dir == 1) - (dir == 3);
- int vy = (dir == 0) - (dir == 2);
- int vz = (dir == 4) - (dir == 5);
+ // note that views in relative positions x = -4, -2, 0 , 2 etc etc
+ // have width = orientated part width
+ // while those in relative positions x = -3, -1, 1 etc
+ // have width = orientated part depth
- //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;
+ // similarly in y positions, height = part height or depth
+
+ layout_width = (1 + floor(max_r_x / 2.0) + floor(-min_r_x / 2.0)) * width;
+ layout_width += (ceil(max_r_x / 2.0) + ceil(-min_r_x / 2.0)) * depth;
+ layout_height = (1 + floor(max_r_y / 2.0) + floor(-min_r_y / 2.0)) * height;
+ layout_height += (ceil(max_r_y / 2.0) + ceil(-min_r_y / 2.0)) * depth;
+}
- calcCentre();
- if (active)
+void OrthoViews::choose_page() // chooses which bit of page space to use depending upon layout & titleblock
+{
+ int h = abs(*horiz); // how many views in direction of title block (horiz points to min_r_x or max_r_x)
+ int v = abs(*vert);
+ float layout_corner_width = (1 + floor(h / 2.0)) * width + ceil(h / 2.0) * depth; // from (0, 0) view inclusively, how wide and tall is the layout in the direction of the title block
+ float layout_corner_height = (1 + floor(v / 2.0)) * height + ceil(v / 2.0) * depth;
+ float rel_space_x = layout_corner_width / layout_width - 1.0 * block[2] / large[2]; // relative to respective sizes, how much space between (0, 0) and title block,
+ float rel_space_y = layout_corner_height / layout_height - 1.0 * block[3] / large[3]; // can be -ve if block extends into / beyond (0, 0) view
+ float view_x, view_y, v_x_r, v_y_r;
+ bool interferes = false;
+ float a, b;
+
+ for (int i = min_r_x; i <= max_r_x; i++)
+ for (int j = min_r_y; j <= max_r_y; j++)
+ if (index(i, j) != -1) // is there a view in this position?
+ {
+ a = i * block[0] * 0.5; // reflect i and j so as +ve is in direction of title block ##
+ b = j * block[1] * 0.5;
+ view_x = ceil(a + 0.5) * width + ceil(a) * depth; // extreme coords of view in direction of block, measured from far corner of (0, 0) view,
+ view_y = ceil(b + 0.5) * height + ceil(b) * depth; // can be -ve if view is on opposite side of (0, 0) from title block
+ v_x_r = view_x / layout_width; // make relative
+ v_y_r = view_y / layout_height;
+ if (v_x_r > rel_space_x && v_y_r > rel_space_y) // ## so that can use > in this condition regardless of position of block
+ interferes = true;
+ }
+
+ if (!interferes)
+ page_dims = large;
+ else
{
- 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(),(const char*)number_to_name(i).toUtf8());
+ if (min(small_h[2] / layout_width, small_h[3] / layout_height) > min(small_v[2] / layout_width, small_v[3] / layout_height))
+ page_dims = small_h;
+ else
+ page_dims = small_v;
}
}
-void orthoView::setDir(float vx, float vy, float vz, float ang, int vert_index)
+void OrthoViews::calc_scale() // compute scale required to meet minimum space requirements
{
- //calcCentre();
- vert[0] = 0;
- vert[1] = 0;
- vert[2] = 0;
+ float scale_x, scale_y, working_scale;
- switch(vert_index)
- {
- case 0:
- vert[1] = -1;
- break;
- case 1:
- vert[0] = 1;
- break;
- case 2:
- vert[1] = 1;
- break;
- case 3:
- vert[0] = -1;
- break;
- case 4:
- vert[2] = 1;
- break;
- case 5:
- vert[2] = -1;
- }
+ scale_x = (page_dims[2] - num_gaps_x * min_space) / layout_width;
+ scale_y = (page_dims[3] - num_gaps_y * min_space) / layout_height;
- axo = true;
- n[0] = vx;
- n[1] = vy;
- n[2] = vz;
- angle = ang;
- setOrientation(0);
+ working_scale = min(scale_x, scale_y);
- if (active)
- {
- Command::doCommand(Command::Doc,"App.activeDocument().%s.Direction = (%f,%f,%f)",myname.c_str(),vx,vy,vz);
- Command::doCommand(Command::Doc,"App.activeDocument().%s.Label = '%s'",myname.c_str(),number_to_name(6).toStdString().c_str());
- }
+ //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 = 7;
+ 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
+
+ scale = valid_scales[(exponent>=0)][i] * pow(10, exponent); //now have the appropriate scale, reapply the *10^b
}
-void orthoView::setPos(float px, float py)
+void OrthoViews::calc_offsets() // calcs SVG coords for centre of upper left view
{
- if (px != 0 && py !=0)
+ // space_x is the emptry clear white space between views
+ // gap_x is the centre - centre distance between views
+
+ float space_x = (page_dims[2] - scale * layout_width) / num_gaps_x;
+ float space_y = (page_dims[3] - scale * layout_height) / num_gaps_y;
+
+ gap_x = space_x + scale * (width + depth) * 0.5;
+ gap_y = space_y + scale * (height + depth) * 0.5;
+
+ if (min_r_x % 2 == 0)
+ offset_x = page_dims[0] + space_x + 0.5 * scale * width;
+ else
+ offset_x = page_dims[0] + space_x + 0.5 * scale * depth;
+
+ if (max_r_y % 2 == 0)
+ offset_y = page_dims[1] + space_y + 0.5 * scale * height;
+ else
+ offset_y = page_dims[1] + space_y + 0.5 * scale * depth;
+}
+
+
+void OrthoViews::set_views() // process all views - scale & positions
+{
+ float x;
+ float y;
+
+ for (unsigned int i = 0; i < views.size(); i++)
{
- pageX = px;
- pageY = py;
+ x = offset_x + (views[i]->rel_x - min_r_x) * gap_x;
+ y = offset_y + (max_r_y - views[i]->rel_y) * gap_y;
+
+ if (views[i]->auto_scale)
+ views[i]->setScale(scale);
+
+ views[i]->setPos(x, y);
}
+}
- float ox = pageX + x;
- float oy = pageY + y;
- if (active)
+void OrthoViews::process_views() // update scale and positions of views
+{
+ if (autodims)
{
- 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);
+ calc_layout_size();
+
+ if (title)
+ choose_page();
+
+ calc_scale();
+ calc_offsets();
}
+
+ set_views();
+ parent_doc->recompute();
}
-void orthoView::setScale(float newScale)
+void OrthoViews::set_hidden(bool state)
{
- scale = newScale;
- if (active)
- Command::doCommand(Command::Doc,"App.activeDocument().%s.Scale = %f",myname.c_str(), scale);
- calcCentre();
+ hidden = state;
+
+ for (unsigned int i = 0; i < views.size(); i++)
+ views[i]->hidden(hidden);
+
+ parent_doc->recompute();
}
-void orthoView::setOrientation(int orient)
+void OrthoViews::set_smooth(bool state)
{
- orientation = orient;
- if (active)
- Command::doCommand(Command::Doc,"App.activeDocument().%s.Rotation = %f", myname.c_str(), (90*orientation+angle));
- calcCentre();
+ smooth = state;
+
+ for (unsigned int i = 0; i < views.size(); i++)
+ views[i]->smooth(smooth);
+
+ parent_doc->recompute();
}
-void orthoView::calcCentre()
+void OrthoViews::set_primary(gp_Dir facing, gp_Dir right) // set the orientation of the primary view
{
-//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.
+ primary.SetDirection(facing);
+ primary.SetXDirection(right);
+ gp_Dir up = primary.YDirection();
- float cx = mybox.CalcCenter().x;
- float cy = mybox.CalcCenter().y;
- float cz = mybox.CalcCenter().z;
+ // compute dimensions of part when orientated according to primary view
+ width = abs(right.X() * bbox.LengthX() + right.Y() * bbox.LengthY() + right.Z() * bbox.LengthZ());
+ height = abs(up.X() * bbox.LengthX() + up.Y() * bbox.LengthY() + up.Z() * bbox.LengthZ());
+ depth = abs(facing.X() * bbox.LengthX() + facing.Y() * bbox.LengthY() + facing.Z() * bbox.LengthZ());
- if (axo)
+ if (views.size() == 0)
+ add_view(0, 0);
+ else
{
- float p[3] = {cx, -cy, cz};
- float n_p[3] = {n[0], -n[1], n[2]};
- float proj_p[3];
- float proj_y[3]; // will be the y axis of the projection
- float proj_x[3]; // will be the x axis of the projection
-
- project(vert, n_p, proj_y);
- //project(p, n, proj_p);
- cross(proj_y, n_p, proj_x);
- normalise(proj_x);
- normalise(proj_y);
- x = -scale * dot(p, proj_x);
- y = scale * dot(p, proj_y);
- //rotate_coords(x, y, angle)
+ views[0]->set_projection(primary);
+ set_all_orientations(); // reorient all other views appropriately
+ process_views();
}
- else
+}
+
+
+void OrthoViews::set_orientation(int index) // set orientation of single view
+{
+ double rotation;
+ int n; // how many 90* rotations from primary view?
+ gp_Dir dir; // rotate about primary x axis (if in a relative y position) or y axis?
+ gp_Ax2 cs;
+
+ if (views[index]->ortho)
{
- float coords[6][2] =
+ if (views[index]->rel_x != 0)
{
- {-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)
+ dir = primary.YDirection();
+ n = views[index]->rel_x;
+ }
+ else
{
- float temp = width;
- width = height;
- height = temp;
+ dir = primary.XDirection();
+ n = -views[index]->rel_y;
}
+
+ rotation = n * rotate_coeff * PI/2; // rotate_coeff is -1 or 1 for 1st or 3rd angle
+ cs = primary.Rotated(gp_Ax1(gp_Pnt(0,0,0), dir), rotation);
+ views[index]->set_projection(cs);
}
}
-void orthoView::hidden(int state)
+void OrthoViews::set_all_orientations() // set orientations of all views (ie projection or primary changed)
{
- 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());
+ for (unsigned int i = 1; i < views.size(); i++) // start from 1 - the 0 is the primary view
+ {
+ if (views[i]->ortho)
+ set_orientation(i);
+ else
+ set_Axo(views[i]->rel_x, views[i]->rel_y);
+ }
}
-void orthoView::smooth(int state)
+void OrthoViews::set_projection(int proj) // 1 = 1st angle, 3 = 3rd angle
{
- 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());
-}
+ if (proj == 3)
+ rotate_coeff = 1;
+ else if (proj == 1)
+ rotate_coeff = -1;
-///////////////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////
+ set_all_orientations();
+ process_views();
+}
-TaskOrthoViews::TaskOrthoViews(QWidget *parent)
- : ui(new Ui_TaskOrthoViews)
+void OrthoViews::add_view(int rel_x, int rel_y) // add a new view to the layout
{
- ui->setupUi(this);
+ if (index(rel_x, rel_y) == -1)
+ {
+ orthoview * view = new orthoview(parent_doc, part, page, & bbox);
+ view->set_data(rel_x, rel_y);
+ views.push_back(view);
- 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());
+ max_r_x = max(max_r_x, rel_x);
+ min_r_x = min(min_r_x, rel_x);
+ max_r_y = max(max_r_y, rel_y);
+ min_r_y = min(min_r_y, rel_y);
- const char * part = obj.front()->getNameInDocument();
- App::Document* doc = App::GetApplication().getActiveDocument();
+ num_gaps_x = max_r_x - min_r_x + 2;
+ num_gaps_y = max_r_y - min_r_y + 2;
- std::vector pages = doc->getObjectsOfType(Drawing::FeaturePage::getClassTypeId());
- std::string PageName = pages.front()->getNameInDocument();
- const char * page = PageName.c_str();
+ int i = views.size() - 1;
+ views[i]->hidden(hidden);
+ views[i]->smooth(smooth);
- App::DocumentObject * this_page = doc->getObject(page);
- std::string template_name = static_cast(this_page)->Template.getValue();
+ if (views[i]->ortho)
+ set_orientation(i);
+ else
+ set_Axo(rel_x, rel_y);
- 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);
+ process_views();
+ }
+}
- 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)));
+void OrthoViews::del_view(int rel_x, int rel_y) // remove a view from the layout
+{
+ int num = index(rel_x, rel_y);
- 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;
- ui->tabWidget->setTabEnabled(1,false);
+ if (num > 0)
+ {
+ views[num]->deleteme();
+ delete views[num];
+ views.erase(views.begin() + num);
- for (int i=0; i < 5; i++)
- connect(inputs[i], SIGNAL(editingFinished()), this, SLOT(data_entered()));
+ min_r_x = max_r_x = 0;
+ min_r_y = max_r_y = 0;
- 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)));
-
- connect(ui->axoProj, SIGNAL(activated(int)), this, SLOT(axoChanged(int)));
- connect(ui->axoTop, SIGNAL(activated(int)), this, SLOT(axoTopChanged(int)));
- connect(ui->axoLeft, SIGNAL(activated(int)), this, SLOT(axoChanged(int)));
- connect(ui->flip, SIGNAL(clicked()), this, SLOT(axo_flip()));
- connect(ui->axoScale, SIGNAL(editingFinished()), this, SLOT(axoScale()));
-
- //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];
- }
+ for (unsigned int i = 1; i < views.size(); i++) // start from 1 - the 0 is the primary view
+ {
+ min_r_x = min(min_r_x, views[i]->rel_x); // calculate extremes from remaining views
+ max_r_x = max(max_r_x, views[i]->rel_x);
+ min_r_y = min(min_r_y, views[i]->rel_y);
+ max_r_y = max(max_r_y, views[i]->rel_y);
+ }
- float temp[3][6][4][4] =
- // isometric
- {{{{1,1,1,180},{-1,1,-1,180},{-1,1,1,180},{1,1,-1,180}}, // top face is the Right
- {{1,1,-1,60},{1,-1,1,240},{1,1,1,300},{1,-1,-1,120}}, // Front
- {{1,-1,-1,0},{-1,-1,1,0},{1,-1,1,0},{-1,-1,-1,0}}, // Left
- {{-1,1,1,60},{-1,-1,-1,240},{-1,-1,1,120},{-1,1,-1,300}}, // Back
- {{1,1,1,60},{1,-1,1,120},{-1,-1,1,240},{-1,1,1,300}}, // Top
- {{-1,1,-1,60},{1,1,-1,300},{1,-1,-1,240},{-1,-1,-1,120}}}, // Bottom
-
- // dimetric
- {{{0.681,0.267,0.681,180},{-0.681,0.267,-0.681,180},{-0.681,0.267,0.681,180},{0.681,0.267,-0.681,180}}, // top face is the Right
- {{0.267,0.681,-0.681,0},{0.267,-0.681,0.681,0},{0.267,0.681,0.681,0},{0.267,-0.681,-0.681,0}}, // Front
- {{0.681,-0.267,-0.681,0},{-0.681,-0.267,0.681,0},{0.681,-0.267,0.681,0},{-0.681,-0.267,-0.681,0}}, // Left
- {{-0.267,0.681,0.681,180},{-0.267,-0.681,-0.681,180},{-0.267,-0.681,0.681,180},{-0.267,0.681,-0.681,180}}, // Back
- {{0.681,0.681,0.267,0},{0.681,-0.681,0.267,0},{-0.681,-0.681,0.267,0},{-0.681,0.681,0.267,0}}, // Top
- {{-0.681,0.681,-0.267,180},{0.681,0.681,-0.267,180},{0.681,-0.681,-0.267,180},{-0.681,-0.681,-0.267,180}}}, // Bottom
-
- // trimetric
- {{{0.211,0.577,0.788,-98.8},{-0.211,0.577,-0.788,81.2},{-0.788,0.577,0.211,81.2},{0.788,0.577,-0.211,-98.8}}, // top face is the Right
- {{0.577,0.211,-0.788,81.2},{0.577,-0.211,0.788,-98.8},{0.577,0.788,0.211,-98.8},{0.577,-0.788,-0.211,81.2}}, // Front
- {{0.211,-0.577,-0.788,-98.8},{-0.211,-0.577,0.788,81.2},{0.788,-0.577,0.211,81.2},{-0.788,-0.577,-0.211,-98.8}}, // Left
- {{-0.577,0.211,0.788,81.2},{-0.577,-0.211,-0.788,-98.8},{-0.577,-0.788,0.211,-98.8},{-0.577,0.788,-0.211,81.2}}, // Back
- {{0.788,0.211,0.577,-98.8},{0.211,-0.788,0.577,81.2},{-0.788,-0.211,0.577,81.2},{-0.211,0.788,0.577,-98.8}}, // Top
- {{-0.788,0.211,-0.577,-98.8},{0.211,0.788,-0.577,81.2},{0.788,-0.211,-0.577,81.2},{-0.211,-0.788,-0.577,-98.8}}}}; // Bottom
-
- for (int i = 0; i < 3; i++)
- for (int j = 0; j < 6; j++)
- for (int k = 0; k < 4; k++)
- for (int l = 0; l < 4; l++)
- axonometric[i][j][k][l] = temp[i][j][k][l];
-
- //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;
- axo_flipped = false;
-
- //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]);
+ num_gaps_x = max_r_x - min_r_x + 2;
+ num_gaps_y = max_r_y - min_r_y + 2;
-} //end of constructor
+ process_views();
+ }
+}
-TaskOrthoViews::~TaskOrthoViews()
+void OrthoViews::del_all()
{
- delete views[0];
- delete views[1];
- delete views[2];
- delete views[3];
- delete ui;
+ for (int i = views.size() - 1; i >= 0; i--) // count downwards to delete from back
+ {
+ views[i]->deleteme();
+ delete views[i];
+ views.pop_back();
+ }
}
-void TaskOrthoViews::changeEvent(QEvent *e)
+int OrthoViews::is_Ortho(int rel_x, int rel_y) // is the view at r_x, r_y an ortho or axo one?
{
- if (e->type() == QEvent::LanguageChange) {
- ui->retranslateUi(this);
- }
+ int result = index(rel_x, rel_y);
+
+ if (result != -1)
+ result = views[result]->ortho;
+
+ return result;
}
-void TaskOrthoViews::pagesize(std::string& page_template)
+int OrthoViews::index(int rel_x, int rel_y) // index in vector of view, -1 if doesn't exist
{
- // /********update num_templates when adding extra templates*******************/
+ int index = -1;
- 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)
- if (page_template.find(templates[i]) != std::string::npos)
+ for (unsigned int i = 0; i < views.size(); i++)
+ if (views[i]->rel_x == rel_x && views[i]->rel_y == rel_y)
{
- pagewidth = dimensions[i][0] - 2*margin;
- pageh1 = dimensions[i][1] - 2*margin;
- pageh2 = dimensions[i][2] - margin;
- return;
+ index = i;
+ break;
}
+
+ return index;
+}
+
+
+void OrthoViews::set_Axo_scale(int rel_x, int rel_y, float axo_scale) // set an axo scale independent of ortho ones
+{
+ int num = index(rel_x, rel_y);
+
+ if (num != -1 && !views[num]->ortho)
+ {
+ views[num]->auto_scale = false;
+ views[num]->setScale(axo_scale);
+ views[num]->setPos();
+ parent_doc->recompute();
}
+}
- //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())
+void OrthoViews::set_Axo(int rel_x, int rel_y, gp_Dir up, gp_Dir right, bool away, int axo, bool tri) // set custom axonometric view
+{
+ int num = index(rel_x, rel_y);
+ double rotations[2];
+ gp_Dir dir;
+
+ views[num]->ortho = false;
+ views[num]->away = away;
+ views[num]->tri = tri;
+ views[num]->axo = axo;
+
+ if (axo == 0)
{
- 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;
- }
+ rotations[0] = -0.7853981633974476;
+ rotations[1] = -0.6154797086703873;
+ }
+ else if (axo == 1)
+ {
+ rotations[0] = -0.7853981633974476;
+ rotations[1] = -0.2712637537260206;
+ }
+ else if (tri)
+ {
+ rotations[0] = -1.3088876392502007;
+ rotations[1] = -0.6156624905260762;
+ }
+ else
+ {
+ rotations[0] = 1.3088876392502007 - PI/2;
+ rotations[1] = -0.6156624905260762;
}
- // open Template file
- std::string line;
- std::string temp_line;
- std::ifstream file (fi.filePath().c_str());
- size_t found;
- bool done = false;
+ if (away)
+ rotations[1] = - rotations[1];
- try
+ gp_Ax2 cs = gp_Ax2(gp_Pnt(0,0,0), right);
+ cs.SetYDirection(up);
+ cs.Rotate(gp_Ax1(gp_Pnt(0,0,0), up), rotations[0]);
+ dir = cs.XDirection();
+ cs.Rotate(gp_Ax1(gp_Pnt(0,0,0), dir), rotations[1]);
+
+ views[num]->up = up;
+ views[num]->right = right;
+ views[num]->set_projection(cs);
+ views[num]->setPos();
+
+ parent_doc->recompute();
+}
+
+
+void OrthoViews::set_Axo(int rel_x, int rel_y) // set view to default axo projection
+{
+ int num = index(rel_x, rel_y);
+
+ if (num != -1)
{
- while (!file.eof())
+ gp_Dir up = primary.YDirection(); // default to view from up and right
+ gp_Dir right = primary.XDirection();
+ bool away = false;
+
+ if (rel_x * rel_y != 0) // but change default if it's a diagonal position
{
- getline (file,line);
- found = line.find("width=");
- if (found != std::string::npos)
+ if (rotate_coeff == 1) // third angle
{
- temp_line = line.substr(7+found);
- sscanf (temp_line.c_str(), "%f", &pagewidth);
- pagewidth -= 2*margin;
+ away = (rel_y < 0);
- if (done)
- {
- file.close();
- return;
- }
+ if (rel_x < 0)
+ right = primary.Direction();
else
- done = true;
+ right = primary.XDirection();
}
-
- found = line.find("height=");
- if (found != std::string::npos)
+ else // first angle
{
- temp_line = line.substr(8+found);
- sscanf (temp_line.c_str(), "%f", &pageh1);
- pageh1 -= 2*margin;
- pageh2 = pageh1;
+ away = (rel_y > 0);
- if (done)
- {
- file.close();
- return;
- }
+ if (rel_x > 0)
+ right = primary.Direction();
else
- done = true;
+ right = primary.XDirection();
}
-
- if (line.find("metadata") != std::string::npos) //give up if we meet a metadata tag
- break;
}
+ set_Axo(rel_x, rel_y, up, right, away);
}
- catch (Standard_Failure)
- { }
-
- file.close();
-
- //width/height not found?? fallback to A4 landscape simple:
- pagewidth = 277;
- pageh1 = 190;
- pageh2 = 190;
}
-void TaskOrthoViews::autodims()
+void OrthoViews::set_Ortho(int rel_x, int rel_y) // return view to orthographic
{
- /************************************* 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;
+ int num = index(rel_x, rel_y);
- 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++)
+ if (num != -1 && rel_x * rel_y == 0)
{
- 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;
+ views[num]->ortho = true;
+ views[num]->setScale(scale);
+ views[num]->auto_scale = true;
+ set_orientation(num);
+ views[num]->setPos();
+
+ parent_doc->recompute();
}
+}
+
- 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;
+bool OrthoViews::get_Axo(int rel_x, int rel_y, int & axo, gp_Dir & up, gp_Dir & right, bool & away, bool & tri, float & axo_scale)
+{
+ int num = index(rel_x, rel_y);
- if (max_y > 0 && !c_boxes[3][3]->isChecked() && min_x == 0 && ((max_x == 1)*w2 > w1 || max_x == 2))
- pageheight = pageh1;
+ if (num != -1 && !views[num]->ortho)
+ {
+ axo = views[num]->axo;
+ up = views[num]->up;
+ right = views[num]->right;
+ away = views[num]->away;
+ tri = views[num]->tri;
+ axo_scale = views[num]->getScale();
+ return true;
+ }
else
- pageheight = pageh2;
+ return false;
+}
- /*************************************** calculate scale **************************************/
- float working_scale = min((pagewidth - (wide + 1) * min_space) / width, (pageheight - (high + 1) * min_space) / height);
+void OrthoViews::auto_dims(bool setting)
+{
+ autodims = setting;
+ if (autodims)
+ process_views();
+}
- //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.
+void OrthoViews::set_configs(float configs[5]) // for autodims off, set scale & positionings
+{
+ if (!autodims)
+ {
+ scale = configs[0];
+ offset_x = configs[1];
+ offset_y = configs[2];
+ gap_x = configs[3];
+ gap_y = configs[4];
+ process_views();
+ }
+}
- 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
+void OrthoViews::get_configs(float configs[5]) // get scale & positionings
+{
+ configs[0] = scale;
+ configs[1] = offset_x;
+ configs[2] = offset_y;
+ configs[3] = gap_x;
+ configs[4] = gap_y;
+}
- /************************************* 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;
+TaskOrthoViews::TaskOrthoViews(QWidget *parent)
+ : ui(new Ui_TaskOrthoViews)
+{
+ ui->setupUi(this);
+ vector obj = Gui::Selection().getObjectsOfType(Part::Feature::getClassTypeId());
+ const char * part = obj.front()->getNameInDocument();
- /************************************* update gui text boxes **********************************/
+ App::Document * doc = App::GetApplication().getActiveDocument();
+ vector pages = doc->getObjectsOfType(Drawing::FeaturePage::getClassTypeId());
+ string PageName = pages.front()->getNameInDocument();
+ const char * page = PageName.c_str();
- for (int i = 0; i < 5; i++)
- inputs[i]->setText(QString::number(*data[i]));
-}
+ // **********************************************************************
+ // note that checkboxes are numbered increasing right & down
+ // while OrthoViews relative positions are increasing right & up
+ // doh! I should renumber the checkboxes for clarity
+ // **********************************************************************
-void TaskOrthoViews::compute()
-{
- float temp_scale = scale;
- if (autoscale)
- autodims();
+ // [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 < 4; i++)
- {
- if (i == axo && i > 0)
- {
- if (temp_scale == ui->axoScale->text().toFloat())
+ 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:
{
- views[i]->setScale(scale); // only update the axonometric scale if it wasn't manually changed
- ui->axoScale->setText(QString::number(scale));
+ connect(c_boxes[i][j], SIGNAL(toggled(bool)), this, SLOT(cb_toggled(bool)));
+ connect(c_boxes[i][j], SIGNAL(customContextMenuRequested(const QPoint&)),this, SLOT(ShowContextMenu(const QPoint&)));
}
- }
- else
- views[i]->setScale(scale);
- views[i]->setPos(x_pos + view_status[i][2] * horiz, y_pos + view_status[i][3] * vert);
+ // access scale / position QLineEdits via array
+ 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(textEdited(const QString &)), this, SLOT(data_entered(const QString &)));
+ connect(inputs[i], SIGNAL(returnPressed()), this, SLOT(text_return()));
}
- Command::updateActive();
- Command::commitCommand();
-}
+ connect(ui->projection, SIGNAL(currentIndexChanged(int)), this, SLOT(projectionChanged(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)));
-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:
+ connect(ui->view_from, SIGNAL(currentIndexChanged(int)), this, SLOT(setPrimary(int)));
+ connect(ui->axis_right, SIGNAL(currentIndexChanged(int)), this, SLOT(setPrimary(int)));
- 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);
- }
- }
- }
- }
- }
- }
+ connect(ui->axoProj, SIGNAL(activated(int)), this, SLOT(change_axo(int)));
+ connect(ui->axoUp, SIGNAL(activated(int)), this, SLOT(change_axo(int)));
+ connect(ui->axoRight, SIGNAL(activated(int)), this, SLOT(change_axo(int)));
+ connect(ui->vert_flip, SIGNAL(clicked()), this, SLOT(axo_button()));
+ connect(ui->tri_flip, SIGNAL(clicked()), this, SLOT(axo_button()));
+ connect(ui->axoScale, SIGNAL(textEdited(const QString &)), this, SLOT(axo_scale(const QString &)));
+ connect(ui->axoScale, SIGNAL(returnPressed()), this, SLOT(text_return()));
+
+ ui->tabWidget->setTabEnabled(1,false);
+
+ gp_Dir facing = gp_Dir(1, 0, 0);
+ gp_Dir right = gp_Dir(0, 1, 0);
+ orthos = new OrthoViews(page, part);
+ orthos->set_primary(facing, right);
+
+ txt_return = false;
+} //end of constructor
+
+
+TaskOrthoViews::~TaskOrthoViews()
+{
+ delete orthos;
+ delete ui;
}
-void TaskOrthoViews::cb_toggled(bool toggle)
+void TaskOrthoViews::ShowContextMenu(const QPoint& pos)
{
QString name = sender()->objectName().right(2);
char letter = name.toStdString()[0];
@@ -838,396 +948,361 @@ void TaskOrthoViews::cb_toggled(bool toggle)
letter = name.toStdString()[1];
int dy = letter - '0' - 2;
- int i = 0;
- if (toggle)
+ if (c_boxes[dx + 2][dy + 2]->isChecked())
{
- for (i = 0; i < 4; i++)
- {
- if (view_status[i][0] == 0)
- break;
- }
-
- int direction, rotation;
- view_status[i][0] = 1;
- view_status[i][2] = dx;
- view_status[i][3] = dy;
- views[i]->activate(true);
-
- if (abs(dx * dy) == 1)
- {
- axo = i;
- ui->tabWidget->setTabEnabled(1,true);
- ui->axoScale->setText(QString::number(scale));
- set_axo();
- }
+ QString str_1 = QObject::tr("Make axonometric...");
+ QString str_2 = QObject::tr("Edit axonometric settings...");
+ QString str_3 = QObject::tr("Make orthographic");
+
+ QPoint globalPos = c_boxes[dx + 2][dy + 2]->mapToGlobal(pos);
+ QMenu myMenu;
+ if (orthos->is_Ortho(dx, -dy))
+ myMenu.addAction(str_1);
else
{
- view_data(dx, dy, direction, rotation);
- views[i]->setDir(direction);
- views[i]->setOrientation(rotation);
+ myMenu.addAction(str_2);
+ if (dx * dy == 0)
+ myMenu.addAction(str_3);
}
- view_count += 1;
- }
- else
- {
- if (((abs(dx) == 1 || abs(dy) == 1)) && (dx*dy) == 0)
+
+ QAction * selectedItem = myMenu.exec(globalPos);
+ if (selectedItem)
{
- c_boxes[dx*2+2][dy*2+2]->setChecked(false);
- if (abs(dx) == 1)
+ QString text = selectedItem->text();
+
+ if (text == str_1) // make axo
{
- c_boxes[dx+2][1]->setChecked(false);
- c_boxes[dx+2][3]->setChecked(false);
+ orthos->set_Axo(dx, -dy);
+ axo_r_x = dx;
+ axo_r_y = dy;
+ ui->tabWidget->setTabEnabled(1, true);
+ ui->tabWidget->setCurrentIndex(1);
+ setup_axo_tab();
}
- else
+ else if (text == str_2) // edit axo
{
- c_boxes[1][dy+2]->setChecked(false);
- c_boxes[3][dy+2]->setChecked(false);
+ axo_r_x = dx;
+ axo_r_y = dy;
+ ui->tabWidget->setTabEnabled(1, true);
+ ui->tabWidget->setCurrentIndex(1);
+ setup_axo_tab();
+ }
+ else if (text == str_3) // make ortho
+ {
+ orthos->set_Ortho(dx, -dy);
+ if (dx == axo_r_x && dy == axo_r_y)
+ {
+ axo_r_x = 0;
+ axo_r_y = 0;
+ ui->tabWidget->setTabEnabled(1, false);
+ }
}
}
+ }
+}
- for (i = 0; i < 4; i++)
- {
- if (view_status[i][2] == dx && view_status[i][3] == dy)
- break;
- }
-
- if (i == axo)
- {
- axo = 0;
- ui->tabWidget->setTabEnabled(1,false);
- }
- views[i]->activate(false);
- view_status[i][0] = 0;
- view_status[i][2] = 0;
- view_status[i][3] = 0;
- view_count -= 1;
+void TaskOrthoViews::changeEvent(QEvent *e)
+{
+ if (e->type() == QEvent::LanguageChange) {
+ ui->retranslateUi(this);
}
- validate_cbs();
- compute();
}
-void TaskOrthoViews::view_data(int x, int y, int & direction, int & rotation)
+void TaskOrthoViews::cb_toggled(bool toggle)
{
- int arr_index;
- rotate_coords(x,y,(4-rotate)%4);
- x = x * proj;
- y = y * proj;
+ 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;
- if (primary < 4)
+ if (toggle)
{
- if (y == 0)
- {
- rotation = rotate;
- direction = (primary + x + 4) % 4;
- }
- else
+ orthos->add_view(dx, -dy);
+ if (dx * dy != 0) // adding an axo view
{
- 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;
+ axo_r_x = dx;
+ axo_r_y = dy;
+ ui->tabWidget->setTabEnabled(1, true);
+ ui->tabWidget->setCurrentIndex(1);
+ setup_axo_tab();
}
}
- else
+ else // removing a view
{
- 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;
+ if (!orthos->is_Ortho(dx, -dy)) // is it an axo one?
+ {
+ if (dx == axo_r_x && dy == axo_r_y) // is it the one currently being edited?
+ {
+ axo_r_x = 0;
+ axo_r_y = 0;
+ ui->tabWidget->setTabEnabled(1, false);
+ }
+ }
+ orthos->del_view(dx, -dy);
}
+
+ set_configs();
}
void TaskOrthoViews::projectionChanged(int index)
{
- proj = 2*(0.5-index); //gives -1 for 1st angle and 1 for 3rd
- updateSecondaries();
- compute();
+ int proj = 3 - 2 * index; // index = 0 = third angle
+ orthos->set_projection(proj);
+
+ set_configs();
}
-void TaskOrthoViews::setRotate(int r)
+void TaskOrthoViews::setPrimary(int dir)
{
- rotate = r;
- views[0]->setOrientation(rotate);
- updateSecondaries();
- compute();
-}
+ int p_sel = ui->view_from->currentIndex(); // index for entry selected for 'view from'
+ int r_sel = ui->axis_right->currentIndex(); // index for entry selected for 'rightwards axis'
+ int p_vec[3] = {0, 0, 0}; // will be the vector for 'view from'
+ int r_vec[3] = {0, 0, 0}; // will be vector for 'rightwards axis'
+ int r[2] = {0, 1};
-void TaskOrthoViews::updateSecondaries()
-{
- int direction, rotation;
- int dx, dy;
- int n;
+ int pos = 1 - 2 * int(p_sel / 3); // 1 if p_sel = 0, 1, 2 or -1 if p_sel = 3, 4, 5
+ p_sel = p_sel % 3; // p_sel = 0, 1, 2
+ p_vec[p_sel] = pos;
- for (int i = 1; i < 4; i++)
- if ((view_status[i][0] == 1) && (i != axo))
- {
- dx = view_status[i][2];
- dy = view_status[i][3];
- view_data(dx, dy, direction, rotation);
- views[i]->setDir(direction);
- views[i]->setOrientation(rotation);
- }
-}
+ for (int i = p_sel; i < 2; i++) // make r[2] to be, {0, 1}, {0, 2}, or {1, 2} depending upon p_sel
+ r[i] += 1;
+ pos = 1 - 2 * int(r_sel / 2); // 1 if r_sel = 0, 1 or -1 if r_sel = 3, 4
+ r_sel = r_sel % 2; // r_sel = 0, 1
+ r_vec[r[r_sel]] = pos;
-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
+ gp_Dir facing = gp_Dir(p_vec[0], p_vec[1], p_vec[2]);
+ gp_Dir right = gp_Dir(r_vec[0], r_vec[1], r_vec[2]);
+
+ orthos->set_primary(facing, right);
+
+ // update rightwards combobox in case of 'view from' change
+ if (sender() == ui->view_from)
{
- 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();
+ disconnect(ui->axis_right, SIGNAL(currentIndexChanged(int)), this, SLOT(setPrimary(int)));
+
+ QStringList items;
+ items << QString::fromUtf8("X +ve") << QString::fromUtf8("Y +ve") << QString::fromUtf8("Z +ve");
+ items << QString::fromUtf8("X -ve") << QString::fromUtf8("Y -ve") << QString::fromUtf8("Z -ve");
+ items.removeAt(p_sel + 3);
+ items.removeAt(p_sel);
+
+ ui->axis_right->clear();
+ ui->axis_right->addItems(items);
+ ui->axis_right->setCurrentIndex(r_sel - pos + 1);
+
+ connect(ui->axis_right, SIGNAL(currentIndexChanged(int)), this, SLOT(setPrimary(int)));
}
- validate_cbs();
+
+ set_configs();
}
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();
+ orthos->set_hidden(i == 2);
}
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();
+ orthos->set_smooth(i == 2);
}
-void TaskOrthoViews::axo_flip()
+void TaskOrthoViews::toggle_auto(int i)
{
- axo_flipped = !axo_flipped;
- set_axo();
+ if (i == 2) //auto scale switched on
+ {
+ orthos->auto_dims(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
+ }
+ else
+ {
+ orthos->auto_dims(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::axoTopChanged(int i)
+void TaskOrthoViews::data_entered(const QString & text)
{
- QStringList items;
- items << QString::fromUtf8("Front") << QString::fromUtf8("Right") << QString::fromUtf8("Back") << QString::fromUtf8("Left") << QString::fromUtf8("Top") << QString::fromUtf8("Bottom");
+ bool ok;
+ QString name = sender()->objectName().right(1);
+ char letter = name.toStdString()[0];
+ int index = letter - '0';
- if (i == 0 || i == 2)
- {
- items.removeAt(0);
- items.removeAt(1);
- }
- else if (i == 1 || i == 3)
+ float value = text.toFloat(&ok);
+
+ if (ok)
{
- items.removeAt(1);
- items.removeAt(2);
+ data[index] = value;
+ orthos->set_configs(data);
}
else
{
- items.removeAt(4);
- items.removeAt(4);
+ inputs[index]->setText(QString::number(data[index]));
+ return;
}
- ui->axoLeft->clear();
- ui->axoLeft->addItems(items);
- set_axo();
}
-void TaskOrthoViews::axoChanged(int i)
+void TaskOrthoViews::clean_up()
{
- if (i == 2)
- ui->flip->setEnabled(true);
- else
- ui->flip->setEnabled(false);
-
- set_axo();
+ orthos->del_all();
}
-void TaskOrthoViews::axoScale()
+void TaskOrthoViews::setup_axo_tab()
{
- bool ok;
- QString temp = ui->axoScale->text();
+ int axo;
+ gp_Dir up, right;
+ bool away, tri;
+ float axo_scale;
+ int up_n, right_n;
+
+ orthos->get_Axo(axo_r_x, -axo_r_y, axo, up, right, away, tri, axo_scale);
+
+ // convert gp_Dirs into selections of comboboxes
+ if (up.X() != 0)
+ up_n = (up.X() == -1) ? 3 : 0;
+ else if (up.Y() != 0)
+ up_n = (up.Y() == -1) ? 4 : 1;
+ else
+ up_n = (up.Z() == -1) ? 5 : 2;
- float value = temp.toFloat(&ok);
- if (ok)
- {
- views[axo]->setScale(value);
- compute();
- }
+ if (right.X() != 0)
+ right_n = (right.X() == -1) ? 3 : 0;
+ else if (right.Y() != 0)
+ right_n = (right.Y() == -1) ? 4 : 1;
else
- ui->axoScale->setText(temp);
+ right_n = (right.Z() == -1) ? 5 : 2;
+
+ if (right_n > (up_n % 3 + 3))
+ right_n -= 2;
+ else if (right_n > up_n)
+ right_n -= 1;
+
+ QStringList items;
+ items << QString::fromUtf8("X +ve") << QString::fromUtf8("Y +ve") << QString::fromUtf8("Z +ve");
+ items << QString::fromUtf8("X -ve") << QString::fromUtf8("Y -ve") << QString::fromUtf8("Z -ve");
+ items.removeAt(up_n % 3 + 3);
+ items.removeAt(up_n % 3);
+
+ ui->axoUp->setCurrentIndex(up_n);
+ ui->axoRight->clear();
+ ui->axoRight->addItems(items);
+ ui->axoRight->setCurrentIndex(right_n);
+
+ ui->vert_flip->setChecked(away);
+ ui->tri_flip->setChecked(tri);
+ ui->axoProj->setCurrentIndex(axo);
+ ui->axoScale->setText(QString::number(axo_scale));
}
-void TaskOrthoViews::set_axo()
+void TaskOrthoViews::change_axo(int p)
{
- float v[3];
- float angle;
- int proj, primary, left;
+ int u_sel = ui->axoUp->currentIndex(); // index for entry selected for 'view from'
+ int r_sel = ui->axoRight->currentIndex(); // index for entry selected for 'rightwards axis'
- proj = ui->axoProj->currentIndex();
- primary = ui->axoTop->currentIndex();
- left = ui->axoLeft->currentIndex();
+ int u_vec[3] = {0, 0, 0}; // will be the vector for 'view from'
+ int r_vec[3] = {0, 0, 0}; // will be vector for 'rightwards axis'
+ int r[2] = {0, 1};
- v[0] = axonometric[proj][primary][left][0];
- v[1] = axonometric[proj][primary][left][1];
- v[2] = axonometric[proj][primary][left][2];
- angle = axonometric[proj][primary][left][3];
+ int pos = 1 - 2 * int(u_sel / 3); // 1 if p_sel = 0,1,2 or -1 if p_sel = 3,4,5
+ u_sel = u_sel % 3; // p_sel = 0,1,2
+ u_vec[u_sel] = pos;
- if (axo_flipped && proj == 2)
- {
- int max_i = 2;
- int min_i = 2;
- float abs_v[3] = {abs(v[0]), abs(v[1]), abs(v[2])};
-
- if (abs_v[0] < abs_v[1] && abs_v[0] < abs_v[2])
- min_i = 0;
- else if (abs_v[1] < abs_v[2])
- min_i = 1;
-
- if (abs_v[0] > abs_v[1] && abs_v[0] > abs_v[2])
- max_i = 0;
- else if (abs_v[1] > abs_v[2])
- max_i = 1;
-
- v[min_i] = ((v[min_i] > 0) - (v[min_i] < 0)) * abs_v[max_i];
- v[max_i] = ((v[max_i] > 0) - (v[max_i] < 0)) * abs_v[min_i];
-
- if (((left == 0 || left == 1) && (primary == 1 || primary == 2)) ||
- ((left == 2 || left == 3) && (primary == 0 || primary == 3)) ||
- ((primary == 5) && (left == 0 || left == 2)) ||
- ((primary == 4) && (left == 1 || left == 3)))
- {
- angle = - angle;
- }
- else
- {
- angle = (angle > 0) ? 98.8 : -81.2;
- }
- }
- views[axo]->setDir(v[0],v[1],v[2], angle, primary);
- compute();
-}
+ for (int i = u_sel; i < 2; i++)
+ r[i] += 1;
+ pos = 1 - 2 * int(r_sel / 2);
+ r_sel = r_sel % 2;
+ r_vec[r[r_sel]] = pos;
-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();
- }
+ gp_Dir up = gp_Dir(u_vec[0], u_vec[1], u_vec[2]);
+ gp_Dir right = gp_Dir(r_vec[0], r_vec[1], r_vec[2]);
+
+ orthos->set_Axo(axo_r_x, -axo_r_y, up, right, ui->vert_flip->isChecked(), ui->axoProj->currentIndex(), ui->tri_flip->isChecked());
+
+ if (ui->axoProj->currentIndex() == 2)
+ ui->tri_flip->setEnabled(true);
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
- }
+ ui->tri_flip->setEnabled(false);
+
+
+ QStringList items;
+ items << QString::fromUtf8("X +ve") << QString::fromUtf8("Y +ve") << QString::fromUtf8("Z +ve");
+ items << QString::fromUtf8("X -ve") << QString::fromUtf8("Y -ve") << QString::fromUtf8("Z -ve");
+ items.removeAt(u_sel % 3 + 3);
+ items.removeAt(u_sel % 3);
+
+ ui->axoRight->clear();
+ ui->axoRight->addItems(items);
+ ui->axoRight->setCurrentIndex(r_sel - pos + 1);
}
-void TaskOrthoViews::data_entered()
+void TaskOrthoViews::axo_button()
{
- //Command::doCommand(Command::Doc,"#1");
- bool ok;
+ change_axo();
+}
- QString name = sender()->objectName().right(1);
- char letter = name.toStdString()[0];
- int index = letter - '0';
+void TaskOrthoViews::axo_scale(const QString & text)
+{
+ bool ok;
+ float value = text.toFloat(&ok);
- float value = inputs[index]->text().toFloat(&ok);
if (ok)
- *data[index] = value;
- else
- {
- inputs[index]->setText(QString::number(*data[index]));
- return;
- }
- compute();
+ orthos->set_Axo_scale(axo_r_x, -axo_r_y, value);
}
-bool TaskOrthoViews::user_input()
+void TaskOrthoViews::set_configs()
{
- //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;
+ orthos->get_configs(data);
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
- }
- }
- if (ui->axoScale->isModified())
- {
- ui->axoScale->setModified(false);
- modified = true;
- }
- return modified;
+ inputs[i]->setText(QString::number(data[i]));
}
-void TaskOrthoViews::clean_up(bool keep)
+bool TaskOrthoViews::user_input()
{
- 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
+ if (txt_return)
{
- views[0]->deleteme();
- views[1]->deleteme();
- views[2]->deleteme();
- views[3]->deleteme();
+ txt_return = false; // return was pressed while text box had focus
+ ui->label_7->setFocus(); // move focus out of text box
+ return true; // return that we were editing
}
+ else
+ return false; // return that we weren't editing ---> treat as clicking OK... we can close the GUI
}
+void TaskOrthoViews::text_return()
+{
+ txt_return = true;
+}
@@ -1265,15 +1340,12 @@ 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);
+ widget->clean_up();
return true;
}
diff --git a/src/Mod/Drawing/Gui/TaskOrthoViews.h b/src/Mod/Drawing/Gui/TaskOrthoViews.h
index 9c88bfa0ee11..5cb9823991d7 100644
--- a/src/Mod/Drawing/Gui/TaskOrthoViews.h
+++ b/src/Mod/Drawing/Gui/TaskOrthoViews.h
@@ -28,53 +28,127 @@
#include "ui_TaskOrthoViews.h"
#include
+#include
+#include
+
+#include
+
+
+
class Ui_TaskOrthoViews;
+using namespace std;
namespace DrawingGui {
-class orthoView
+class orthoview
{
public:
- orthoView(std::string, const char *, const char *, Base::BoundBox3d);
- ~orthoView();
-
- void activate(bool);
- void setDir(int);
- void setDir(float,float,float,float,int);
- void setPos(float = 0, float = 0);
- void setScale(float);
- void setOrientation(int);
- void deleteme();
- void hidden(int);
- void smooth(int);
-
-public:
- bool active;
- float width;
- float height;
+ orthoview(App::Document * parent, App::DocumentObject * part, App::DocumentObject * page, Base::BoundBox3d * partbox);
+ ~orthoview();
+
+ void set_data(int r_x, int r_y);
+ void set_projection(gp_Ax2 cs);
+ void setPos(float = 0, float = 0);
+ void setScale(float newscale);
+ float getScale();
+ void deleteme();
+ void hidden(bool);
+ void smooth(bool);
private:
- void calcCentre();
- void updateView();
+ void calcCentre();
+
+public: // these aren't used by orthoView, but just informational, hence public
+ bool ortho; // orthonometric? or axonometric
+ bool auto_scale; // scale for axonometric has not been manually changed?
+ int rel_x, rel_y; // relative position of this view
+ bool away, tri; // binary parameters for axonometric view
+ int axo; // 0 / 1 / 2 = iso / di / tri metric
+ gp_Dir up, right; // directions prior to rotations (ie, what was used to orientate the projection)
private:
- std::string myname;
- Base::BoundBox3d mybox;
- int dir;
- float angle;
- float n[3];
- int orientation;
- float x, y;
- float pageX, pageY;
- float scale;
- bool axo;
- float vert[3];
+ App::Document * parent_doc;
+ Drawing::FeatureViewPart * this_view;
+
+ string myname;
+ float x, y; // 2D projection coords of bbox centre relative to origin
+ float cx, cy, cz; // coords of bbox centre in 3D space
+ float pageX, pageY; // required coords of centre of bbox projection on page
+ float scale; // scale of projection
+ gp_Dir X_dir, Y_dir, Z_dir; // directions of projection, X_dir makes x on page, Y_dir is y on page, Z_dir is out of page
};
+class OrthoViews
+{
+public:
+ OrthoViews(const char * pagename, const char * partname);
+ ~OrthoViews();
+
+ void set_primary(gp_Dir facing, gp_Dir right);
+ void add_view(int rel_x, int rel_y);
+ void del_view(int rel_x, int rel_y);
+ void del_all();
+ void set_projection(int proj);
+ void set_hidden(bool state);
+ void set_smooth(bool state);
+ void set_Axo(int rel_x, int rel_y, gp_Dir up, gp_Dir right, bool away = false, int axo = 0, bool tri = false);
+ void set_Axo(int rel_x, int rel_y);
+ void set_Axo_scale(int rel_x, int rel_y, float axo_scale);
+ void set_Ortho(int rel_x, int rel_y);
+ int is_Ortho(int rel_x, int rel_y);
+ bool get_Axo(int rel_x, int rel_y, int & axo, gp_Dir & up, gp_Dir & right, bool & away, bool & tri, float & axo_scale);
+ void auto_dims(bool setting);
+ void set_configs(float configs[5]);
+ void get_configs(float configs[5]);
+
+private:
+ void set_orientation(int index);
+ void load_page(); // get page / titleblock dims from template
+ void choose_page(); // determine correct portion of page to use to avoid interference with title block
+ void set_all_orientations(); // update orientations of all views following change in primary view
+ void calc_layout_size(); // what's the real world size of chosen layout, excluding spaces
+ void calc_offsets();
+ void set_views();
+ void calc_scale();
+ void process_views();
+ int index(int rel_x, int rel_y);
+
+private:
+ vector views;
+ Base::BoundBox3d bbox;
+ App::Document * parent_doc;
+ App::DocumentObject * part;
+ App::DocumentObject * page;
+
+ string page_name, part_name;
+
+ int large[4]; // arrays containing page size info [margin_x, margin_y, size_x, size_y] = [x1, y1, x2-x1, y2-y1]
+ int small_h[4], small_v[4]; // page size avoiding title block, using maximum horizontal / vertical space
+ int * page_dims; // points to one of above arrays for which set of page dimensions to use
+ int block[4]; // title block info [corner x, corner y, width, height], eg [-1, 1, w, h] is in top left corner
+ bool title;
+ int * horiz, * vert; // points to min or max r_x / r_y depending upon which corner title block is in
+
+ int rotate_coeff; // 1st (= -1) or 3rd (= 1) angle
+ int min_r_x, max_r_x; // extreme relative positions of views
+ int min_r_y, max_r_y; // " " "
+ float width, height, depth; // of non-scaled primary view
+ float layout_width, layout_height; // of non-scaled layout without spaces
+ float gap_x, gap_y, min_space; // required spacing between views
+ float offset_x, offset_y; // coords of centre of upper left view
+ float scale;
+ int num_gaps_x, num_gaps_y; // how many gaps between views/edges? = num of views in given direction + 1
+ gp_Ax2 primary; // coord system of primary view
+
+ bool hidden, smooth;
+ bool autodims;
+};
+
+
class TaskOrthoViews : public QWidget//: public Gui::TaskView::TaskBox
@@ -85,68 +159,41 @@ class TaskOrthoViews : public QWidget//: public Gui::TaskView::TaskBox
TaskOrthoViews(QWidget *parent = 0);
~TaskOrthoViews();
bool user_input();
- void clean_up(bool);
+ void clean_up();
protected Q_SLOTS:
- void setPrimary(int);
- void setRotate(int);
- void cb_toggled(bool);
- void projectionChanged(int);
- void hidden(int);
- void smooth(int);
- void toggle_auto(int);
- void data_entered();
- void axoChanged(int);
- void axoTopChanged(int);
- void axo_flip();
- void axoScale();
+ void ShowContextMenu(const QPoint & pos);
+ void setPrimary(int dir);
+ void cb_toggled(bool toggle);
+ void projectionChanged(int index);
+ void hidden(int i);
+ void smooth(int i);
+ void toggle_auto(int i);
+ void data_entered(const QString & text);
+ void change_axo(int p = 3);
+ void axo_button();
+ void axo_scale(const QString & text);
+ void text_return();
protected:
- void changeEvent(QEvent *);
+ void changeEvent(QEvent * e);
private:
- void pagesize(std::string&);
- void autodims();
- void compute();
- void validate_cbs();
- void view_data(int, int, int &, int &);
- void updateSecondaries();
- void set_axo();
+ void setup_axo_tab();
+ void set_configs();
private:
- class Private;
+ //class Private;
Ui_TaskOrthoViews * ui;
- orthoView * views[4];
- QCheckBox * c_boxes[5][5]; //matrix of pointers to gui checkboxes
- QLineEdit * inputs[5]; //pointers to manual position/scale boxes
- float * data[5]; //pointers to scale, x_pos, y_pos, horiz, vert
-
- int map1[4][3][2]; //contains view directions and rotations for vertical secondary positions, for primaries 1,2,3,4
- int map2[4][3][2]; //contains view directions and rotations for H and V secondary positions, primaries 5,6
- float axonometric[3][6][4][4]; //contains view direction vectors and rotations for axonometric views
-
- int view_status[4][4]; //matrix containing status of four orthoView objects (in use, axo, rel x, rel y)
- int view_count; //number of active views
-
- int primary; //view direction of primary view
- float x_pos, y_pos; //x and y coords for primary view
- int rotate; //rotate primary view clockwise by rotate*90
- int proj; //first (=-1) or third (=1) angle projection
- float scale; //scale of drawing
- bool autoscale; //whether or not to run autodims
-
- float horiz, vert; //centre-centre distances
-
- bool axo_flipped;
- int axo;
-
- float pagewidth, pageheight; //these are actually the available width and height, calculated in constructor.
- float pageh1, pageh2; //h1 - total usable page height, h2 - total height allowing for info box.
- int margin;
- int min_space; //minimum space between views, and page edge
-};
+ OrthoViews * orthos;
+ QCheckBox * c_boxes[5][5]; // matrix of pointers to gui checkboxes
+ QLineEdit * inputs[5]; // pointers to manual position/scale boxes
+ float data[5]; // scale, x_pos, y_pos, horiz, vert
+ int axo_r_x, axo_r_y; // relative position of axo view currently being edited
+ bool txt_return; // flag to show if return was pressed while editing a text box;
+};
//////////////////////////////////////////////////////////////
@@ -162,20 +209,15 @@ class TaskDlgOrthoViews : public Gui::TaskView::TaskDialog
TaskDlgOrthoViews();
~TaskDlgOrthoViews();
-
public:
void open();
bool accept();
bool reject();
void clicked(int);
-// QDialogButtonBox::StandardButtons getStandardButtons() const
-// { return QDialogButtonBox::Ok|QDialogButtonBox::Cancel; }
-
private:
TaskOrthoViews * widget;
Gui::TaskView::TaskBox* taskbox;
-
};
} //namespace DrawingGui
diff --git a/src/Mod/Drawing/Gui/TaskOrthoViews.ui b/src/Mod/Drawing/Gui/TaskOrthoViews.ui
index 33d9e4b92305..1c0d07f53c32 100644
--- a/src/Mod/Drawing/Gui/TaskOrthoViews.ui
+++ b/src/Mod/Drawing/Gui/TaskOrthoViews.ui
@@ -6,8 +6,8 @@
0
0
- 259
- 496
+ 250
+ 486
@@ -31,7 +31,7 @@
-
- false
+ true
@@ -39,6 +39,12 @@
0
+
+ Qt::CustomContextMenu
+
+
+ Right click for axonometric settings
+
Qt::RightToLeft
@@ -50,7 +56,7 @@
-
- false
+ true
@@ -58,6 +64,12 @@
0
+
+ Qt::CustomContextMenu
+
+
+ Right click for axonometric settings
+
Qt::RightToLeft
@@ -69,7 +81,7 @@
-
- false
+ true
@@ -77,6 +89,12 @@
0
+
+ Qt::CustomContextMenu
+
+
+ Right click for axonometric settings
+
Qt::RightToLeft
@@ -88,7 +106,7 @@
-
- false
+ true
@@ -96,6 +114,12 @@
0
+
+ Qt::CustomContextMenu
+
+
+ Right click for axonometric settings
+
Qt::RightToLeft
@@ -107,7 +131,7 @@
-
- false
+ true
@@ -115,6 +139,12 @@
0
+
+ Qt::CustomContextMenu
+
+
+ Right click for axonometric settings
+
Qt::RightToLeft
@@ -132,7 +162,7 @@
-
- false
+ true
@@ -140,6 +170,12 @@
0
+
+ Qt::CustomContextMenu
+
+
+ Right click for axonometric settings
+
Qt::RightToLeft
@@ -151,7 +187,7 @@
-
- false
+ true
@@ -159,6 +195,12 @@
0
+
+ Qt::CustomContextMenu
+
+
+ Right click for axonometric settings
+
Qt::RightToLeft
@@ -170,7 +212,7 @@
-
- false
+ true
@@ -178,6 +220,12 @@
0
+
+ Qt::CustomContextMenu
+
+
+ Right click for axonometric settings
+
Qt::RightToLeft
@@ -189,7 +237,7 @@
-
- false
+ true
@@ -197,6 +245,12 @@
0
+
+ Qt::CustomContextMenu
+
+
+ Right click for axonometric settings
+
Qt::RightToLeft
@@ -208,7 +262,7 @@
-
- false
+ true
@@ -216,6 +270,12 @@
0
+
+ Qt::CustomContextMenu
+
+
+ Right click for axonometric settings
+
Qt::RightToLeft
@@ -227,7 +287,7 @@
-
- false
+ true
@@ -235,6 +295,12 @@
0
+
+ Qt::CustomContextMenu
+
+
+ Right click for axonometric settings
+
Qt::RightToLeft
@@ -264,7 +330,7 @@
- false
+ true
@@ -281,7 +347,7 @@
-
- false
+ true
@@ -289,6 +355,12 @@
0
+
+ Qt::CustomContextMenu
+
+
+ Right click for axonometric settings
+
Qt::RightToLeft
@@ -393,7 +465,7 @@
false
- Primary x / y
+ Top left x / y
2
@@ -441,7 +513,7 @@
false
- Secondary dx / dy
+ Spacing dx / dy
2
@@ -507,8 +579,59 @@
Axonometric
-
-
+
-
+
-
+
+
+ Axis out and right
+
+
+
+ -
+
+
+ Vertical tilt
+
+
+
+ -
+
+
+ true
+
+
-
+
+ X +ve
+
+
+ -
+
+ Y +ve
+
+
+ -
+
+ Z +ve
+
+
+ -
+
+ X -ve
+
+
+ -
+
+ Y -ve
+
+
+ -
+
+ Z -ve
+
+
+
+
-
@@ -531,17 +654,7 @@
- -
-
-
- false
-
-
- Switch direction
-
-
-
- -
+
-
Scale
@@ -558,95 +671,77 @@
-
- Top face
+ Axis aligned up
- -
-
-
- Left face
-
-
-
- -
-
+
-
+
true
-
- Front
+ Y +ve
-
- Right
+ Z +ve
-
- Back
+ Y -ve
-
- Left
-
-
- -
-
- Top
-
-
- -
-
- Bottom
+ Z -ve
- -
-
+
-
+
true
-
-
-
- Right
-
-
- -
-
- Left
-
-
- -
-
- Top
-
-
- -
-
- Bottom
-
-
-
-
-
+
+
+ Flip
+
+
true
+
+ false
+
- -
+
-
Trimetric
+ -
+
+
+ false
+
+
+ Flip
+
+
+ true
+
+
+
@@ -693,12 +788,12 @@
-
- Primary View
+ View from:
-
-
+
QComboBox::AdjustToContentsOnFirstShow
@@ -707,37 +802,32 @@
-
-
-
-
- -
-
- Front
+ X +ve
-
- Right
+ Y +ve
-
- Back
+ Z +ve
-
- Left
+ X -ve
-
- Top
+ Y -ve
-
- Bottom
+ Z -ve
@@ -745,33 +835,33 @@
-
- - Rotate
+ Axis aligned right:
- Qt::AlignCenter
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
-
-
+
-
- 0
+ Y +ve
-
- 90
+ Z +ve
-
- 180
+ Y -ve
-
- 270
+ Z -ve
diff --git a/src/Mod/Drawing/Templates/A3_Landscape.svg b/src/Mod/Drawing/Templates/A3_Landscape.svg
index d30384799b13..9d2535ac6832 100644
--- a/src/Mod/Drawing/Templates/A3_Landscape.svg
+++ b/src/Mod/Drawing/Templates/A3_Landscape.svg
@@ -18,6 +18,8 @@
inkscape:version="0.48.1 r9760"
sodipodi:docname="A3_Landscape.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
+
+
diff --git a/src/Mod/Drawing/Templates/A4_Landscape.svg b/src/Mod/Drawing/Templates/A4_Landscape.svg
index 018c614dc3ab..dcc5ae73e395 100644
--- a/src/Mod/Drawing/Templates/A4_Landscape.svg
+++ b/src/Mod/Drawing/Templates/A4_Landscape.svg
@@ -17,6 +17,8 @@
inkscape:version="0.47 r22583"
sodipodi:docname="A4_Landscape.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
+
+
diff --git a/src/Mod/Plot/InitGui.py b/src/Mod/Plot/InitGui.py
index 2afc60afae4e..c72e1dfa66a9 100644
--- a/src/Mod/Plot/InitGui.py
+++ b/src/Mod/Plot/InitGui.py
@@ -1,7 +1,7 @@
#***************************************************************************
#* *
-#* Copyright (c) 2011, 2012 *
-#* Jose Luis Cercos Pita *
+#* Copyright (c) 2011, 2012 *
+#* Jose Luis Cercos Pita *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
@@ -21,26 +21,42 @@
#* *
#***************************************************************************
-class PlotWorkbench ( Workbench ):
- """ @brief Workbench of Plot module. Here toolbars & icons are append. """
- from plotUtils import Paths
- import PlotGui
- Icon = 'Icon.svg'
- MenuText = "Plot"
- ToolTip = "The Plot module is used to edit/save output plots performed by other tools"
+class PlotWorkbench(Workbench):
+ """Workbench of Plot module."""
+ from plotUtils import Paths
+ import PlotGui
+
+ Icon = 'Icon.svg'
+ MenuText = "Plot"
+ ToolTip = ("The Plot module is used to edit/save output plots performed "
+ "by other tools")
+
+ def Initialize(self):
+ from PySide import QtCore, QtGui
+ cmdlst = ["Plot_SaveFig",
+ "Plot_Axes",
+ "Plot_Series",
+ "Plot_Grid",
+ "Plot_Legend",
+ "Plot_Labels",
+ "Plot_Positions"]
+ self.appendToolbar(str(QtCore.QT_TRANSLATE_NOOP(
+ "Plot",
+ "Plot edition tools")), cmdlst)
+ self.appendMenu(str(QtCore.QT_TRANSLATE_NOOP(
+ "Plot",
+ "Plot")), cmdlst)
+ try:
+ import matplotlib
+ except ImportError:
+ from PySide import QtCore, QtGui
+ msg = QtGui.QApplication.translate(
+ "plot_console",
+ "matplotlib not found, Plot module will be disabled",
+ None,
+ QtGui.QApplication.UnicodeUTF8)
+ FreeCAD.Console.PrintMessage(msg + '\n')
- def Initialize(self):
- from PyQt4 import QtCore, QtGui
- cmdlst = ["Plot_SaveFig", "Plot_Axes", "Plot_Series", "Plot_Grid", "Plot_Legend", "Plot_Labels", "Plot_Positions"]
- self.appendToolbar(str(QtCore.QT_TRANSLATE_NOOP("Plot", "Plot edition tools")),cmdlst)
- self.appendMenu(str(QtCore.QT_TRANSLATE_NOOP("Plot", "Plot")),cmdlst)
- try:
- import matplotlib
- except ImportError:
- from PyQt4 import QtCore, QtGui
- msg = QtGui.QApplication.translate("plot_console", "matplotlib not found, Plot module will be disabled",
- None,QtGui.QApplication.UnicodeUTF8)
- FreeCAD.Console.PrintMessage(msg + '\n')
Gui.addWorkbench(PlotWorkbench())
diff --git a/src/Mod/Plot/Plot.py b/src/Mod/Plot/Plot.py
index c943363a6072..95b3bcd2cc52 100644
--- a/src/Mod/Plot/Plot.py
+++ b/src/Mod/Plot/Plot.py
@@ -1,7 +1,7 @@
#***************************************************************************
#* *
-#* Copyright (c) 2011, 2012 *
-#* Jose Luis Cercos Pita *
+#* Copyright (c) 2011, 2012 *
+#* Jose Luis Cercos Pita *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
@@ -21,301 +21,409 @@
#* *
#***************************************************************************
-# FreeCAD
import FreeCAD
-# PyQt4
-from PyQt4 import QtCore, QtGui
+import PySide
+from PySide import QtCore, QtGui
-# Matplot lib
try:
- import matplotlib
- import matplotlib.pyplot as plt
- from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
- from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar
- from matplotlib.figure import Figure
+ import matplotlib
+ matplotlib.use('Qt4Agg')
+ matplotlib.rcParams['backend.qt4']='PySide'
+ import matplotlib.pyplot as plt
+ from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
+ from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar
+ from matplotlib.figure import Figure
except ImportError:
- msg = QtGui.QApplication.translate("plot_console", "matplotlib not found, so Plot module can not be loaded",
- None,QtGui.QApplication.UnicodeUTF8)
- FreeCAD.Console.PrintMessage(msg + '\n')
- raise ImportError("matplotlib not installed")
+ msg = QtGui.QApplication.translate(
+ "plot_console",
+ "matplotlib not found, so Plot module can not be loaded",
+ None,
+ QtGui.QApplication.UnicodeUTF8)
+ FreeCAD.Console.PrintMessage(msg + '\n')
+ raise ImportError("matplotlib not installed")
+
def getMainWindow():
- """ getMainWindow(): Gets FreeCAD main window. """
- toplevel = QtGui.qApp.topLevelWidgets()
- for i in toplevel:
- if i.metaObject().className() == "Gui::MainWindow":
- return i
- return None
+ """ Return the FreeCAD main window. """
+ toplevel = QtGui.qApp.topLevelWidgets()
+ for i in toplevel:
+ if i.metaObject().className() == "Gui::MainWindow":
+ return i
+ return None
+
def getMdiArea():
- """ getMdiArea(): Gets FreeCAD MdiArea. """
- mw = getMainWindow()
- if not mw:
- return None
- return mw.findChild(QtGui.QMdiArea)
+ """ Return FreeCAD MdiArea. """
+ mw = getMainWindow()
+ if not mw:
+ return None
+ childs = mw.children()
+ for c in childs:
+ if isinstance(c, PySide.QtGui.QMdiArea):
+ return c
+ return None
+
def getPlot():
- """ getPlot(): Gets selected Plot document if exist. """
- # Get active tab
- mdi = getMdiArea()
- if not mdi:
- return None
- sub = mdi.activeSubWindow()
- if not sub:
- return None
- # Explore childrens looking for Plot class
- for i in sub.children():
- if i.metaObject().className() == "Plot":
- return i
- return None
+ """ Return the selected Plot document if exist. """
+ # Get active tab
+ mdi = getMdiArea()
+ if not mdi:
+ return None
+ sub = mdi.activeSubWindow()
+ if not sub:
+ return None
+ # Explore childrens looking for Plot class
+ for i in sub.children():
+ if i.metaObject().className() == "Plot":
+ return i
+ return None
+
def figure(winTitle="plot"):
- """ figure(winTitle="plot"): Create a new plot subwindow.\n winTitle = Tab title. """
- mdi = getMdiArea()
- if not mdi:
- return None
- win = Plot(winTitle)
- sub=mdi.addSubWindow(win)
- sub.show()
- return win
-
-def plot(x,y,name=None):
- """ plot(x,y,name=None): Plots a new serie (as line plot)\n x = X values\n y = Y values\n name = Serie name (for legend). """
- # Get active plot, or create another one if don't exist
- plt = getPlot()
- if not plt:
- plt = figure()
- # Call to plot
- return plt.plot(x,y,name)
+ """Create a new plot subwindow/tab.
+
+ Keyword arguments:
+ winTitle -- Plot tab title.
+ """
+ mdi = getMdiArea()
+ if not mdi:
+ return None
+ win = Plot(winTitle)
+ sub = mdi.addSubWindow(win)
+ sub.show()
+ return win
+
+
+def plot(x, y, name=None):
+ """Plots a new serie (as line plot)
+
+ Keyword arguments:
+ x -- X values
+ y -- Y values
+ name -- Data serie name (for legend).
+ """
+ # Get active plot, or create another one if don't exist
+ plt = getPlot()
+ if not plt:
+ plt = figure()
+ # Call to plot
+ return plt.plot(x, y, name)
+
def series():
- """ lines(): Get all lines from selected plot. """
- plt = getPlot()
- if not plt:
- return []
- return plt.series
+ """Return all the lines from a selected plot."""
+ plt = getPlot()
+ if not plt:
+ return []
+ return plt.series
+
def removeSerie(index):
- """ removeSerie(index): Removes a serie from plot.\n index = Index of serie to remove. """
- # Get active series
- plt = getPlot()
- if not plt:
- return
- plots = plt.series
- if not plots:
- return
- # Remove line from plot
- axes = plots[index].axes
- axes.lines.pop(plots[index].lid)
- # Remove serie from list
- del plt.series[index]
- # Update GUI
- plt.update()
+ """Remove a data serie from the active plot.
+
+ Keyword arguments:
+ index -- Index of the serie to remove.
+ """
+ # Get active series
+ plt = getPlot()
+ if not plt:
+ return
+ plots = plt.series
+ if not plots:
+ return
+ # Remove line from plot
+ axes = plots[index].axes
+ axes.lines.pop(plots[index].lid)
+ # Remove serie from list
+ del plt.series[index]
+ # Update GUI
+ plt.update()
+
def legend(status=True, pos=None, fontsize=None):
- """ legend(status=True): Show/Hide legend.\n status = True if legend must be shown, False otherwise.\n pos = Legend position.\n fontsize = Font size """
- plt = getPlot()
- if not plt:
- return
- plt.legend = status
- if fontsize:
- plt.legSiz = fontsize
- # Hide all legends
- for axes in plt.axesList:
- axes.legend_ = None
- # Legend must be activated on last axes
- axes = plt.axesList[-1]
- if status:
- # Setup legend handles and names
- lines = series()
- handles = []
- names = []
- for l in lines:
- if l.name != None:
- handles.append(l.line)
- names.append(l.name)
- # Show the legend (at selected position or at best)
- if pos:
- l = axes.legend(handles, names, bbox_to_anchor=pos)
- plt.legPos = pos
- else:
- l = axes.legend(handles, names, loc='best')
- # Update canvas in order to compute legend data
- plt.canvas.draw()
- # Get resultant position
- fax = axes.get_frame().get_extents()
- fl = l.get_frame()
- plt.legPos = ((fl._x+fl._width-fax.x0) / fax.width, (fl._y+fl._height-fax.y0) / fax.height)
- # Set fontsize
- for t in l.get_texts():
- t.set_fontsize(plt.legSiz)
- plt.update()
+ """Show/Hide the legend from the active plot.
+
+ Keyword arguments:
+ status -- True if legend must be shown, False otherwise.
+ pos -- Legend position.
+ fontsize -- Font size
+ """
+ plt = getPlot()
+ if not plt:
+ return
+ plt.legend = status
+ if fontsize:
+ plt.legSiz = fontsize
+ # Hide all legends
+ for axes in plt.axesList:
+ axes.legend_ = None
+ # Legend must be activated on last axes
+ axes = plt.axesList[-1]
+ if status:
+ # Setup legend handles and names
+ lines = series()
+ handles = []
+ names = []
+ for l in lines:
+ if l.name is not None:
+ handles.append(l.line)
+ names.append(l.name)
+ # Show the legend (at selected position or at best)
+ if pos:
+ l = axes.legend(handles, names, bbox_to_anchor=pos)
+ plt.legPos = pos
+ else:
+ l = axes.legend(handles, names, loc='best')
+ # Update canvas in order to compute legend data
+ plt.canvas.draw()
+ # Get resultant position
+ fax = axes.get_frame().get_extents()
+ fl = l.get_frame()
+ plt.legPos = (
+ (fl._x + fl._width - fax.x0) / fax.width,
+ (fl._y + fl._height - fax.y0) / fax.height)
+ # Set fontsize
+ for t in l.get_texts():
+ t.set_fontsize(plt.legSiz)
+ plt.update()
+
def grid(status=True):
- """ grid(status=True): Show/Hide grid.\n status = True if grid must be shown, False otherwise. """
- plt = getPlot()
- if not plt:
- return
- plt.grid = status
- axes = plt.axes
- axes.grid(status)
- plt.update()
+ """Show/Hide the grid from the active plot.
+
+ Keyword arguments:
+ status -- True if grid must be shown, False otherwise.
+ """
+ plt = getPlot()
+ if not plt:
+ return
+ plt.grid = status
+ axes = plt.axes
+ axes.grid(status)
+ plt.update()
+
def title(string):
- """ title(string): Setup plot title.\n string = Title to set. """
- plt = getPlot()
- if not plt:
- return
- axes = plt.axes
- axes.set_title(string)
- plt.update()
+ """Setup the plot title.
+
+ Keyword arguments:
+ string -- Plot title.
+ """
+ plt = getPlot()
+ if not plt:
+ return
+ axes = plt.axes
+ axes.set_title(string)
+ plt.update()
+
def xlabel(string):
- """ xlabel(string): Setup x label.\n string = Title to set. """
- plt = getPlot()
- if not plt:
- return
- axes = plt.axes
- axes.set_xlabel(string)
- plt.update()
+ """Setup the x label.
+
+ Keyword arguments:
+ string -- Title to set.
+ """
+ plt = getPlot()
+ if not plt:
+ return
+ axes = plt.axes
+ axes.set_xlabel(string)
+ plt.update()
+
def ylabel(string):
- """ ylabel(string): Setup y label.\n string = Title to set. """
- plt = getPlot()
- if not plt:
- return
- axes = plt.axes
- axes.set_ylabel(string)
- plt.update()
+ """Setup the y label.
+
+ Keyword arguments:
+ string -- Title to set.
+ """
+ plt = getPlot()
+ if not plt:
+ return
+ axes = plt.axes
+ axes.set_ylabel(string)
+ plt.update()
+
def axesList():
- """ axesList(): Gets plot axes list. """
- plt = getPlot()
- if not plt:
- return []
- return plt.axesList
+ """Return the plot axes sets list. """
+ plt = getPlot()
+ if not plt:
+ return []
+ return plt.axesList
+
def axes():
- """ axes(): Gets active plot axes. """
- plt = getPlot()
- if not plt:
- return None
- return plt.axes
+ """Return the active plot axes."""
+ plt = getPlot()
+ if not plt:
+ return None
+ return plt.axes
+
def addNewAxes(rect=None, frameon=True, patchcolor='none'):
- """ addNewAxes(pos=None, frameon=True): Add new axes to plot, setting it as active one.\n rect = Axes area, None to copy last axes data.\n frameon = True to show frame, False otherwise.\n patchcolor = Patch color, 'none' for transparent plot. """
- plt = getPlot()
- if not plt:
- return None
- fig = plt.fig
- if rect == None:
- rect = plt.axes.get_position()
- ax = fig.add_axes(rect, frameon=frameon)
- ax.xaxis.set_ticks_position('bottom')
- ax.spines['top'].set_color('none')
- ax.yaxis.set_ticks_position('left')
- ax.spines['right'].set_color('none')
- ax.patch.set_facecolor(patchcolor)
- plt.axesList.append(ax)
- plt.setActiveAxes(-1)
- plt.update()
- return ax
+ """Add new axes to plot, setting it as the active one.
+
+ Keyword arguments:
+ rect -- Axes area, None to copy from the last axes data.
+ frameon -- True to show frame, False otherwise.
+ patchcolor -- Patch color, 'none' for transparent plot.
+ """
+ plt = getPlot()
+ if not plt:
+ return None
+ fig = plt.fig
+ if rect is None:
+ rect = plt.axes.get_position()
+ ax = fig.add_axes(rect, frameon=frameon)
+ ax.xaxis.set_ticks_position('bottom')
+ ax.spines['top'].set_color('none')
+ ax.yaxis.set_ticks_position('left')
+ ax.spines['right'].set_color('none')
+ ax.patch.set_facecolor(patchcolor)
+ plt.axesList.append(ax)
+ plt.setActiveAxes(-1)
+ plt.update()
+ return ax
+
def save(path, figsize=None, dpi=None):
- """ save(path): Save plot.\n path = Destination file path.\n figsize = w,h figure size tuple in inches.\n dpi = Dots per inch."""
- plt = getPlot()
- if not plt:
- return
- # Backup figure options
- fig = plt.fig
- sizeBack = fig.get_size_inches()
- dpiBack = fig.get_dpi()
- # Save figure with new options
- if figsize:
- fig.set_size_inches(figsize[0], figsize[1])
- if dpi:
- fig.set_dpi(dpi)
- plt.canvas.print_figure(path)
- # Restore figure options
- fig.set_size_inches(sizeBack[0], sizeBack[1])
- fig.set_dpi(dpiBack)
- plt.update()
+ """Save plot.
+
+ Keyword arguments:
+ path -- Destination file path.
+ figsize -- w,h figure size tuple in inches.
+ dpi -- Dots per inch.
+ """
+ plt = getPlot()
+ if not plt:
+ return
+ # Backup figure options
+ fig = plt.fig
+ sizeBack = fig.get_size_inches()
+ dpiBack = fig.get_dpi()
+ # Save figure with new options
+ if figsize:
+ fig.set_size_inches(figsize[0], figsize[1])
+ if dpi:
+ fig.set_dpi(dpi)
+ plt.canvas.print_figure(path)
+ # Restore figure options
+ fig.set_size_inches(sizeBack[0], sizeBack[1])
+ fig.set_dpi(dpiBack)
+ plt.update()
+
class Line():
- def __init__(self, axes, x, y, name):
- """ __init__(axes, x, y, name): Construct new plot serie.\n axes = Active axes\n x = X values\n y = Y values\n name = Serie name (for legend). """
- self.axes = axes
- self.x = x
- self.y = y
- self.name = name
- self.lid = len(axes.lines)
- self.line, = axes.plot(x,y)
-
- def setp(self, prop, value):
- """ setp(prop, value): Change line property value.\n prop = Property name.\n value = New property value. """
- plt.setp(self.line, prop, value)
-
- def getp(self, prop):
- """ getp(prop): Get property value.\n prop = Property name."""
- return plt.getp(self.line, prop)
+ def __init__(self, axes, x, y, name):
+ """Construct a new plot serie.
+
+ Keyword arguments:
+ axes -- Active axes
+ x -- X values
+ y -- Y values
+ name -- Data serie name (for legend).
+ """
+ self.axes = axes
+ self.x = x
+ self.y = y
+ self.name = name
+ self.lid = len(axes.lines)
+ self.line, = axes.plot(x, y)
+
+ def setp(self, prop, value):
+ """Change a line property value.
+
+ Keyword arguments:
+ prop -- Property name.
+ value -- New property value.
+ """
+ plt.setp(self.line, prop, value)
+
+ def getp(self, prop):
+ """Get line property value.
+
+ Keyword arguments:
+ prop -- Property name.
+ """
+ return plt.getp(self.line, prop)
+
class Plot(QtGui.QWidget):
- def __init__(self, winTitle="plot", parent = None, flags = QtCore.Qt.WindowFlags(0)):
- """ __init__(winTitle="plot", parent = None, flags = Qt.WindowFlags(0)): Construct a new plot widget.\n winTitle = Tab title.\n parent = Widget parent.\n flags = QWidget flags"""
- QtGui.QWidget.__init__(self, parent, flags)
- self.setWindowTitle(winTitle)
- # Create matplotlib canvas
- self.fig = Figure()
- self.canvas = FigureCanvas(self.fig)
- self.canvas.setParent(self)
- # Get axes
- self.axes = self.fig.add_subplot(111)
- self.axesList = [self.axes]
- self.axes.xaxis.set_ticks_position('bottom')
- self.axes.spines['top'].set_color('none')
- self.axes.yaxis.set_ticks_position('left')
- self.axes.spines['right'].set_color('none')
- # Setup layout
- vbox = QtGui.QVBoxLayout()
- vbox.addWidget(self.canvas)
- self.setLayout(vbox)
- # Active series
- self.series = []
- # Indicators
- self.skip = False
- self.legend = False
- self.legPos = (1.0,1.0)
- self.legSiz = 14
- self.grid = False
-
- def plot(self, x, y, name=None):
- """ plot(self, x, y, name=None): Plot a new line and return it.\n x = X values\n y = Y values\n name = Serie name (for legend). """
- l = Line(self.axes, x, y, name)
- self.series.append(l)
- # Update window
- self.update()
- return l
-
- def update(self):
- """ update(): Updates plot. """
- if not self.skip:
- self.skip = True
- if self.legend:
- legend(self.legend, self.legPos, self.legSiz)
- self.canvas.draw()
- self.skip = False
-
- def isGrid(self):
- """ isGrid(): Return True if Grid is active, False otherwise. """
- return bool(self.grid)
-
- def isLegend(self):
- """ isLegend(): Return True if Legend is active, False otherwise. """
- return bool(self.legend)
-
- def setActiveAxes(self, index):
- """ setActiveAxes(index): Change current active axes.\n index = Index of the new active axes. """
- self.axes = self.axesList[index]
- self.fig.sca(self.axes)
+ def __init__(self,
+ winTitle="plot",
+ parent=None,
+ flags=QtCore.Qt.WindowFlags(0)):
+ """Construct a new plot widget.
+
+ Keyword arguments:
+ winTitle -- Tab title.
+ parent -- Widget parent.
+ flags -- QWidget flags
+ """
+ QtGui.QWidget.__init__(self, parent, flags)
+ self.setWindowTitle(winTitle)
+ # Create matplotlib canvas
+ self.fig = Figure()
+ self.canvas = FigureCanvas(self.fig)
+ self.canvas.setParent(self)
+ # Get axes
+ self.axes = self.fig.add_subplot(111)
+ self.axesList = [self.axes]
+ self.axes.xaxis.set_ticks_position('bottom')
+ self.axes.spines['top'].set_color('none')
+ self.axes.yaxis.set_ticks_position('left')
+ self.axes.spines['right'].set_color('none')
+ # Setup layout
+ vbox = QtGui.QVBoxLayout()
+ vbox.addWidget(self.canvas)
+ self.setLayout(vbox)
+ # Active series
+ self.series = []
+ # Indicators
+ self.skip = False
+ self.legend = False
+ self.legPos = (1.0, 1.0)
+ self.legSiz = 14
+ self.grid = False
+
+ def plot(self, x, y, name=None):
+ """Plot a new line and return it.
+
+ Keyword arguments:
+ x -- X values
+ y -- Y values
+ name -- Serie name (for legend). """
+ l = Line(self.axes, x, y, name)
+ self.series.append(l)
+ # Update window
+ self.update()
+ return l
+
+ def update(self):
+ """Update the plot, redrawing the canvas."""
+ if not self.skip:
+ self.skip = True
+ if self.legend:
+ legend(self.legend, self.legPos, self.legSiz)
+ self.canvas.draw()
+ self.skip = False
+
+ def isGrid(self):
+ """Return True if Grid is active, False otherwise."""
+ return bool(self.grid)
+
+ def isLegend(self):
+ """Return True if Legend is active, False otherwise."""
+ return bool(self.legend)
+
+ def setActiveAxes(self, index):
+ """Change the current active axes.
+ Keyword arguments:
+ index -- Index of the new active axes set.
+ """
+ self.axes = self.axesList[index]
+ self.fig.sca(self.axes)
diff --git a/src/Mod/Plot/PlotGui.py b/src/Mod/Plot/PlotGui.py
index 0f7a3c639edc..189545522063 100644
--- a/src/Mod/Plot/PlotGui.py
+++ b/src/Mod/Plot/PlotGui.py
@@ -1,7 +1,7 @@
#***************************************************************************
#* *
-#* Copyright (c) 2011, 2012 *
-#* Jose Luis Cercos Pita *
+#* Copyright (c) 2011, 2012 *
+#* Jose Luis Cercos Pita *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
@@ -21,126 +21,163 @@
#* *
#***************************************************************************
-from PyQt4 import QtCore, QtGui
-import FreeCAD, FreeCADGui, os
+import PySide
+from PySide import QtCore, QtGui
+import FreeCAD
+import FreeCADGui
+import os
-# Load resources
import Plot_rc
+
+
FreeCADGui.addLanguagePath(":/Plot/translations")
FreeCADGui.addIconPath(":/Plot/icons")
-"""
-# Setup tranlations
-from plotUtils import Paths
-path = Paths.translationsPath()
-FreeCADGui.addLanguagePath(path)
-import os
-import FreeCAD
-translator = QtCore.QTranslator()
-dirList=os.listdir(path)
-for fname in dirList:
- valid = translator.load(os.path.join(path, fname))
- if valid:
- QtGui.QApplication.installTranslator(translator)
-"""
-
-class Save:
- def Activated(self):
- import plotSave
- plotSave.load()
-
- def GetResources(self):
- # from plotUtils import Paths
- # IconPath = Paths.iconsPath() + "/Save.svg"
- MenuText = QtCore.QT_TRANSLATE_NOOP("Plot_SaveFig", "Save plot")
- ToolTip = QtCore.QT_TRANSLATE_NOOP("Plot_SaveFig", "Save plot as image file")
- return {'Pixmap' : 'Save', 'MenuText': MenuText, 'ToolTip': ToolTip}
-
-class Axes:
- def Activated(self):
- import plotAxes
- plotAxes.load()
-
- def GetResources(self):
- # from plotUtils import Paths
- # IconPath = Paths.iconsPath() + "/Axes.svg"
- MenuText = QtCore.QT_TRANSLATE_NOOP("Plot_Axes", "Configure axes")
- ToolTip = QtCore.QT_TRANSLATE_NOOP("Plot_Axes", "Configure axes parameters")
- return {'Pixmap' : 'Axes', 'MenuText': MenuText, 'ToolTip': ToolTip}
-
-class Series:
- def Activated(self):
- import plotSeries
- plotSeries.load()
-
- def GetResources(self):
- # from plotUtils import Paths
- # IconPath = Paths.iconsPath() + "/Series.svg"
- MenuText = QtCore.QT_TRANSLATE_NOOP("Plot_Series", "Configure series")
- ToolTip = QtCore.QT_TRANSLATE_NOOP("Plot_Series", "Configure series drawing style and label")
- return {'Pixmap' : 'Series', 'MenuText': MenuText, 'ToolTip': ToolTip}
-
-class Grid:
- def Activated(self):
- import Plot
- plt = Plot.getPlot()
- if not plt:
- msg = QtGui.QApplication.translate("plot_console", "Grid must be activated on top of a plot document",
- None,QtGui.QApplication.UnicodeUTF8)
- FreeCAD.Console.PrintError(msg+"\n")
- return
- flag = plt.isGrid()
- Plot.grid(not flag)
-
- def GetResources(self):
- # from plotUtils import Paths
- # IconPath = Paths.iconsPath() + "/Grid.svg"
- MenuText = QtCore.QT_TRANSLATE_NOOP("Plot_Grid", "Show/Hide grid")
- ToolTip = QtCore.QT_TRANSLATE_NOOP("Plot_Grid", "Show/Hide grid on selected plot")
- return {'Pixmap' : 'Grid', 'MenuText': MenuText, 'ToolTip': ToolTip}
-
-class Legend:
- def Activated(self):
- import Plot
- plt = Plot.getPlot()
- if not plt:
- msg = QtGui.QApplication.translate("plot_console", "Legend must be activated on top of a plot document",
- None,QtGui.QApplication.UnicodeUTF8)
- FreeCAD.Console.PrintError(msg+"\n")
- return
- flag = plt.isLegend()
- Plot.legend(not flag)
-
- def GetResources(self):
- # from plotUtils import Paths
- # IconPath = Paths.iconsPath() + "/Legend.svg"
- MenuText = QtCore.QT_TRANSLATE_NOOP("Plot_Legend", "Show/Hide legend")
- ToolTip = QtCore.QT_TRANSLATE_NOOP("Plot_Legend", "Show/Hide legend on selected plot")
- return {'Pixmap' : 'Legend', 'MenuText': MenuText, 'ToolTip': ToolTip}
-
-class Labels:
- def Activated(self):
- import plotLabels
- plotLabels.load()
-
- def GetResources(self):
- # from plotUtils import Paths
- # IconPath = Paths.iconsPath() + "/Labels.svg"
- MenuText = QtCore.QT_TRANSLATE_NOOP("Plot_Labels", "Set labels")
- ToolTip = QtCore.QT_TRANSLATE_NOOP("Plot_Labels", "Set title and axes labels")
- return {'Pixmap' : 'Labels', 'MenuText': MenuText, 'ToolTip': ToolTip}
-
-class Positions:
- def Activated(self):
- import plotPositions
- plotPositions.load()
-
- def GetResources(self):
- # from plotUtils import Paths
- # IconPath = Paths.iconsPath() + "/Positions.svg"
- MenuText = QtCore.QT_TRANSLATE_NOOP("Plot_Positions", "Set positions and sizes")
- ToolTip = QtCore.QT_TRANSLATE_NOOP("Plot_Positions", "Set labels and legend positions and sizes")
- return {'Pixmap' : 'Positions', 'MenuText': MenuText, 'ToolTip': ToolTip}
+
+class Save:
+ def Activated(self):
+ import plotSave
+ plotSave.load()
+
+ def GetResources(self):
+ # from plotUtils import Paths
+ # IconPath = Paths.iconsPath() + "/Save.svg"
+ MenuText = QtCore.QT_TRANSLATE_NOOP(
+ "Plot_SaveFig",
+ "Save plot")
+ ToolTip = QtCore.QT_TRANSLATE_NOOP(
+ "Plot_SaveFig",
+ "Save the plot as an image file")
+ return {'Pixmap': 'Save',
+ 'MenuText': MenuText,
+ 'ToolTip': ToolTip}
+
+
+class Axes:
+ def Activated(self):
+ import plotAxes
+ plotAxes.load()
+
+ def GetResources(self):
+ MenuText = QtCore.QT_TRANSLATE_NOOP(
+ "Plot_Axes",
+ "Configure axes")
+ ToolTip = QtCore.QT_TRANSLATE_NOOP(
+ "Plot_Axes",
+ "Configure the axes parameters")
+ return {'Pixmap': 'Axes',
+ 'MenuText': MenuText,
+ 'ToolTip': ToolTip}
+
+
+class Series:
+ def Activated(self):
+ import plotSeries
+ plotSeries.load()
+
+ def GetResources(self):
+ # from plotUtils import Paths
+ # IconPath = Paths.iconsPath() + "/Series.svg"
+ MenuText = QtCore.QT_TRANSLATE_NOOP(
+ "Plot_Series",
+ "Configure series")
+ ToolTip = QtCore.QT_TRANSLATE_NOOP(
+ "Plot_Series",
+ "Configure series drawing style and label")
+ return {'Pixmap': 'Series',
+ 'MenuText': MenuText,
+ 'ToolTip': ToolTip}
+
+
+class Grid:
+ def Activated(self):
+ import Plot
+ plt = Plot.getPlot()
+ if not plt:
+ msg = QtGui.QApplication.translate(
+ "plot_console",
+ "The grid must be activated on top of a plot document",
+ None,
+ QtGui.QApplication.UnicodeUTF8)
+ FreeCAD.Console.PrintError(msg + "\n")
+ return
+ flag = plt.isGrid()
+ Plot.grid(not flag)
+
+ def GetResources(self):
+ # from plotUtils import Paths
+ # IconPath = Paths.iconsPath() + "/Grid.svg"
+ MenuText = QtCore.QT_TRANSLATE_NOOP(
+ "Plot_Grid",
+ "Show/Hide grid")
+ ToolTip = QtCore.QT_TRANSLATE_NOOP(
+ "Plot_Grid",
+ "Show/Hide grid on selected plot")
+ return {'Pixmap': 'Grid',
+ 'MenuText': MenuText,
+ 'ToolTip': ToolTip}
+
+
+class Legend:
+ def Activated(self):
+ import Plot
+ plt = Plot.getPlot()
+ if not plt:
+ msg = QtGui.QApplication.translate(
+ "plot_console",
+ "The legend must be activated on top of a plot document",
+ None,
+ QtGui.QApplication.UnicodeUTF8)
+ FreeCAD.Console.PrintError(msg + "\n")
+ return
+ flag = plt.isLegend()
+ Plot.legend(not flag)
+
+ def GetResources(self):
+ MenuText = QtCore.QT_TRANSLATE_NOOP(
+ "Plot_Legend",
+ "Show/Hide legend")
+ ToolTip = QtCore.QT_TRANSLATE_NOOP(
+ "Plot_Legend",
+ "Show/Hide legend on selected plot")
+ return {'Pixmap': 'Legend',
+ 'MenuText': MenuText,
+ 'ToolTip': ToolTip}
+
+
+class Labels:
+ def Activated(self):
+ import plotLabels
+ plotLabels.load()
+
+ def GetResources(self):
+ MenuText = QtCore.QT_TRANSLATE_NOOP(
+ "Plot_Labels",
+ "Set labels")
+ ToolTip = QtCore.QT_TRANSLATE_NOOP(
+ "Plot_Labels",
+ "Set title and axes labels")
+ return {'Pixmap': 'Labels',
+ 'MenuText': MenuText,
+ 'ToolTip': ToolTip}
+
+
+class Positions:
+ def Activated(self):
+ import plotPositions
+ plotPositions.load()
+
+ def GetResources(self):
+ MenuText = QtCore.QT_TRANSLATE_NOOP(
+ "Plot_Positions",
+ "Set positions and sizes")
+ ToolTip = QtCore.QT_TRANSLATE_NOOP(
+ "Plot_Positions",
+ "Set labels and legend positions and sizes")
+ return {'Pixmap': 'Positions',
+ 'MenuText': MenuText,
+ 'ToolTip': ToolTip}
+
FreeCADGui.addCommand('Plot_SaveFig', Save())
FreeCADGui.addCommand('Plot_Axes', Axes())
@@ -149,4 +186,3 @@ def GetResources(self):
FreeCADGui.addCommand('Plot_Legend', Legend())
FreeCADGui.addCommand('Plot_Labels', Labels())
FreeCADGui.addCommand('Plot_Positions', Positions())
-
diff --git a/src/Mod/Plot/Plot_rc.py b/src/Mod/Plot/Plot_rc.py
index 7840d561bdeb..f2c29b177f23 100644
--- a/src/Mod/Plot/Plot_rc.py
+++ b/src/Mod/Plot/Plot_rc.py
@@ -7,7 +7,7 @@
#
# WARNING! All changes made in this file will be lost!
-from PyQt4 import QtCore
+from PySide import QtCore
qt_resource_data = "\
\x00\x00\x00\x10\
diff --git a/src/Mod/Plot/plotAxes/TaskPanel.py b/src/Mod/Plot/plotAxes/TaskPanel.py
index 35d165853278..5a89c60ca279 100644
--- a/src/Mod/Plot/plotAxes/TaskPanel.py
+++ b/src/Mod/Plot/plotAxes/TaskPanel.py
@@ -1,463 +1,673 @@
#***************************************************************************
-#* *
-#* Copyright (c) 2011, 2012 *
-#* Jose Luis Cercos Pita *
-#* *
+#* *
+#* Copyright (c) 2011, 2012 *
+#* Jose Luis Cercos Pita *
+#* *
#* This program is free software; you can redistribute it and/or modify *
-#* it under the terms of the GNU Lesser General Public License (LGPL) *
-#* as published by the Free Software Foundation; either version 2 of *
-#* the License, or (at your option) any later version. *
-#* for detail see the LICENCE text file. *
-#* *
-#* This program 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 *
+#* it under the terms of the GNU Lesser General Public License (LGPL) *
+#* as published by the Free Software Foundation; either version 2 of *
+#* the License, or (at your option) any later version. *
+#* for detail see the LICENCE text file. *
+#* *
+#* This program 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 program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
-#* USA *
-#* *
+#* USA *
+#* *
#***************************************************************************
-# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
-# Qt library
-from PyQt4 import QtGui,QtCore
-# Module
+
+from PySide import QtGui, QtCore
+
import Plot
from plotUtils import Paths
+
class TaskPanel:
- def __init__(self):
- self.ui = Paths.modulePath() + "/plotAxes/TaskPanel.ui"
- self.skip = False
-
- def accept(self):
- return True
-
- def reject(self):
- return True
-
- def clicked(self, index):
- pass
-
- def open(self):
- pass
-
- def needsFullSpace(self):
- return True
-
- def isAllowedAlterSelection(self):
- return False
-
- def isAllowedAlterView(self):
- return True
-
- def isAllowedAlterDocument(self):
- return False
-
- def helpRequested(self):
- pass
-
- def setupUi(self):
- mw = self.getMainWindow()
- form = mw.findChild(QtGui.QWidget, "TaskPanel")
- form.axId = form.findChild(QtGui.QSpinBox, "axesIndex")
- form.new = form.findChild(QtGui.QPushButton, "newAxesButton")
- form.remove = form.findChild(QtGui.QPushButton, "delAxesButton")
- form.all = form.findChild(QtGui.QCheckBox, "allAxes")
- form.xMin = form.findChild(QtGui.QSlider, "posXMin")
- form.xMax = form.findChild(QtGui.QSlider, "posXMax")
- form.yMin = form.findChild(QtGui.QSlider, "posYMin")
- form.yMax = form.findChild(QtGui.QSlider, "posYMax")
- form.xAlign = form.findChild(QtGui.QComboBox, "xAlign")
- form.yAlign = form.findChild(QtGui.QComboBox, "yAlign")
- form.xOffset = form.findChild(QtGui.QSpinBox, "xOffset")
- form.yOffset = form.findChild(QtGui.QSpinBox, "yOffset")
- form.xAuto = form.findChild(QtGui.QCheckBox, "xAuto")
- form.yAuto = form.findChild(QtGui.QCheckBox, "yAuto")
- form.xSMin = form.findChild(QtGui.QLineEdit, "xMin")
- form.xSMax = form.findChild(QtGui.QLineEdit, "xMax")
- form.ySMin = form.findChild(QtGui.QLineEdit, "yMin")
- form.ySMax = form.findChild(QtGui.QLineEdit, "yMax")
- self.form = form
- self.retranslateUi()
- # Look for active axes if can
- axId = 0
- plt = Plot.getPlot()
- if plt:
- while plt.axes != plt.axesList[axId]:
- axId = axId + 1
- form.axId.setValue(axId)
- self.updateUI()
- QtCore.QObject.connect(form.axId, QtCore.SIGNAL('valueChanged(int)'),self.onAxesId)
- QtCore.QObject.connect(form.new, QtCore.SIGNAL("pressed()"),self.onNew)
- QtCore.QObject.connect(form.remove, QtCore.SIGNAL("pressed()"),self.onRemove)
- QtCore.QObject.connect(form.xMin, QtCore.SIGNAL("valueChanged(int)"),self.onDims)
- QtCore.QObject.connect(form.xMax, QtCore.SIGNAL("valueChanged(int)"),self.onDims)
- QtCore.QObject.connect(form.yMin, QtCore.SIGNAL("valueChanged(int)"),self.onDims)
- QtCore.QObject.connect(form.yMax, QtCore.SIGNAL("valueChanged(int)"),self.onDims)
- QtCore.QObject.connect(form.xAlign, QtCore.SIGNAL("currentIndexChanged(int)"),self.onAlign)
- QtCore.QObject.connect(form.yAlign, QtCore.SIGNAL("currentIndexChanged(int)"),self.onAlign)
- QtCore.QObject.connect(form.xOffset,QtCore.SIGNAL("valueChanged(int)"),self.onOffset)
- QtCore.QObject.connect(form.yOffset,QtCore.SIGNAL("valueChanged(int)"),self.onOffset)
- QtCore.QObject.connect(form.xAuto, QtCore.SIGNAL("stateChanged(int)"),self.onScales)
- QtCore.QObject.connect(form.yAuto, QtCore.SIGNAL("stateChanged(int)"),self.onScales)
- QtCore.QObject.connect(form.xSMin, QtCore.SIGNAL("editingFinished()"),self.onScales)
- QtCore.QObject.connect(form.xSMax, QtCore.SIGNAL("editingFinished()"),self.onScales)
- QtCore.QObject.connect(form.ySMin, QtCore.SIGNAL("editingFinished()"),self.onScales)
- QtCore.QObject.connect(form.ySMax, QtCore.SIGNAL("editingFinished()"),self.onScales)
- QtCore.QObject.connect(Plot.getMdiArea(),QtCore.SIGNAL("subWindowActivated(QMdiSubWindow*)"),self.onMdiArea)
- return False
-
- def getMainWindow(self):
- "returns the main window"
- # using QtGui.qApp.activeWindow() isn't very reliable because if another
- # widget than the mainwindow is active (e.g. a dialog) the wrong widget is
- # returned
- toplevel = QtGui.qApp.topLevelWidgets()
- for i in toplevel:
- if i.metaObject().className() == "Gui::MainWindow":
- return i
- raise Exception("No main window found")
-
- def retranslateUi(self):
- """ Set user interface locale strings.
- """
- self.form.setWindowTitle(QtGui.QApplication.translate("plot_axes", "Configure axes",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "axesLabel").setText(QtGui.QApplication.translate("plot_axes", "Active axes",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.all.setText(QtGui.QApplication.translate("plot_axes", "Apply to all axes",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "dimLabel").setText(QtGui.QApplication.translate("plot_axes", "Dimensions",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "xPosLabel").setText(QtGui.QApplication.translate("plot_axes", "X axis position",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "yPosLabel").setText(QtGui.QApplication.translate("plot_axes", "Y axis position",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "scalesLabel").setText(QtGui.QApplication.translate("plot_axes", "Scales",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.xAuto.setText(QtGui.QApplication.translate("plot_axes", "X auto",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.yAuto.setText(QtGui.QApplication.translate("plot_axes", "Y auto",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QCheckBox, "allAxes").setText(QtGui.QApplication.translate("plot_axes", "Apply to all axes",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "dimLabel").setText(QtGui.QApplication.translate("plot_axes", "Dimensions",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "xPosLabel").setText(QtGui.QApplication.translate("plot_axes", "X axis position",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "yPosLabel").setText(QtGui.QApplication.translate("plot_axes", "Y axis position",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.axId.setToolTip(QtGui.QApplication.translate("plot_axes", "Index of the active axes",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.new.setToolTip(QtGui.QApplication.translate("plot_axes", "Add new axes to the plot",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.remove.setToolTip(QtGui.QApplication.translate("plot_axes", "Remove selected axes",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.all.setToolTip(QtGui.QApplication.translate("plot_axes", "Check it to apply transformations to all axes",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.xMin.setToolTip(QtGui.QApplication.translate("plot_axes", "Left bound of axes",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.xMax.setToolTip(QtGui.QApplication.translate("plot_axes", "Right bound of axes",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.yMin.setToolTip(QtGui.QApplication.translate("plot_axes", "Bottom bound of axes",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.yMax.setToolTip(QtGui.QApplication.translate("plot_axes", "Top bound of axes",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.xOffset.setToolTip(QtGui.QApplication.translate("plot_axes", "Outward offset of X axis",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.yOffset.setToolTip(QtGui.QApplication.translate("plot_axes", "Outward offset of Y axis",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.xAuto.setToolTip(QtGui.QApplication.translate("plot_axes", "X axis scale autoselection",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.yAuto.setToolTip(QtGui.QApplication.translate("plot_axes", "Y axis scale autoselection",
- None,QtGui.QApplication.UnicodeUTF8))
-
- def onAxesId(self, value):
- """ Executed when axes index is modified. """
- if not self.skip:
- self.skip = True
- # UI control in some special plot cases
- plt = Plot.getPlot()
- if not plt:
- self.updateUI()
- self.skip = False
- return
- # UI control in most cases
- self.form.axId.setMaximum(len(plt.axesList))
- if self.form.axId.value() >= len(plt.axesList):
- self.form.axId.setValue(len(plt.axesList)-1)
- # Send new control to Plot instance
- plt.setActiveAxes(self.form.axId.value())
- self.updateUI()
- self.skip = False
-
- def onNew(self):
- """ Executed when new axes must be created. """
- plt = Plot.getPlot()
- if not plt:
- self.updateUI()
- return
- Plot.addNewAxes()
- self.form.axId.setValue(len(plt.axesList)-1)
- plt.update()
-
- def onRemove(self):
- """ Executed when axes must be deleted. """
- plt = Plot.getPlot()
- if not plt:
- self.updateUI()
- return
- # Don't remove first axes
- if not self.form.axId.value():
- msg = QtGui.QApplication.translate("plot_console", "Axes 0 can not be deleted",
- None,QtGui.QApplication.UnicodeUTF8)
- App.Console.PrintError(msg+"\n")
- return
- # Remove axes
- ax = plt.axes
- ax.set_axis_off()
- plt.axesList.pop(self.form.axId.value())
- # Ensure that active axes is correct
- index = min(self.form.axId.value(), len(plt.axesList)-1)
- self.form.axId.setValue(index)
- plt.update()
-
- def onDims(self, value):
- """ Executed when axes dims have been modified. """
- # Get apply environment
- plt = Plot.getPlot()
- if not plt:
- self.updateUI()
- return
- axesList = [plt.axes]
- if self.form.all.isChecked():
- axesList = plt.axesList
- # Set new dimensions
- xmin = self.form.xMin.value() / 100.0
- xmax = self.form.xMax.value() / 100.0
- ymin = self.form.yMin.value() / 100.0
- ymax = self.form.yMax.value() / 100.0
- for axes in axesList:
- axes.set_position([xmin, ymin, xmax-xmin, ymax-ymin])
- plt.update()
-
- def onAlign(self, value):
- """ Executed when axes align have been modified. """
- # Get apply environment
- plt = Plot.getPlot()
- if not plt:
- self.updateUI()
- return
- axesList = [plt.axes]
- if self.form.all.isChecked():
- axesList = plt.axesList
- # Set new alignement
- for axes in axesList:
- if self.form.xAlign.currentIndex() == 0:
- axes.xaxis.tick_bottom()
- axes.spines['bottom'].set_color((0.0,0.0,0.0))
- axes.spines['top'].set_color('none')
- axes.xaxis.set_ticks_position('bottom')
- axes.xaxis.set_label_position('bottom')
- else:
- axes.xaxis.tick_top()
- axes.spines['top'].set_color((0.0,0.0,0.0))
- axes.spines['bottom'].set_color('none')
- axes.xaxis.set_ticks_position('top')
- axes.xaxis.set_label_position('top')
- if self.form.yAlign.currentIndex() == 0:
- axes.yaxis.tick_left()
- axes.spines['left'].set_color((0.0,0.0,0.0))
- axes.spines['right'].set_color('none')
- axes.yaxis.set_ticks_position('left')
- axes.yaxis.set_label_position('left')
- else:
- axes.yaxis.tick_right()
- axes.spines['right'].set_color((0.0,0.0,0.0))
- axes.spines['left'].set_color('none')
- axes.yaxis.set_ticks_position('right')
- axes.yaxis.set_label_position('right')
- plt.update()
-
- def onOffset(self, value):
- """ Executed when axes offsets have been modified. """
- # Get apply environment
- plt = Plot.getPlot()
- if not plt:
- self.updateUI()
- return
- axesList = [plt.axes]
- if self.form.all.isChecked():
- axesList = plt.axesList
- # Set new offset
- for axes in axesList:
- # For some reason, modify spines offset erase axes labels, so we
- # need store it in order to regenerate later
- x = axes.get_xlabel()
- y = axes.get_ylabel()
- for loc, spine in axes.spines.iteritems():
- if loc in ['bottom', 'top']:
- spine.set_position(('outward',self.form.xOffset.value()))
- if loc in ['left', 'right']:
- spine.set_position(('outward',self.form.yOffset.value()))
- # Now we can restore axes labels
- Plot.xlabel(unicode(x))
- Plot.ylabel(unicode(y))
- plt.update()
-
- def onScales(self):
- """ Executed when axes scales have been modified. """
- # Get apply environment
- plt = Plot.getPlot()
- if not plt:
- self.updateUI()
- return
- axesList = [plt.axes]
- if self.form.all.isChecked():
- axesList = plt.axesList
- if not self.skip:
- self.skip = True
- # X axis
- if self.form.xAuto.isChecked():
- for ax in axesList:
- ax.set_autoscalex_on(True)
- self.form.xSMin.setEnabled(False)
- self.form.xSMax.setEnabled(False)
- lim = plt.axes.get_xlim()
- self.form.xSMin.setText(str(lim[0]))
- self.form.xSMax.setText(str(lim[1]))
- else:
- self.form.xSMin.setEnabled(True)
- self.form.xSMax.setEnabled(True)
- try:
- xMin = float(self.form.xSMin.text())
- except:
- xMin = plt.axes.get_xlim()[0]
- self.form.xSMin.setText(str(xMin))
- try:
- xMax = float(self.form.xSMax.text())
- except:
- xMax = plt.axes.get_xlim()[1]
- self.form.xSMax.setText(str(xMax))
- for ax in axesList:
- ax.set_xlim(( xMin,xMax ))
- # Y axis
- if self.form.yAuto.isChecked():
- for ax in axesList:
- ax.set_autoscaley_on(True)
- self.form.ySMin.setEnabled(False)
- self.form.ySMax.setEnabled(False)
- lim = plt.axes.get_ylim()
- self.form.ySMin.setText(str(lim[0]))
- self.form.ySMax.setText(str(lim[1]))
- else:
- self.form.ySMin.setEnabled(True)
- self.form.ySMax.setEnabled(True)
- try:
- yMin = float(self.form.ySMin.text())
- except:
- yMin = plt.axes.get_ylim()[0]
- self.form.ySMin.setText(str(yMin))
- try:
- yMax = float(self.form.ySMax.text())
- except:
- yMax = plt.axes.get_ylim()[1]
- self.form.ySMax.setText(str(yMax))
- for ax in axesList:
- ax.set_ylim(( yMin,yMax ))
- plt.update()
- self.skip = False
-
- def onMdiArea(self, subWin):
- """ Executed when window is selected on mdi area.
- @param subWin Selected window.
- """
- plt = Plot.getPlot()
- if plt != subWin:
- self.updateUI()
-
- def updateUI(self):
- """ Setup UI controls values if possible """
- plt = Plot.getPlot()
- self.form.axId.setEnabled(bool(plt))
- self.form.new.setEnabled(bool(plt))
- self.form.remove.setEnabled(bool(plt))
- self.form.all.setEnabled(bool(plt))
- self.form.xMin.setEnabled(bool(plt))
- self.form.xMax.setEnabled(bool(plt))
- self.form.yMin.setEnabled(bool(plt))
- self.form.yMax.setEnabled(bool(plt))
- self.form.xAlign.setEnabled(bool(plt))
- self.form.yAlign.setEnabled(bool(plt))
- self.form.xOffset.setEnabled(bool(plt))
- self.form.yOffset.setEnabled(bool(plt))
- self.form.xAuto.setEnabled(bool(plt))
- self.form.yAuto.setEnabled(bool(plt))
- self.form.xSMin.setEnabled(bool(plt))
- self.form.xSMax.setEnabled(bool(plt))
- self.form.ySMin.setEnabled(bool(plt))
- self.form.ySMax.setEnabled(bool(plt))
- if not plt:
- return
- # Ensure that active axes is correct
- index = min(self.form.axId.value(), len(plt.axesList)-1)
- self.form.axId.setValue(index)
- # Set dimensions
- ax = plt.axes
- bb = ax.get_position()
- self.form.xMin.setValue(int(100*bb._get_xmin()))
- self.form.xMax.setValue(int(100*bb._get_xmax()))
- self.form.yMin.setValue(int(100*bb._get_ymin()))
- self.form.yMax.setValue(int(100*bb._get_ymax()))
- # Set alignment and offset
- xPos = ax.xaxis.get_ticks_position()
- yPos = ax.yaxis.get_ticks_position()
- xOffset = ax.spines['bottom'].get_position()[1]
- yOffset = ax.spines['left'].get_position()[1]
- if xPos == 'bottom' or xPos == 'default':
- self.form.xAlign.setCurrentIndex(0)
- else:
- self.form.xAlign.setCurrentIndex(1)
- self.form.xOffset.setValue(xOffset)
- if yPos == 'left' or yPos == 'default':
- self.form.yAlign.setCurrentIndex(0)
- else:
- self.form.yAlign.setCurrentIndex(1)
- self.form.yOffset.setValue(yOffset)
- # Set scales
- if ax.get_autoscalex_on():
- self.form.xAuto.setChecked(True)
- self.form.xSMin.setEnabled(False)
- self.form.xSMax.setEnabled(False)
- else:
- self.form.xAuto.setChecked(False)
- self.form.xSMin.setEnabled(True)
- self.form.xSMax.setEnabled(True)
- lim = ax.get_xlim()
- self.form.xSMin.setText(str(lim[0]))
- self.form.xSMax.setText(str(lim[1]))
- if ax.get_autoscaley_on():
- self.form.yAuto.setChecked(True)
- self.form.ySMin.setEnabled(False)
- self.form.ySMax.setEnabled(False)
- else:
- self.form.yAuto.setChecked(False)
- self.form.ySMin.setEnabled(True)
- self.form.ySMax.setEnabled(True)
- lim = ax.get_ylim()
- self.form.ySMin.setText(str(lim[0]))
- self.form.ySMax.setText(str(lim[1]))
+ def __init__(self):
+ self.ui = Paths.modulePath() + "/plotAxes/TaskPanel.ui"
+ self.skip = False
+
+ def accept(self):
+ return True
+
+ def reject(self):
+ return True
+
+ def clicked(self, index):
+ pass
+
+ def open(self):
+ pass
+
+ def needsFullSpace(self):
+ return True
+
+ def isAllowedAlterSelection(self):
+ return False
+
+ def isAllowedAlterView(self):
+ return True
+
+ def isAllowedAlterDocument(self):
+ return False
+
+ def helpRequested(self):
+ pass
+
+ def setupUi(self):
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ self.form = form
+ form.axId = self.widget(QtGui.QSpinBox, "axesIndex")
+ form.new = self.widget(QtGui.QPushButton, "newAxesButton")
+ form.remove = self.widget(QtGui.QPushButton, "delAxesButton")
+ form.all = self.widget(QtGui.QCheckBox, "allAxes")
+ form.xMin = self.widget(QtGui.QSlider, "posXMin")
+ form.xMax = self.widget(QtGui.QSlider, "posXMax")
+ form.yMin = self.widget(QtGui.QSlider, "posYMin")
+ form.yMax = self.widget(QtGui.QSlider, "posYMax")
+ form.xAlign = self.widget(QtGui.QComboBox, "xAlign")
+ form.yAlign = self.widget(QtGui.QComboBox, "yAlign")
+ form.xOffset = self.widget(QtGui.QSpinBox, "xOffset")
+ form.yOffset = self.widget(QtGui.QSpinBox, "yOffset")
+ form.xAuto = self.widget(QtGui.QCheckBox, "xAuto")
+ form.yAuto = self.widget(QtGui.QCheckBox, "yAuto")
+ form.xSMin = self.widget(QtGui.QLineEdit, "xMin")
+ form.xSMax = self.widget(QtGui.QLineEdit, "xMax")
+ form.ySMin = self.widget(QtGui.QLineEdit, "yMin")
+ form.ySMax = self.widget(QtGui.QLineEdit, "yMax")
+ self.retranslateUi()
+ # Look for active axes if can
+ axId = 0
+ plt = Plot.getPlot()
+ if plt:
+ while plt.axes != plt.axesList[axId]:
+ axId = axId + 1
+ form.axId.setValue(axId)
+ self.updateUI()
+ QtCore.QObject.connect(form.axId,
+ QtCore.SIGNAL('valueChanged(int)'),
+ self.onAxesId)
+ QtCore.QObject.connect(form.new,
+ QtCore.SIGNAL("pressed()"),
+ self.onNew)
+ QtCore.QObject.connect(form.remove,
+ QtCore.SIGNAL("pressed()"),
+ self.onRemove)
+ QtCore.QObject.connect(form.xMin,
+ QtCore.SIGNAL("valueChanged(int)"),
+ self.onDims)
+ QtCore.QObject.connect(form.xMax,
+ QtCore.SIGNAL("valueChanged(int)"),
+ self.onDims)
+ QtCore.QObject.connect(form.yMin,
+ QtCore.SIGNAL("valueChanged(int)"),
+ self.onDims)
+ QtCore.QObject.connect(form.yMax,
+ QtCore.SIGNAL("valueChanged(int)"),
+ self.onDims)
+ QtCore.QObject.connect(form.xAlign,
+ QtCore.SIGNAL("currentIndexChanged(int)"),
+ self.onAlign)
+ QtCore.QObject.connect(form.yAlign,
+ QtCore.SIGNAL("currentIndexChanged(int)"),
+ self.onAlign)
+ QtCore.QObject.connect(form.xOffset,
+ QtCore.SIGNAL("valueChanged(int)"),
+ self.onOffset)
+ QtCore.QObject.connect(form.yOffset,
+ QtCore.SIGNAL("valueChanged(int)"),
+ self.onOffset)
+ QtCore.QObject.connect(form.xAuto,
+ QtCore.SIGNAL("stateChanged(int)"),
+ self.onScales)
+ QtCore.QObject.connect(form.yAuto,
+ QtCore.SIGNAL("stateChanged(int)"),
+ self.onScales)
+ QtCore.QObject.connect(form.xSMin,
+ QtCore.SIGNAL("editingFinished()"),
+ self.onScales)
+ QtCore.QObject.connect(form.xSMax,
+ QtCore.SIGNAL("editingFinished()"),
+ self.onScales)
+ QtCore.QObject.connect(form.ySMin,
+ QtCore.SIGNAL("editingFinished()"),
+ self.onScales)
+ QtCore.QObject.connect(form.ySMax,
+ QtCore.SIGNAL("editingFinished()"),
+ self.onScales)
+ QtCore.QObject.connect(
+ Plot.getMdiArea(),
+ QtCore.SIGNAL("subWindowActivated(QMdiSubWindow*)"),
+ self.onMdiArea)
+ return False
+
+ def getMainWindow(self):
+ toplevel = QtGui.qApp.topLevelWidgets()
+ for i in toplevel:
+ if i.metaObject().className() == "Gui::MainWindow":
+ return i
+ raise Exception("No main window found")
+
+ def widget(self, class_id, name):
+ """Return the selected widget.
+
+ Keyword arguments:
+ class_id -- Class identifier
+ name -- Name of the widget
+ """
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ return form.findChild(class_id, name)
+
+ def retranslateUi(self):
+ """Set the user interface locale strings.
+ """
+ form = self.form
+ form.setWindowTitle(QtGui.QApplication.translate(
+ "plot_axes",
+ "Configure axes",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "axesLabel").setText(
+ QtGui.QApplication.translate("plot_axes",
+ "Active axes",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QCheckBox, "allAxes").setText(
+ QtGui.QApplication.translate("plot_axes",
+ "Apply to all axes",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "dimLabel").setText(
+ QtGui.QApplication.translate("plot_axes",
+ "Dimensions",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "xPosLabel").setText(
+ QtGui.QApplication.translate("plot_axes",
+ "X axis position",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "yPosLabel").setText(
+ QtGui.QApplication.translate("plot_axes",
+ "Y axis position",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "scalesLabel").setText(
+ QtGui.QApplication.translate("plot_axes",
+ "Scales",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QCheckBox, "xAuto").setText(
+ QtGui.QApplication.translate("plot_axes",
+ "X auto",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QCheckBox, "yAuto").setText(
+ QtGui.QApplication.translate("plot_axes",
+ "Y auto",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QCheckBox, "allAxes").setText(
+ QtGui.QApplication.translate("plot_axes",
+ "Apply to all axes",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "dimLabel").setText(
+ QtGui.QApplication.translate("plot_axes",
+ "Dimensions",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "xPosLabel").setText(
+ QtGui.QApplication.translate("plot_axes",
+ "X axis position",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "yPosLabel").setText(
+ QtGui.QApplication.translate("plot_axes",
+ "Y axis position",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QSpinBox, "axesIndex").setToolTip(
+ QtGui.QApplication.translate("plot_axes",
+ "Index of the active axes",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QPushButton, "newAxesButton").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_axes",
+ "Add new axes to the plot",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QPushButton, "delAxesButton").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_axes",
+ "Remove selected axes",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QCheckBox, "allAxes").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_axes",
+ "Check it to apply transformations to all axes",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QSlider, "posXMin").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_axes",
+ "Left bound of axes",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QSlider, "posXMax").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_axes",
+ "Right bound of axes",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QSlider, "posYMin").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_axes",
+ "Bottom bound of axes",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QSlider, "posYMax").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_axes",
+ "Top bound of axes",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QSpinBox, "xOffset").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_axes",
+ "Outward offset of X axis",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QSpinBox, "yOffset").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_axes",
+ "Outward offset of Y axis",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QCheckBox, "xAuto").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_axes",
+ "X axis scale autoselection",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QCheckBox, "yAuto").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_axes",
+ "Y axis scale autoselection",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+
+ def onAxesId(self, value):
+ """Executed when axes index is modified."""
+ if not self.skip:
+ self.skip = True
+ # No active plot case
+ plt = Plot.getPlot()
+ if not plt:
+ self.updateUI()
+ self.skip = False
+ return
+ # Get again all the subwidgets (to avoid PySide Pitfalls)
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.axId = self.widget(QtGui.QSpinBox, "axesIndex")
+
+ form.axId.setMaximum(len(plt.axesList))
+ if form.axId.value() >= len(plt.axesList):
+ form.axId.setValue(len(plt.axesList) - 1)
+ # Send new control to Plot instance
+ plt.setActiveAxes(form.axId.value())
+ self.updateUI()
+ self.skip = False
+
+ def onNew(self):
+ """Executed when new axes must be created."""
+ # Ensure that we can work
+ plt = Plot.getPlot()
+ if not plt:
+ self.updateUI()
+ return
+ # Get again all the subwidgets (to avoid PySide Pitfalls)
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.axId = self.widget(QtGui.QSpinBox, "axesIndex")
+
+ Plot.addNewAxes()
+ form.axId.setValue(len(plt.axesList) - 1)
+ plt.update()
+
+ def onRemove(self):
+ """Executed when axes must be deleted."""
+ # Ensure taht we can work
+ plt = Plot.getPlot()
+ if not plt:
+ self.updateUI()
+ return
+ # Get again all the subwidgets (to avoid PySide Pitfalls)
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.axId = self.widget(QtGui.QSpinBox, "axesIndex")
+
+ # Don't remove first axes
+ if not form.axId.value():
+ msg = QtGui.QApplication.translate(
+ "plot_console",
+ "Axes 0 can not be deleted",
+ None,
+ QtGui.QApplication.UnicodeUTF8)
+ App.Console.PrintError(msg + "\n")
+ return
+ # Remove axes
+ ax = plt.axes
+ ax.set_axis_off()
+ plt.axesList.pop(form.axId.value())
+ # Ensure that active axes is correct
+ index = min(form.axId.value(), len(plt.axesList) - 1)
+ form.axId.setValue(index)
+ plt.update()
+
+ def onDims(self, value):
+ """Executed when axes dims have been modified."""
+ # Ensure that we can work
+ plt = Plot.getPlot()
+ if not plt:
+ self.updateUI()
+ return
+ # Get again all the subwidgets (to avoid PySide Pitfalls)
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.all = self.widget(QtGui.QCheckBox, "allAxes")
+ form.xMin = self.widget(QtGui.QSlider, "posXMin")
+ form.xMax = self.widget(QtGui.QSlider, "posXMax")
+ form.yMin = self.widget(QtGui.QSlider, "posYMin")
+ form.yMax = self.widget(QtGui.QSlider, "posYMax")
+
+ axesList = [plt.axes]
+ if form.all.isChecked():
+ axesList = plt.axesList
+ # Set new dimensions
+ xmin = form.xMin.value() / 100.0
+ xmax = form.xMax.value() / 100.0
+ ymin = form.yMin.value() / 100.0
+ ymax = form.yMax.value() / 100.0
+ for axes in axesList:
+ axes.set_position([xmin, ymin, xmax - xmin, ymax - ymin])
+ plt.update()
+
+ def onAlign(self, value):
+ """Executed when axes align have been modified."""
+ # Ensure that we can work
+ plt = Plot.getPlot()
+ if not plt:
+ self.updateUI()
+ return
+ # Get again all the subwidgets (to avoid PySide Pitfalls)
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.all = self.widget(QtGui.QCheckBox, "allAxes")
+ form.xAlign = self.widget(QtGui.QComboBox, "xAlign")
+ form.yAlign = self.widget(QtGui.QComboBox, "yAlign")
+
+ axesList = [plt.axes]
+ if form.all.isChecked():
+ axesList = plt.axesList
+ # Set new alignement
+ for axes in axesList:
+ if form.xAlign.currentIndex() == 0:
+ axes.xaxis.tick_bottom()
+ axes.spines['bottom'].set_color((0.0, 0.0, 0.0))
+ axes.spines['top'].set_color('none')
+ axes.xaxis.set_ticks_position('bottom')
+ axes.xaxis.set_label_position('bottom')
+ else:
+ axes.xaxis.tick_top()
+ axes.spines['top'].set_color((0.0, 0.0, 0.0))
+ axes.spines['bottom'].set_color('none')
+ axes.xaxis.set_ticks_position('top')
+ axes.xaxis.set_label_position('top')
+ if form.yAlign.currentIndex() == 0:
+ axes.yaxis.tick_left()
+ axes.spines['left'].set_color((0.0, 0.0, 0.0))
+ axes.spines['right'].set_color('none')
+ axes.yaxis.set_ticks_position('left')
+ axes.yaxis.set_label_position('left')
+ else:
+ axes.yaxis.tick_right()
+ axes.spines['right'].set_color((0.0, 0.0, 0.0))
+ axes.spines['left'].set_color('none')
+ axes.yaxis.set_ticks_position('right')
+ axes.yaxis.set_label_position('right')
+ plt.update()
+
+ def onOffset(self, value):
+ """Executed when axes offsets have been modified."""
+ # Ensure that we can work
+ plt = Plot.getPlot()
+ if not plt:
+ self.updateUI()
+ return
+ # Get again all the subwidgets (to avoid PySide Pitfalls)
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.all = self.widget(QtGui.QCheckBox, "allAxes")
+ form.xOffset = self.widget(QtGui.QSpinBox, "xOffset")
+ form.yOffset = self.widget(QtGui.QSpinBox, "yOffset")
+
+ axesList = [plt.axes]
+ if form.all.isChecked():
+ axesList = plt.axesList
+ # Set new offset
+ for axes in axesList:
+ # For some reason, modify spines offset erase axes labels, so we
+ # need store it in order to regenerate later
+ x = axes.get_xlabel()
+ y = axes.get_ylabel()
+ for loc, spine in axes.spines.iteritems():
+ if loc in ['bottom', 'top']:
+ spine.set_position(('outward', form.xOffset.value()))
+ if loc in ['left', 'right']:
+ spine.set_position(('outward', form.yOffset.value()))
+ # Now we can restore axes labels
+ Plot.xlabel(unicode(x))
+ Plot.ylabel(unicode(y))
+ plt.update()
+
+ def onScales(self):
+ """Executed when axes scales have been modified."""
+ # Ensure that we can work
+ plt = Plot.getPlot()
+ if not plt:
+ self.updateUI()
+ return
+ # Get again all the subwidgets (to avoid PySide Pitfalls)
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.all = self.widget(QtGui.QCheckBox, "allAxes")
+ form.xAuto = self.widget(QtGui.QCheckBox, "xAuto")
+ form.yAuto = self.widget(QtGui.QCheckBox, "yAuto")
+ form.xSMin = self.widget(QtGui.QLineEdit, "xMin")
+ form.xSMax = self.widget(QtGui.QLineEdit, "xMax")
+ form.ySMin = self.widget(QtGui.QLineEdit, "yMin")
+ form.ySMax = self.widget(QtGui.QLineEdit, "yMax")
+
+ axesList = [plt.axes]
+ if form.all.isChecked():
+ axesList = plt.axesList
+ if not self.skip:
+ self.skip = True
+ # X axis
+ if form.xAuto.isChecked():
+ for ax in axesList:
+ ax.set_autoscalex_on(True)
+ form.xSMin.setEnabled(False)
+ form.xSMax.setEnabled(False)
+ lim = plt.axes.get_xlim()
+ form.xSMin.setText(str(lim[0]))
+ form.xSMax.setText(str(lim[1]))
+ else:
+ form.xSMin.setEnabled(True)
+ form.xSMax.setEnabled(True)
+ try:
+ xMin = float(form.xSMin.text())
+ except:
+ xMin = plt.axes.get_xlim()[0]
+ form.xSMin.setText(str(xMin))
+ try:
+ xMax = float(form.xSMax.text())
+ except:
+ xMax = plt.axes.get_xlim()[1]
+ form.xSMax.setText(str(xMax))
+ for ax in axesList:
+ ax.set_xlim((xMin, xMax))
+ # Y axis
+ if form.yAuto.isChecked():
+ for ax in axesList:
+ ax.set_autoscaley_on(True)
+ form.ySMin.setEnabled(False)
+ form.ySMax.setEnabled(False)
+ lim = plt.axes.get_ylim()
+ form.ySMin.setText(str(lim[0]))
+ form.ySMax.setText(str(lim[1]))
+ else:
+ form.ySMin.setEnabled(True)
+ form.ySMax.setEnabled(True)
+ try:
+ yMin = float(form.ySMin.text())
+ except:
+ yMin = plt.axes.get_ylim()[0]
+ form.ySMin.setText(str(yMin))
+ try:
+ yMax = float(form.ySMax.text())
+ except:
+ yMax = plt.axes.get_ylim()[1]
+ form.ySMax.setText(str(yMax))
+ for ax in axesList:
+ ax.set_ylim((yMin, yMax))
+ plt.update()
+ self.skip = False
+
+ def onMdiArea(self, subWin):
+ """Executed when window is selected on mdi area.
+
+ Keyword arguments:
+ subWin -- Selected window.
+ """
+ plt = Plot.getPlot()
+ if plt != subWin:
+ self.updateUI()
+
+ def updateUI(self):
+ """Setup UI controls values if possible"""
+ plt = Plot.getPlot()
+ # Get again all the subwidgets (to avoid PySide Pitfalls)
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.axId = self.widget(QtGui.QSpinBox, "axesIndex")
+ form.new = self.widget(QtGui.QPushButton, "newAxesButton")
+ form.remove = self.widget(QtGui.QPushButton, "delAxesButton")
+ form.all = self.widget(QtGui.QCheckBox, "allAxes")
+ form.xMin = self.widget(QtGui.QSlider, "posXMin")
+ form.xMax = self.widget(QtGui.QSlider, "posXMax")
+ form.yMin = self.widget(QtGui.QSlider, "posYMin")
+ form.yMax = self.widget(QtGui.QSlider, "posYMax")
+ form.xAlign = self.widget(QtGui.QComboBox, "xAlign")
+ form.yAlign = self.widget(QtGui.QComboBox, "yAlign")
+ form.xOffset = self.widget(QtGui.QSpinBox, "xOffset")
+ form.yOffset = self.widget(QtGui.QSpinBox, "yOffset")
+ form.xAuto = self.widget(QtGui.QCheckBox, "xAuto")
+ form.yAuto = self.widget(QtGui.QCheckBox, "yAuto")
+ form.xSMin = self.widget(QtGui.QLineEdit, "xMin")
+ form.xSMax = self.widget(QtGui.QLineEdit, "xMax")
+ form.ySMin = self.widget(QtGui.QLineEdit, "yMin")
+ form.ySMax = self.widget(QtGui.QLineEdit, "yMax")
+ # Enable/disable them
+ form.axId.setEnabled(bool(plt))
+ form.new.setEnabled(bool(plt))
+ form.remove.setEnabled(bool(plt))
+ form.all.setEnabled(bool(plt))
+ form.xMin.setEnabled(bool(plt))
+ form.xMax.setEnabled(bool(plt))
+ form.yMin.setEnabled(bool(plt))
+ form.yMax.setEnabled(bool(plt))
+ form.xAlign.setEnabled(bool(plt))
+ form.yAlign.setEnabled(bool(plt))
+ form.xOffset.setEnabled(bool(plt))
+ form.yOffset.setEnabled(bool(plt))
+ form.xAuto.setEnabled(bool(plt))
+ form.yAuto.setEnabled(bool(plt))
+ form.xSMin.setEnabled(bool(plt))
+ form.xSMax.setEnabled(bool(plt))
+ form.ySMin.setEnabled(bool(plt))
+ form.ySMax.setEnabled(bool(plt))
+ if not plt:
+ form.axId.setValue(0)
+ return
+ # Ensure that active axes is correct
+ index = min(form.axId.value(), len(plt.axesList) - 1)
+ form.axId.setValue(index)
+ # Set dimensions
+ ax = plt.axes
+ bb = ax.get_position()
+ form.xMin.setValue(int(100 * bb._get_xmin()))
+ form.xMax.setValue(int(100 * bb._get_xmax()))
+ form.yMin.setValue(int(100 * bb._get_ymin()))
+ form.yMax.setValue(int(100 * bb._get_ymax()))
+ # Set alignment and offset
+ xPos = ax.xaxis.get_ticks_position()
+ yPos = ax.yaxis.get_ticks_position()
+ xOffset = ax.spines['bottom'].get_position()[1]
+ yOffset = ax.spines['left'].get_position()[1]
+ if xPos == 'bottom' or xPos == 'default':
+ form.xAlign.setCurrentIndex(0)
+ else:
+ form.xAlign.setCurrentIndex(1)
+ form.xOffset.setValue(xOffset)
+ if yPos == 'left' or yPos == 'default':
+ form.yAlign.setCurrentIndex(0)
+ else:
+ form.yAlign.setCurrentIndex(1)
+ form.yOffset.setValue(yOffset)
+ # Set scales
+ if ax.get_autoscalex_on():
+ form.xAuto.setChecked(True)
+ form.xSMin.setEnabled(False)
+ form.xSMax.setEnabled(False)
+ else:
+ form.xAuto.setChecked(False)
+ form.xSMin.setEnabled(True)
+ form.xSMax.setEnabled(True)
+ lim = ax.get_xlim()
+ form.xSMin.setText(str(lim[0]))
+ form.xSMax.setText(str(lim[1]))
+ if ax.get_autoscaley_on():
+ form.yAuto.setChecked(True)
+ form.ySMin.setEnabled(False)
+ form.ySMax.setEnabled(False)
+ else:
+ form.yAuto.setChecked(False)
+ form.ySMin.setEnabled(True)
+ form.ySMax.setEnabled(True)
+ lim = ax.get_ylim()
+ form.ySMin.setText(str(lim[0]))
+ form.ySMax.setText(str(lim[1]))
+
def createTask():
- panel = TaskPanel()
- Gui.Control.showDialog(panel)
- if panel.setupUi():
- Gui.Control.closeDialog(panel)
- return None
- return panel
+ panel = TaskPanel()
+ Gui.Control.showDialog(panel)
+ if panel.setupUi():
+ Gui.Control.closeDialog(panel)
+ return None
+ return panel
diff --git a/src/Mod/Plot/plotAxes/__init__.py b/src/Mod/Plot/plotAxes/__init__.py
index 24058d7a93ee..6a97f58b26af 100644
--- a/src/Mod/Plot/plotAxes/__init__.py
+++ b/src/Mod/Plot/plotAxes/__init__.py
@@ -1,7 +1,7 @@
#***************************************************************************
#* *
-#* Copyright (c) 2011, 2012 *
-#* Jose Luis Cercos Pita *
+#* Copyright (c) 2011, 2012 *
+#* Jose Luis Cercos Pita *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
@@ -21,16 +21,9 @@
#* *
#***************************************************************************
-# FreeCAD modules
-import FreeCAD
-import FreeCADGui
-
-# Qt libraries
-from PyQt4 import QtGui,QtCore
-
-# Main object
import TaskPanel
+
def load():
- """ Loads the tool """
- TaskPanel.createTask()
+ """Load the tool"""
+ TaskPanel.createTask()
diff --git a/src/Mod/Plot/plotLabels/TaskPanel.py b/src/Mod/Plot/plotLabels/TaskPanel.py
index f2ea4106dfa4..87dddcb9d720 100644
--- a/src/Mod/Plot/plotLabels/TaskPanel.py
+++ b/src/Mod/Plot/plotLabels/TaskPanel.py
@@ -1,225 +1,322 @@
#***************************************************************************
-#* *
-#* Copyright (c) 2011, 2012 *
-#* Jose Luis Cercos Pita *
-#* *
+#* *
+#* Copyright (c) 2011, 2012 *
+#* Jose Luis Cercos Pita *
+#* *
#* This program is free software; you can redistribute it and/or modify *
-#* it under the terms of the GNU Lesser General Public License (LGPL) *
-#* as published by the Free Software Foundation; either version 2 of *
-#* the License, or (at your option) any later version. *
-#* for detail see the LICENCE text file. *
-#* *
-#* This program 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 *
+#* it under the terms of the GNU Lesser General Public License (LGPL) *
+#* as published by the Free Software Foundation; either version 2 of *
+#* the License, or (at your option) any later version. *
+#* for detail see the LICENCE text file. *
+#* *
+#* This program 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 program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
-#* USA *
-#* *
+#* USA *
+#* *
#***************************************************************************
-# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
-# Qt library
-from PyQt4 import QtGui,QtCore
-# Module
+
+from PySide import QtGui, QtCore
+
import Plot
from plotUtils import Paths
+
class TaskPanel:
- def __init__(self):
- self.ui = Paths.modulePath() + "/plotLabels/TaskPanel.ui"
- self.skip = False
-
- def accept(self):
- return True
-
- def reject(self):
- return True
-
- def clicked(self, index):
- pass
-
- def open(self):
- pass
-
- def needsFullSpace(self):
- return True
-
- def isAllowedAlterSelection(self):
- return False
-
- def isAllowedAlterView(self):
- return True
-
- def isAllowedAlterDocument(self):
- return False
-
- def helpRequested(self):
- pass
-
- def setupUi(self):
- mw = self.getMainWindow()
- form = mw.findChild(QtGui.QWidget, "TaskPanel")
- form.axId = form.findChild(QtGui.QSpinBox, "axesIndex")
- form.title = form.findChild(QtGui.QLineEdit, "title")
- form.titleSize = form.findChild(QtGui.QSpinBox, "titleSize")
- form.xLabel = form.findChild(QtGui.QLineEdit, "titleX")
- form.xSize = form.findChild(QtGui.QSpinBox, "xSize")
- form.yLabel = form.findChild(QtGui.QLineEdit, "titleY")
- form.ySize = form.findChild(QtGui.QSpinBox, "ySize")
- self.form = form
- self.retranslateUi()
- # Look for active axes if can
- axId = 0
- plt = Plot.getPlot()
- if plt:
- while plt.axes != plt.axesList[axId]:
- axId = axId + 1
- form.axId.setValue(axId)
- self.updateUI()
- QtCore.QObject.connect(form.axId, QtCore.SIGNAL('valueChanged(int)'),self.onAxesId)
- QtCore.QObject.connect(form.title, QtCore.SIGNAL("editingFinished()"),self.onLabels)
- QtCore.QObject.connect(form.xLabel, QtCore.SIGNAL("editingFinished()"),self.onLabels)
- QtCore.QObject.connect(form.yLabel, QtCore.SIGNAL("editingFinished()"),self.onLabels)
- QtCore.QObject.connect(form.titleSize,QtCore.SIGNAL("valueChanged(int)"),self.onFontSizes)
- QtCore.QObject.connect(form.xSize, QtCore.SIGNAL("valueChanged(int)"),self.onFontSizes)
- QtCore.QObject.connect(form.ySize, QtCore.SIGNAL("valueChanged(int)"),self.onFontSizes)
- QtCore.QObject.connect(Plot.getMdiArea(),QtCore.SIGNAL("subWindowActivated(QMdiSubWindow*)"),self.onMdiArea)
- return False
-
- def getMainWindow(self):
- "returns the main window"
- # using QtGui.qApp.activeWindow() isn't very reliable because if another
- # widget than the mainwindow is active (e.g. a dialog) the wrong widget is
- # returned
- toplevel = QtGui.qApp.topLevelWidgets()
- for i in toplevel:
- if i.metaObject().className() == "Gui::MainWindow":
- return i
- raise Exception("No main window found")
-
- def retranslateUi(self):
- """ Set user interface locale strings.
- """
- self.form.setWindowTitle(QtGui.QApplication.translate("plot_labels", "Set labels",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "axesLabel").setText(QtGui.QApplication.translate("plot_labels", "Active axes",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "titleLabel").setText(QtGui.QApplication.translate("plot_labels", "Title",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "xLabel").setText(QtGui.QApplication.translate("plot_labels", "X label",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "yLabel").setText(QtGui.QApplication.translate("plot_labels", "Y label",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.axId.setToolTip(QtGui.QApplication.translate("plot_labels", "Index of the active axes",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.title.setToolTip(QtGui.QApplication.translate("plot_labels", "Title (associated to active axes)",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.titleSize.setToolTip(QtGui.QApplication.translate("plot_labels", "Title font size",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.xLabel.setToolTip(QtGui.QApplication.translate("plot_labels", "X axis title",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.xSize.setToolTip(QtGui.QApplication.translate("plot_labels", "X axis title font size",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.yLabel.setToolTip(QtGui.QApplication.translate("plot_labels", "Y axis title",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.ySize.setToolTip(QtGui.QApplication.translate("plot_labels", "Y axis title font size",
- None,QtGui.QApplication.UnicodeUTF8))
-
- def onAxesId(self, value):
- """ Executed when axes index is modified. """
- if not self.skip:
- self.skip = True
- # UI control in some special plot cases
- plt = Plot.getPlot()
- if not plt:
- self.updateUI()
- self.skip = False
- return
- # UI control in most cases
- self.form.axId.setMaximum(len(plt.axesList))
- if self.form.axId.value() >= len(plt.axesList):
- self.form.axId.setValue(len(plt.axesList)-1)
- # Send new control to Plot instance
- plt.setActiveAxes(self.form.axId.value())
- self.updateUI()
- self.skip = False
-
- def onLabels(self):
- """ Executed when labels have been modified. """
- plt = Plot.getPlot()
- if not plt:
- self.updateUI()
- return
- # Set labels
- Plot.title(unicode(self.form.title.text()))
- Plot.xlabel(unicode(self.form.xLabel.text()))
- Plot.ylabel(unicode(self.form.yLabel.text()))
- plt.update()
-
- def onFontSizes(self, value):
- """ Executed when font sizes have been modified. """
- # Get apply environment
- plt = Plot.getPlot()
- if not plt:
- self.updateUI()
- return
- # Set font sizes
- ax = plt.axes
- ax.title.set_fontsize(self.form.titleSize.value())
- ax.xaxis.label.set_fontsize(self.form.xSize.value())
- ax.yaxis.label.set_fontsize(self.form.ySize.value())
- plt.update()
-
- def onMdiArea(self, subWin):
- """ Executed when window is selected on mdi area.
- @param subWin Selected window.
- """
- plt = Plot.getPlot()
- if plt != subWin:
- self.updateUI()
-
- def updateUI(self):
- """ Setup UI controls values if possible """
- plt = Plot.getPlot()
- self.form.axId.setEnabled(bool(plt))
- self.form.title.setEnabled(bool(plt))
- self.form.titleSize.setEnabled(bool(plt))
- self.form.xLabel.setEnabled(bool(plt))
- self.form.xSize.setEnabled(bool(plt))
- self.form.yLabel.setEnabled(bool(plt))
- self.form.ySize.setEnabled(bool(plt))
- if not plt:
- return
- # Ensure that active axes is correct
- index = min(self.form.axId.value(), len(plt.axesList)-1)
- self.form.axId.setValue(index)
- # Store data before starting changing it.
- ax = plt.axes
- t = ax.get_title()
- x = ax.get_xlabel()
- y = ax.get_ylabel()
- tt = ax.title.get_fontsize()
- xx = ax.xaxis.label.get_fontsize()
- yy = ax.yaxis.label.get_fontsize()
- # Set labels
- self.form.title.setText(t)
- self.form.xLabel.setText(x)
- self.form.yLabel.setText(y)
- # Set font sizes
- self.form.titleSize.setValue(tt)
- self.form.xSize.setValue(xx)
- self.form.ySize.setValue(yy)
+ def __init__(self):
+ self.ui = Paths.modulePath() + "/plotLabels/TaskPanel.ui"
+ self.skip = False
+
+ def accept(self):
+ return True
+
+ def reject(self):
+ return True
+
+ def clicked(self, index):
+ pass
+
+ def open(self):
+ pass
+
+ def needsFullSpace(self):
+ return True
+
+ def isAllowedAlterSelection(self):
+ return False
+
+ def isAllowedAlterView(self):
+ return True
+
+ def isAllowedAlterDocument(self):
+ return False
+
+ def helpRequested(self):
+ pass
+
+ def setupUi(self):
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.axId = self.widget(QtGui.QSpinBox, "axesIndex")
+ form.title = self.widget(QtGui.QLineEdit, "title")
+ form.titleSize = self.widget(QtGui.QSpinBox, "titleSize")
+ form.xLabel = self.widget(QtGui.QLineEdit, "titleX")
+ form.xSize = self.widget(QtGui.QSpinBox, "xSize")
+ form.yLabel = self.widget(QtGui.QLineEdit, "titleY")
+ form.ySize = self.widget(QtGui.QSpinBox, "ySize")
+ self.form = form
+ self.retranslateUi()
+ # Look for active axes if can
+ axId = 0
+ plt = Plot.getPlot()
+ if plt:
+ while plt.axes != plt.axesList[axId]:
+ axId = axId + 1
+ form.axId.setValue(axId)
+ self.updateUI()
+ QtCore.QObject.connect(form.axId,
+ QtCore.SIGNAL('valueChanged(int)'),
+ self.onAxesId)
+ QtCore.QObject.connect(form.title,
+ QtCore.SIGNAL("editingFinished()"),
+ self.onLabels)
+ QtCore.QObject.connect(form.xLabel,
+ QtCore.SIGNAL("editingFinished()"),
+ self.onLabels)
+ QtCore.QObject.connect(form.yLabel,
+ QtCore.SIGNAL("editingFinished()"),
+ self.onLabels)
+ QtCore.QObject.connect(form.titleSize,
+ QtCore.SIGNAL("valueChanged(int)"),
+ self.onFontSizes)
+ QtCore.QObject.connect(form.xSize,
+ QtCore.SIGNAL("valueChanged(int)"),
+ self.onFontSizes)
+ QtCore.QObject.connect(form.ySize,
+ QtCore.SIGNAL("valueChanged(int)"),
+ self.onFontSizes)
+ QtCore.QObject.connect(
+ Plot.getMdiArea(),
+ QtCore.SIGNAL("subWindowActivated(QMdiSubWindow*)"),
+ self.onMdiArea)
+ return False
+
+ def getMainWindow(self):
+ toplevel = QtGui.qApp.topLevelWidgets()
+ for i in toplevel:
+ if i.metaObject().className() == "Gui::MainWindow":
+ return i
+ raise Exception("No main window found")
+
+ def widget(self, class_id, name):
+ """Return the selected widget.
+
+ Keyword arguments:
+ class_id -- Class identifier
+ name -- Name of the widget
+ """
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ return form.findChild(class_id, name)
+
+ def retranslateUi(self):
+ """ Set the user interface locale strings.
+ """
+ self.form.setWindowTitle(QtGui.QApplication.translate(
+ "plot_labels",
+ "Set labels",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "axesLabel").setText(
+ QtGui.QApplication.translate("plot_labels",
+ "Active axes",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "titleLabel").setText(
+ QtGui.QApplication.translate("plot_labels",
+ "Title",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "xLabel").setText(
+ QtGui.QApplication.translate("plot_labels",
+ "X label",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "yLabel").setText(
+ QtGui.QApplication.translate("plot_labels",
+ "Y label",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QSpinBox, "axesIndex").setToolTip(QtGui.QApplication.translate(
+ "plot_labels",
+ "Index of the active axes",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLineEdit, "title").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_labels",
+ "Title (associated to active axes)",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QSpinBox, "titleSize").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_labels",
+ "Title font size",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLineEdit, "titleX").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_labels",
+ "X axis title",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QSpinBox, "xSize").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_labels",
+ "X axis title font size",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLineEdit, "titleY").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_labels",
+ "Y axis title",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QSpinBox, "ySize").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_labels",
+ "Y axis title font size",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+
+ def onAxesId(self, value):
+ """ Executed when axes index is modified. """
+ if not self.skip:
+ self.skip = True
+ # No active plot case
+ plt = Plot.getPlot()
+ if not plt:
+ self.updateUI()
+ self.skip = False
+ return
+ # Get again all the subwidgets (to avoid PySide Pitfalls)
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.axId = self.widget(QtGui.QSpinBox, "axesIndex")
+
+ form.axId.setMaximum(len(plt.axesList))
+ if form.axId.value() >= len(plt.axesList):
+ form.axId.setValue(len(plt.axesList) - 1)
+ # Send new control to Plot instance
+ plt.setActiveAxes(form.axId.value())
+ self.updateUI()
+ self.skip = False
+
+ def onLabels(self):
+ """ Executed when labels have been modified. """
+ plt = Plot.getPlot()
+ if not plt:
+ self.updateUI()
+ return
+ # Get again all the subwidgets (to avoid PySide Pitfalls)
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.title = self.widget(QtGui.QLineEdit, "title")
+ form.xLabel = self.widget(QtGui.QLineEdit, "titleX")
+ form.yLabel = self.widget(QtGui.QLineEdit, "titleY")
+
+ Plot.title(unicode(form.title.text()))
+ Plot.xlabel(unicode(form.xLabel.text()))
+ Plot.ylabel(unicode(form.yLabel.text()))
+ plt.update()
+
+ def onFontSizes(self, value):
+ """ Executed when font sizes have been modified. """
+ # Get apply environment
+ plt = Plot.getPlot()
+ if not plt:
+ self.updateUI()
+ return
+ # Get again all the subwidgets (to avoid PySide Pitfalls)
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.titleSize = self.widget(QtGui.QSpinBox, "titleSize")
+ form.xSize = self.widget(QtGui.QSpinBox, "xSize")
+ form.ySize = self.widget(QtGui.QSpinBox, "ySize")
+
+ ax = plt.axes
+ ax.title.set_fontsize(form.titleSize.value())
+ ax.xaxis.label.set_fontsize(form.xSize.value())
+ ax.yaxis.label.set_fontsize(form.ySize.value())
+ plt.update()
+
+ def onMdiArea(self, subWin):
+ """ Executed when window is selected on mdi area.
+
+ Keyword arguments:
+ subWin -- Selected window.
+ """
+ plt = Plot.getPlot()
+ if plt != subWin:
+ self.updateUI()
+
+ def updateUI(self):
+ """ Setup UI controls values if possible """
+ # Get again all the subwidgets (to avoid PySide Pitfalls)
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.axId = self.widget(QtGui.QSpinBox, "axesIndex")
+ form.title = self.widget(QtGui.QLineEdit, "title")
+ form.titleSize = self.widget(QtGui.QSpinBox, "titleSize")
+ form.xLabel = self.widget(QtGui.QLineEdit, "titleX")
+ form.xSize = self.widget(QtGui.QSpinBox, "xSize")
+ form.yLabel = self.widget(QtGui.QLineEdit, "titleY")
+ form.ySize = self.widget(QtGui.QSpinBox, "ySize")
+
+ plt = Plot.getPlot()
+ form.axId.setEnabled(bool(plt))
+ form.title.setEnabled(bool(plt))
+ form.titleSize.setEnabled(bool(plt))
+ form.xLabel.setEnabled(bool(plt))
+ form.xSize.setEnabled(bool(plt))
+ form.yLabel.setEnabled(bool(plt))
+ form.ySize.setEnabled(bool(plt))
+ if not plt:
+ return
+ # Ensure that active axes is correct
+ index = min(form.axId.value(), len(plt.axesList) - 1)
+ form.axId.setValue(index)
+ # Store data before starting changing it.
+
+ ax = plt.axes
+ t = ax.get_title()
+ x = ax.get_xlabel()
+ y = ax.get_ylabel()
+ tt = ax.title.get_fontsize()
+ xx = ax.xaxis.label.get_fontsize()
+ yy = ax.yaxis.label.get_fontsize()
+ # Set labels
+ form.title.setText(t)
+ form.xLabel.setText(x)
+ form.yLabel.setText(y)
+ # Set font sizes
+ form.titleSize.setValue(tt)
+ form.xSize.setValue(xx)
+ form.ySize.setValue(yy)
+
def createTask():
- panel = TaskPanel()
- Gui.Control.showDialog(panel)
- if panel.setupUi():
- Gui.Control.closeDialog(panel)
- return None
- return panel
+ panel = TaskPanel()
+ Gui.Control.showDialog(panel)
+ if panel.setupUi():
+ Gui.Control.closeDialog(panel)
+ return None
+ return panel
diff --git a/src/Mod/Plot/plotLabels/__init__.py b/src/Mod/Plot/plotLabels/__init__.py
index 24058d7a93ee..6a97f58b26af 100644
--- a/src/Mod/Plot/plotLabels/__init__.py
+++ b/src/Mod/Plot/plotLabels/__init__.py
@@ -1,7 +1,7 @@
#***************************************************************************
#* *
-#* Copyright (c) 2011, 2012 *
-#* Jose Luis Cercos Pita *
+#* Copyright (c) 2011, 2012 *
+#* Jose Luis Cercos Pita *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
@@ -21,16 +21,9 @@
#* *
#***************************************************************************
-# FreeCAD modules
-import FreeCAD
-import FreeCADGui
-
-# Qt libraries
-from PyQt4 import QtGui,QtCore
-
-# Main object
import TaskPanel
+
def load():
- """ Loads the tool """
- TaskPanel.createTask()
+ """Load the tool"""
+ TaskPanel.createTask()
diff --git a/src/Mod/Plot/plotPositions/TaskPanel.py b/src/Mod/Plot/plotPositions/TaskPanel.py
index cc082489475a..9ff0bfebfcfc 100644
--- a/src/Mod/Plot/plotPositions/TaskPanel.py
+++ b/src/Mod/Plot/plotPositions/TaskPanel.py
@@ -1,234 +1,301 @@
#***************************************************************************
-#* *
-#* Copyright (c) 2011, 2012 *
-#* Jose Luis Cercos Pita *
-#* *
+#* *
+#* Copyright (c) 2011, 2012 *
+#* Jose Luis Cercos Pita *
+#* *
#* This program is free software; you can redistribute it and/or modify *
-#* it under the terms of the GNU Lesser General Public License (LGPL) *
-#* as published by the Free Software Foundation; either version 2 of *
-#* the License, or (at your option) any later version. *
-#* for detail see the LICENCE text file. *
-#* *
-#* This program 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 *
+#* it under the terms of the GNU Lesser General Public License (LGPL) *
+#* as published by the Free Software Foundation; either version 2 of *
+#* the License, or (at your option) any later version. *
+#* for detail see the LICENCE text file. *
+#* *
+#* This program 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 program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
-#* USA *
-#* *
+#* USA *
+#* *
#***************************************************************************
-# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
-# Qt library
-from PyQt4 import QtGui,QtCore
-# Module
+
+from PySide import QtGui, QtCore
+
import Plot
from plotUtils import Paths
+
class TaskPanel:
- def __init__(self):
- self.ui = Paths.modulePath() + "/plotPositions/TaskPanel.ui"
- self.skip = False
- self.item = 0
- self.names = []
- self.objs = []
- self.plt = None
-
- def accept(self):
- return True
-
- def reject(self):
- return True
-
- def clicked(self, index):
- pass
-
- def open(self):
- pass
-
- def needsFullSpace(self):
- return True
-
- def isAllowedAlterSelection(self):
- return False
-
- def isAllowedAlterView(self):
- return True
-
- def isAllowedAlterDocument(self):
- return False
-
- def helpRequested(self):
- pass
-
- def setupUi(self):
- mw = self.getMainWindow()
- form = mw.findChild(QtGui.QWidget, "TaskPanel")
- form.items = form.findChild(QtGui.QListWidget, "items")
- form.x = form.findChild(QtGui.QDoubleSpinBox, "x")
- form.y = form.findChild(QtGui.QDoubleSpinBox, "y")
- form.s = form.findChild(QtGui.QDoubleSpinBox, "size")
- self.form = form
- self.retranslateUi()
- self.updateUI()
- QtCore.QObject.connect(form.items, QtCore.SIGNAL("currentRowChanged(int)"),self.onItem)
- QtCore.QObject.connect(form.x, QtCore.SIGNAL("valueChanged(double)"),self.onData)
- QtCore.QObject.connect(form.y, QtCore.SIGNAL("valueChanged(double)"),self.onData)
- QtCore.QObject.connect(form.s, QtCore.SIGNAL("valueChanged(double)"),self.onData)
- QtCore.QObject.connect(Plot.getMdiArea(),QtCore.SIGNAL("subWindowActivated(QMdiSubWindow*)"),self.onMdiArea)
- return False
-
- def getMainWindow(self):
- "returns the main window"
- # using QtGui.qApp.activeWindow() isn't very reliable because if another
- # widget than the mainwindow is active (e.g. a dialog) the wrong widget is
- # returned
- toplevel = QtGui.qApp.topLevelWidgets()
- for i in toplevel:
- if i.metaObject().className() == "Gui::MainWindow":
- return i
- raise Exception("No main window found")
-
- def retranslateUi(self):
- """ Set user interface locale strings.
- """
- self.form.setWindowTitle(QtGui.QApplication.translate("plot_positions", "Set positions and sizes",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "posLabel").setText(QtGui.QApplication.translate("plot_positions", "Position",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "sizeLabel").setText(QtGui.QApplication.translate("plot_positions", "Size",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.items.setToolTip(QtGui.QApplication.translate("plot_positions", "List of modificable items",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.x.setToolTip(QtGui.QApplication.translate("plot_positions", "X item position",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.y.setToolTip(QtGui.QApplication.translate("plot_positions", "Y item position",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.s.setToolTip(QtGui.QApplication.translate("plot_positions", "Item size",
- None,QtGui.QApplication.UnicodeUTF8))
-
- def onItem(self, row):
- """ Executed when selected item is modified. """
- # Get selected item
- self.item = row
- # Call to update
- self.updateUI()
-
- def onData(self, value):
- """ Executed when selected item data is modified. """
- plt = Plot.getPlot()
- if not plt:
- self.updateUI()
- return
- if not self.skip:
- self.skip = True
- name = self.names[self.item]
- obj = self.objs[self.item]
- x = self.form.x.value()
- y = self.form.y.value()
- s = self.form.s.value()
- # x/y labels only have one position control
- if name.find('x label') >= 0:
- self.form.y.setValue(x)
- elif name.find('y label') >= 0:
- self.form.x.setValue(y)
- # title and labels only have one size control
- if name.find('title') >= 0 or name.find('label') >= 0:
- obj.set_position((x,y))
- obj.set_size(s)
- # legend have all controls
- else:
- Plot.legend(plt.legend, (x,y), s)
- plt.update()
- self.skip = False
-
- def onMdiArea(self, subWin):
- """ Executed when window is selected on mdi area.
- @param subWin Selected window.
- """
- plt = Plot.getPlot()
- if plt != subWin:
- self.updateUI()
-
- def updateUI(self):
- """ Setup UI controls values if possible """
- plt = Plot.getPlot()
- self.form.items.setEnabled(bool(plt))
- self.form.x.setEnabled(bool(plt))
- self.form.y.setEnabled(bool(plt))
- self.form.s.setEnabled(bool(plt))
- if not plt:
- self.plt = plt
- self.form.items.clear()
- return
- # Refill items list only if Plot instance have been changed
- if self.plt != plt:
- self.plt = plt
- self.plt.update() # Update plot in order to put legend in correct place
- self.setList()
- # Get data for controls
- name = self.names[self.item]
- obj = self.objs[self.item]
- if name.find('title') >= 0 or name.find('label') >= 0:
- p = obj.get_position()
- x = p[0]
- y = p[1]
- s = obj.get_size()
- if name.find('x label') >= 0:
- self.form.y.setEnabled(False)
- self.form.y.setValue(x)
- elif name.find('y label') >= 0:
- self.form.x.setEnabled(False)
- self.form.x.setValue(y)
- else:
- x = plt.legPos[0]
- y = plt.legPos[1]
- s = obj.get_texts()[-1].get_fontsize()
- # Send it to controls
- self.form.x.setValue(x)
- self.form.y.setValue(y)
- self.form.s.setValue(s)
-
- def setList(self):
- """ Setup UI controls values if possible """
- # Clear lists
- self.names = []
- self.objs = []
- # Fill lists with available objects
- if self.plt:
- # Axes data
- for i in range(0,len(self.plt.axesList)):
- ax = self.plt.axesList[i]
- # Each axes have title, xaxis and yaxis
- self.names.append('title (axes %d)' % (i))
- self.objs.append(ax.title)
- self.names.append('x label (axes %d)' % (i))
- self.objs.append(ax.xaxis.get_label())
- self.names.append('y label (axes %d)' % (i))
- self.objs.append(ax.yaxis.get_label())
- # Legend if exist
- ax = self.plt.axesList[-1]
- if ax.legend_:
- self.names.append('legend')
- self.objs.append(ax.legend_)
- # Send list to widget
- self.form.items.clear()
- for name in self.names:
- self.form.items.addItem(name)
- # Ensure that selected item is correct
- if self.item >= len(self.names):
- self.item = len(self.names)-1
- self.form.items.setCurrentIndex(self.item)
+ def __init__(self):
+ self.ui = Paths.modulePath() + "/plotPositions/TaskPanel.ui"
+ self.skip = False
+ self.item = 0
+ self.names = []
+ self.objs = []
+ self.plt = None
+
+ def accept(self):
+ return True
+
+ def reject(self):
+ return True
+
+ def clicked(self, index):
+ pass
+
+ def open(self):
+ pass
+
+ def needsFullSpace(self):
+ return True
+
+ def isAllowedAlterSelection(self):
+ return False
+
+ def isAllowedAlterView(self):
+ return True
+
+ def isAllowedAlterDocument(self):
+ return False
+
+ def helpRequested(self):
+ pass
+
+ def setupUi(self):
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.items = self.widget(QtGui.QListWidget, "items")
+ form.x = self.widget(QtGui.QDoubleSpinBox, "x")
+ form.y = self.widget(QtGui.QDoubleSpinBox, "y")
+ form.s = self.widget(QtGui.QDoubleSpinBox, "size")
+ self.form = form
+ self.retranslateUi()
+ self.updateUI()
+ QtCore.QObject.connect(
+ form.items,
+ QtCore.SIGNAL("currentRowChanged(int)"),
+ self.onItem)
+ QtCore.QObject.connect(
+ form.x,
+ QtCore.SIGNAL("valueChanged(double)"),
+ self.onData)
+ QtCore.QObject.connect(
+ form.y,
+ QtCore.SIGNAL("valueChanged(double)"),
+ self.onData)
+ QtCore.QObject.connect(
+ form.s,
+ QtCore.SIGNAL("valueChanged(double)"),
+ self.onData)
+ QtCore.QObject.connect(
+ Plot.getMdiArea(),
+ QtCore.SIGNAL("subWindowActivated(QMdiSubWindow*)"),
+ self.onMdiArea)
+ return False
+
+ def getMainWindow(self):
+ toplevel = QtGui.qApp.topLevelWidgets()
+ for i in toplevel:
+ if i.metaObject().className() == "Gui::MainWindow":
+ return i
+ raise Exception("No main window found")
+
+ def widget(self, class_id, name):
+ """Return the selected widget.
+
+ Keyword arguments:
+ class_id -- Class identifier
+ name -- Name of the widget
+ """
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ return form.findChild(class_id, name)
+
+ def retranslateUi(self):
+ """Set the user interface locale strings."""
+ self.form.setWindowTitle(QtGui.QApplication.translate(
+ "plot_positions",
+ "Set positions and sizes",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "posLabel").setText(
+ QtGui.QApplication.translate(
+ "plot_positions",
+ "Position",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "sizeLabel").setText(
+ QtGui.QApplication.translate(
+ "plot_positions",
+ "Size",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QListWidget, "items").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_positions",
+ "List of modificable items",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QDoubleSpinBox, "x").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_positions",
+ "X item position",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QDoubleSpinBox, "y").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_positions",
+ "Y item position",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QDoubleSpinBox, "size").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_positions",
+ "Item size",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+
+ def onItem(self, row):
+ """ Executed when selected item is modified. """
+ self.item = row
+ self.updateUI()
+
+ def onData(self, value):
+ """ Executed when selected item data is modified. """
+ plt = Plot.getPlot()
+ if not plt:
+ self.updateUI()
+ return
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.items = self.widget(QtGui.QListWidget, "items")
+ form.x = self.widget(QtGui.QDoubleSpinBox, "x")
+ form.y = self.widget(QtGui.QDoubleSpinBox, "y")
+ form.s = self.widget(QtGui.QDoubleSpinBox, "size")
+ if not self.skip:
+ self.skip = True
+ name = self.names[self.item]
+ obj = self.objs[self.item]
+ x = form.x.value()
+ y = form.y.value()
+ s = form.s.value()
+ # x/y labels only have one position control
+ if name.find('x label') >= 0:
+ form.y.setValue(x)
+ elif name.find('y label') >= 0:
+ form.x.setValue(y)
+ # title and labels only have one size control
+ if name.find('title') >= 0 or name.find('label') >= 0:
+ obj.set_position((x, y))
+ obj.set_size(s)
+ # legend have all controls
+ else:
+ Plot.legend(plt.legend, (x, y), s)
+ plt.update()
+ self.skip = False
+
+ def onMdiArea(self, subWin):
+ """Executed when a new window is selected on the mdi area.
+
+ Keyword arguments:
+ subWin -- Selected window.
+ """
+ plt = Plot.getPlot()
+ if plt != subWin:
+ self.updateUI()
+
+ def updateUI(self):
+ """Setup the UI control values if it is possible."""
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.items = self.widget(QtGui.QListWidget, "items")
+ form.x = self.widget(QtGui.QDoubleSpinBox, "x")
+ form.y = self.widget(QtGui.QDoubleSpinBox, "y")
+ form.s = self.widget(QtGui.QDoubleSpinBox, "size")
+ plt = Plot.getPlot()
+ form.items.setEnabled(bool(plt))
+ form.x.setEnabled(bool(plt))
+ form.y.setEnabled(bool(plt))
+ form.s.setEnabled(bool(plt))
+ if not plt:
+ self.plt = plt
+ form.items.clear()
+ return
+ # Refill items list only if Plot instance have been changed
+ if self.plt != plt:
+ self.plt = plt
+ self.plt.update()
+ self.setList()
+ # Get data for controls
+ name = self.names[self.item]
+ obj = self.objs[self.item]
+ if name.find('title') >= 0 or name.find('label') >= 0:
+ p = obj.get_position()
+ x = p[0]
+ y = p[1]
+ s = obj.get_size()
+ if name.find('x label') >= 0:
+ form.y.setEnabled(False)
+ form.y.setValue(x)
+ elif name.find('y label') >= 0:
+ form.x.setEnabled(False)
+ form.x.setValue(y)
+ else:
+ x = plt.legPos[0]
+ y = plt.legPos[1]
+ s = obj.get_texts()[-1].get_fontsize()
+ # Send it to controls
+ form.x.setValue(x)
+ form.y.setValue(y)
+ form.s.setValue(s)
+
+ def setList(self):
+ """ Setup UI controls values if possible """
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.items = self.widget(QtGui.QListWidget, "items")
+ form.x = self.widget(QtGui.QDoubleSpinBox, "x")
+ form.y = self.widget(QtGui.QDoubleSpinBox, "y")
+ form.s = self.widget(QtGui.QDoubleSpinBox, "size")
+ # Clear lists
+ self.names = []
+ self.objs = []
+ # Fill lists with available objects
+ if self.plt:
+ # Axes data
+ for i in range(0, len(self.plt.axesList)):
+ ax = self.plt.axesList[i]
+ # Each axes have title, xaxis and yaxis
+ self.names.append('title (axes {})'.format(i))
+ self.objs.append(ax.title)
+ self.names.append('x label (axes {})'.format(i))
+ self.objs.append(ax.xaxis.get_label())
+ self.names.append('y label (axes {})'.format(i))
+ self.objs.append(ax.yaxis.get_label())
+ # Legend if exist
+ ax = self.plt.axesList[-1]
+ if ax.legend_:
+ self.names.append('legend')
+ self.objs.append(ax.legend_)
+ # Send list to widget
+ form.items.clear()
+ for name in self.names:
+ form.items.addItem(name)
+ # Ensure that selected item is correct
+ if self.item >= len(self.names):
+ self.item = len(self.names) - 1
+ form.items.setCurrentIndex(self.item)
+
def createTask():
- panel = TaskPanel()
- Gui.Control.showDialog(panel)
- if panel.setupUi():
- Gui.Control.closeDialog(panel)
- return None
- return panel
+ panel = TaskPanel()
+ Gui.Control.showDialog(panel)
+ if panel.setupUi():
+ Gui.Control.closeDialog(panel)
+ return None
+ return panel
diff --git a/src/Mod/Plot/plotPositions/__init__.py b/src/Mod/Plot/plotPositions/__init__.py
index 24058d7a93ee..6a97f58b26af 100644
--- a/src/Mod/Plot/plotPositions/__init__.py
+++ b/src/Mod/Plot/plotPositions/__init__.py
@@ -1,7 +1,7 @@
#***************************************************************************
#* *
-#* Copyright (c) 2011, 2012 *
-#* Jose Luis Cercos Pita *
+#* Copyright (c) 2011, 2012 *
+#* Jose Luis Cercos Pita *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
@@ -21,16 +21,9 @@
#* *
#***************************************************************************
-# FreeCAD modules
-import FreeCAD
-import FreeCADGui
-
-# Qt libraries
-from PyQt4 import QtGui,QtCore
-
-# Main object
import TaskPanel
+
def load():
- """ Loads the tool """
- TaskPanel.createTask()
+ """Load the tool"""
+ TaskPanel.createTask()
diff --git a/src/Mod/Plot/plotSave/TaskPanel.py b/src/Mod/Plot/plotSave/TaskPanel.py
index 1ee042de1399..2ba6d936c835 100644
--- a/src/Mod/Plot/plotSave/TaskPanel.py
+++ b/src/Mod/Plot/plotSave/TaskPanel.py
@@ -1,163 +1,235 @@
#***************************************************************************
-#* *
-#* Copyright (c) 2011, 2012 *
-#* Jose Luis Cercos Pita *
-#* *
+#* *
+#* Copyright (c) 2011, 2012 *
+#* Jose Luis Cercos Pita *
+#* *
#* This program is free software; you can redistribute it and/or modify *
-#* it under the terms of the GNU Lesser General Public License (LGPL) *
-#* as published by the Free Software Foundation; either version 2 of *
-#* the License, or (at your option) any later version. *
-#* for detail see the LICENCE text file. *
-#* *
-#* This program 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 *
+#* it under the terms of the GNU Lesser General Public License (LGPL) *
+#* as published by the Free Software Foundation; either version 2 of *
+#* the License, or (at your option) any later version. *
+#* for detail see the LICENCE text file. *
+#* *
+#* This program 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 program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
-#* USA *
-#* *
+#* USA *
+#* *
#***************************************************************************
import os
-# FreeCAD modules
+
import FreeCAD as App
import FreeCADGui as Gui
-# Qt library
-from PyQt4 import QtGui,QtCore
-# Module
+
+from PySide import QtGui, QtCore
+
import Plot
from plotUtils import Paths
+
class TaskPanel:
- def __init__(self):
- self.ui = Paths.modulePath() + "/plotSave/TaskPanel.ui"
-
- def accept(self):
- plt = Plot.getPlot()
- if not plt:
- msg = QtGui.QApplication.translate("plot_console", "Plot document must be selected in order to save it",
- None,QtGui.QApplication.UnicodeUTF8)
- App.Console.PrintError(msg+"\n")
- return False
- path = unicode(self.form.path.text())
- size = (self.form.sizeX.value(), self.form.sizeY.value())
- dpi = self.form.dpi.value()
- Plot.save(path, size, dpi)
- return True
-
- def reject(self):
- return True
-
- def clicked(self, index):
- pass
-
- def open(self):
- pass
-
- def needsFullSpace(self):
- return True
-
- def isAllowedAlterSelection(self):
- return False
-
- def isAllowedAlterView(self):
- return True
-
- def isAllowedAlterDocument(self):
- return False
-
- def helpRequested(self):
- pass
-
- def setupUi(self):
- mw = self.getMainWindow()
- form = mw.findChild(QtGui.QWidget, "TaskPanel")
- form.path = form.findChild(QtGui.QLineEdit, "path")
- form.pathButton = form.findChild(QtGui.QPushButton, "pathButton")
- form.sizeX = form.findChild(QtGui.QDoubleSpinBox, "sizeX")
- form.sizeY = form.findChild(QtGui.QDoubleSpinBox, "sizeY")
- form.dpi = form.findChild(QtGui.QSpinBox, "dpi")
- self.form = form
- self.retranslateUi()
- QtCore.QObject.connect(form.pathButton,QtCore.SIGNAL("pressed()"),self.onPathButton)
- QtCore.QObject.connect(Plot.getMdiArea(),QtCore.SIGNAL("subWindowActivated(QMdiSubWindow*)"),self.onMdiArea)
- home = os.getenv('USERPROFILE') or os.getenv('HOME')
- form.path.setText(os.path.join(home,"plot.png"))
- self.updateUI()
- return False
-
- def getMainWindow(self):
- "returns the main window"
- # using QtGui.qApp.activeWindow() isn't very reliable because if another
- # widget than the mainwindow is active (e.g. a dialog) the wrong widget is
- # returned
- toplevel = QtGui.qApp.topLevelWidgets()
- for i in toplevel:
- if i.metaObject().className() == "Gui::MainWindow":
- return i
- raise Exception("No main window found")
-
- def retranslateUi(self):
- """ Set user interface locale strings.
- """
- self.form.setWindowTitle(QtGui.QApplication.translate("plot_save", "Save figure",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "sizeLabel").setText(QtGui.QApplication.translate("plot_save", "Inches",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "dpiLabel").setText(QtGui.QApplication.translate("plot_save", "Dots per Inch",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.path.setToolTip(QtGui.QApplication.translate("plot_save", "Output image file path",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.pathButton.setToolTip(QtGui.QApplication.translate("plot_save", "Show a file selection dialog",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.sizeX.setToolTip(QtGui.QApplication.translate("plot_save", "X image size",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.sizeY.setToolTip(QtGui.QApplication.translate("plot_save", "Y image size",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.dpi.setToolTip(QtGui.QApplication.translate("plot_save", "Dots per point, with size will define output image resolution",
- None,QtGui.QApplication.UnicodeUTF8))
-
- def updateUI(self):
- """ Setup UI controls values if possible """
- plt = Plot.getPlot()
- self.form.path.setEnabled(bool(plt))
- self.form.pathButton.setEnabled(bool(plt))
- self.form.sizeX.setEnabled(bool(plt))
- self.form.sizeY.setEnabled(bool(plt))
- self.form.dpi.setEnabled(bool(plt))
- if not plt:
- return
- fig = plt.fig
- size = fig.get_size_inches()
- dpi = fig.get_dpi()
- self.form.sizeX.setValue(size[0])
- self.form.sizeY.setValue(size[1])
- self.form.dpi.setValue(dpi)
-
- def onPathButton(self):
- """ Executed when path button is pressed.
- """
- path = self.form.path.text()
- file_choices = "Portable Network Graphics (*.png)|*.png;;Portable Document Format (*.pdf)|*.pdf;;PostScript (*.ps)|*.ps;;Encapsulated PostScript (*.eps)|*.eps"
- path = QtGui.QFileDialog.getSaveFileName(None, 'Save figure', path, file_choices)
- if path:
- self.form.path.setText(path)
-
- def onMdiArea(self, subWin):
- """ Executed when window is selected on mdi area.
- @param subWin Selected window.
- """
- plt = Plot.getPlot()
- if plt != subWin:
- self.updateUI()
+ def __init__(self):
+ self.ui = Paths.modulePath() + "/plotSave/TaskPanel.ui"
+
+ def accept(self):
+ plt = Plot.getPlot()
+ if not plt:
+ msg = QtGui.QApplication.translate(
+ "plot_console",
+ "Plot document must be selected in order to save it",
+ None,
+ QtGui.QApplication.UnicodeUTF8)
+ App.Console.PrintError(msg + "\n")
+ return False
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.path = self.widget(QtGui.QLineEdit, "path")
+ form.sizeX = self.widget(QtGui.QDoubleSpinBox, "sizeX")
+ form.sizeY = self.widget(QtGui.QDoubleSpinBox, "sizeY")
+ form.dpi = self.widget(QtGui.QSpinBox, "dpi")
+ path = unicode(form.path.text())
+ size = (form.sizeX.value(), form.sizeY.value())
+ dpi = form.dpi.value()
+ Plot.save(path, size, dpi)
+ return True
+
+ def reject(self):
+ return True
+
+ def clicked(self, index):
+ pass
+
+ def open(self):
+ pass
+
+ def needsFullSpace(self):
+ return True
+
+ def isAllowedAlterSelection(self):
+ return False
+
+ def isAllowedAlterView(self):
+ return True
+
+ def isAllowedAlterDocument(self):
+ return False
+
+ def helpRequested(self):
+ pass
+
+ def setupUi(self):
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.path = self.widget(QtGui.QLineEdit, "path")
+ form.pathButton = self.widget(QtGui.QPushButton, "pathButton")
+ form.sizeX = self.widget(QtGui.QDoubleSpinBox, "sizeX")
+ form.sizeY = self.widget(QtGui.QDoubleSpinBox, "sizeY")
+ form.dpi = self.widget(QtGui.QSpinBox, "dpi")
+ self.form = form
+ self.retranslateUi()
+ QtCore.QObject.connect(
+ form.pathButton,
+ QtCore.SIGNAL("pressed()"),
+ self.onPathButton)
+ QtCore.QObject.connect(
+ Plot.getMdiArea(),
+ QtCore.SIGNAL("subWindowActivated(QMdiSubWindow*)"),
+ self.onMdiArea)
+ home = os.getenv('USERPROFILE') or os.getenv('HOME')
+ form.path.setText(os.path.join(home, "plot.png"))
+ self.updateUI()
+ return False
+
+ def getMainWindow(self):
+ toplevel = QtGui.qApp.topLevelWidgets()
+ for i in toplevel:
+ if i.metaObject().className() == "Gui::MainWindow":
+ return i
+ raise Exception("No main window found")
+
+ def widget(self, class_id, name):
+ """Return the selected widget.
+
+ Keyword arguments:
+ class_id -- Class identifier
+ name -- Name of the widget
+ """
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ return form.findChild(class_id, name)
+
+ def retranslateUi(self):
+ """Set the user interface locale strings."""
+ self.form.setWindowTitle(QtGui.QApplication.translate(
+ "plot_save",
+ "Save figure",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "sizeLabel").setText(
+ QtGui.QApplication.translate(
+ "plot_save",
+ "Inches",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "dpiLabel").setText(
+ QtGui.QApplication.translate(
+ "plot_save",
+ "Dots per Inch",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLineEdit, "path").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_save",
+ "Output image file path",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QPushButton, "pathButton").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_save",
+ "Show a file selection dialog",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QDoubleSpinBox, "sizeX").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_save",
+ "X image size",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QDoubleSpinBox, "sizeY").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_save",
+ "Y image size",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QSpinBox, "dpi").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_save",
+ "Dots per point, with size will define output image"
+ " resolution",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+
+ def updateUI(self):
+ """ Setup UI controls values if possible """
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.path = self.widget(QtGui.QLineEdit, "path")
+ form.pathButton = self.widget(QtGui.QPushButton, "pathButton")
+ form.sizeX = self.widget(QtGui.QDoubleSpinBox, "sizeX")
+ form.sizeY = self.widget(QtGui.QDoubleSpinBox, "sizeY")
+ form.dpi = self.widget(QtGui.QSpinBox, "dpi")
+ plt = Plot.getPlot()
+ form.path.setEnabled(bool(plt))
+ form.pathButton.setEnabled(bool(plt))
+ form.sizeX.setEnabled(bool(plt))
+ form.sizeY.setEnabled(bool(plt))
+ form.dpi.setEnabled(bool(plt))
+ if not plt:
+ return
+ fig = plt.fig
+ size = fig.get_size_inches()
+ dpi = fig.get_dpi()
+ form.sizeX.setValue(size[0])
+ form.sizeY.setValue(size[1])
+ form.dpi.setValue(dpi)
+
+ def onPathButton(self):
+ """Executed when the path selection button is pressed."""
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.path = self.widget(QtGui.QLineEdit, "path")
+ path = form.path.text()
+ file_choices = ("Portable Network Graphics (*.png)|*.png;;"
+ "Portable Document Format (*.pdf)|*.pdf;;"
+ "PostScript (*.ps)|*.ps;;"
+ "Encapsulated PostScript (*.eps)|*.eps")
+ path = QtGui.QFileDialog.getSaveFileName(None,
+ 'Save figure',
+ path,
+ file_choices)
+ if path:
+ form.path.setText(path)
+
+ def onMdiArea(self, subWin):
+ """Executed when a new window is selected on the mdi area.
+
+ Keyword arguments:
+ subWin -- Selected window.
+ """
+ plt = Plot.getPlot()
+ if plt != subWin:
+ self.updateUI()
+
def createTask():
- panel = TaskPanel()
- Gui.Control.showDialog(panel)
- if panel.setupUi():
- Gui.Control.closeDialog(panel)
- return None
- return panel
+ panel = TaskPanel()
+ Gui.Control.showDialog(panel)
+ if panel.setupUi():
+ Gui.Control.closeDialog(panel)
+ return None
+ return panel
diff --git a/src/Mod/Plot/plotSave/__init__.py b/src/Mod/Plot/plotSave/__init__.py
index 24058d7a93ee..6a97f58b26af 100644
--- a/src/Mod/Plot/plotSave/__init__.py
+++ b/src/Mod/Plot/plotSave/__init__.py
@@ -1,7 +1,7 @@
#***************************************************************************
#* *
-#* Copyright (c) 2011, 2012 *
-#* Jose Luis Cercos Pita *
+#* Copyright (c) 2011, 2012 *
+#* Jose Luis Cercos Pita *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
@@ -21,16 +21,9 @@
#* *
#***************************************************************************
-# FreeCAD modules
-import FreeCAD
-import FreeCADGui
-
-# Qt libraries
-from PyQt4 import QtGui,QtCore
-
-# Main object
import TaskPanel
+
def load():
- """ Loads the tool """
- TaskPanel.createTask()
+ """Load the tool"""
+ TaskPanel.createTask()
diff --git a/src/Mod/Plot/plotSeries/TaskPanel.py b/src/Mod/Plot/plotSeries/TaskPanel.py
index 381d41b89ef7..f32b8aeacc71 100644
--- a/src/Mod/Plot/plotSeries/TaskPanel.py
+++ b/src/Mod/Plot/plotSeries/TaskPanel.py
@@ -1,332 +1,462 @@
#***************************************************************************
-#* *
-#* Copyright (c) 2011, 2012 *
-#* Jose Luis Cercos Pita *
-#* *
+#* *
+#* Copyright (c) 2011, 2012 *
+#* Jose Luis Cercos Pita *
+#* *
#* This program is free software; you can redistribute it and/or modify *
-#* it under the terms of the GNU Lesser General Public License (LGPL) *
-#* as published by the Free Software Foundation; either version 2 of *
-#* the License, or (at your option) any later version. *
-#* for detail see the LICENCE text file. *
-#* *
-#* This program 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 *
+#* it under the terms of the GNU Lesser General Public License (LGPL) *
+#* as published by the Free Software Foundation; either version 2 of *
+#* the License, or (at your option) any later version. *
+#* for detail see the LICENCE text file. *
+#* *
+#* This program 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 program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
-#* USA *
-#* *
+#* USA *
+#* *
#***************************************************************************
-# FreeCAD modules
import FreeCAD as App
import FreeCADGui as Gui
-# Qt library
-from PyQt4 import QtGui,QtCore
-# Module
+
+from PySide import QtGui, QtCore
+
import Plot
from plotUtils import Paths
-# matplotlib
+
import matplotlib
from matplotlib.lines import Line2D
import matplotlib.colors as Colors
+
class TaskPanel:
- def __init__(self):
- self.ui = Paths.modulePath() + "/plotSeries/TaskPanel.ui"
- self.skip = False
- self.item = 0
- self.plt = None
-
- def accept(self):
- return True
-
- def reject(self):
- return True
-
- def clicked(self, index):
- pass
-
- def open(self):
- pass
-
- def needsFullSpace(self):
- return True
-
- def isAllowedAlterSelection(self):
- return False
-
- def isAllowedAlterView(self):
- return True
-
- def isAllowedAlterDocument(self):
- return False
-
- def helpRequested(self):
- pass
-
- def setupUi(self):
- mw = self.getMainWindow()
- form = mw.findChild(QtGui.QWidget, "TaskPanel")
- form.items = form.findChild(QtGui.QListWidget, "items")
- form.label = form.findChild(QtGui.QLineEdit, "label")
- form.isLabel = form.findChild(QtGui.QCheckBox, "isLabel")
- form.style = form.findChild(QtGui.QComboBox, "lineStyle")
- form.marker = form.findChild(QtGui.QComboBox, "markers")
- form.width = form.findChild(QtGui.QDoubleSpinBox, "lineWidth")
- form.size = form.findChild(QtGui.QSpinBox, "markerSize")
- form.color = form.findChild(QtGui.QPushButton, "color")
- form.remove = form.findChild(QtGui.QPushButton, "remove")
- self.form = form
- self.retranslateUi()
- self.fillStyles()
- self.updateUI()
- QtCore.QObject.connect(form.items, QtCore.SIGNAL("currentRowChanged(int)"),self.onItem)
- QtCore.QObject.connect(form.label, QtCore.SIGNAL("editingFinished()"),self.onData)
- QtCore.QObject.connect(form.isLabel,QtCore.SIGNAL("stateChanged(int)"),self.onData)
- QtCore.QObject.connect(form.style, QtCore.SIGNAL("currentIndexChanged(int)"),self.onData)
- QtCore.QObject.connect(form.marker, QtCore.SIGNAL("currentIndexChanged(int)"),self.onData)
- QtCore.QObject.connect(form.width, QtCore.SIGNAL("valueChanged(double)"),self.onData)
- QtCore.QObject.connect(form.size, QtCore.SIGNAL("valueChanged(int)"),self.onData)
- QtCore.QObject.connect(form.color, QtCore.SIGNAL("pressed()"),self.onColor)
- QtCore.QObject.connect(form.remove, QtCore.SIGNAL("pressed()"),self.onRemove)
- QtCore.QObject.connect(Plot.getMdiArea(),QtCore.SIGNAL("subWindowActivated(QMdiSubWindow*)"),self.onMdiArea)
- return False
-
- def getMainWindow(self):
- "returns the main window"
- # using QtGui.qApp.activeWindow() isn't very reliable because if another
- # widget than the mainwindow is active (e.g. a dialog) the wrong widget is
- # returned
- toplevel = QtGui.qApp.topLevelWidgets()
- for i in toplevel:
- if i.metaObject().className() == "Gui::MainWindow":
- return i
- raise Exception("No main window found")
-
- def retranslateUi(self):
- """ Set user interface locale strings.
- """
- self.form.setWindowTitle(QtGui.QApplication.translate("plot_series", "Configure series",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.isLabel.setText(QtGui.QApplication.translate("plot_series", "No label",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.remove.setText(QtGui.QApplication.translate("plot_series", "Remove serie",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "styleLabel").setText(QtGui.QApplication.translate("plot_series", "Line style",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.findChild(QtGui.QLabel, "markerLabel").setText(QtGui.QApplication.translate("plot_series", "Marker",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.items.setToolTip(QtGui.QApplication.translate("plot_series", "List of available series",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.label.setToolTip(QtGui.QApplication.translate("plot_series", "Line title",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.isLabel.setToolTip(QtGui.QApplication.translate("plot_series", "If checked serie will not be considered for legend",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.style.setToolTip(QtGui.QApplication.translate("plot_series", "Line style",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.marker.setToolTip(QtGui.QApplication.translate("plot_series", "Marker style",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.width.setToolTip(QtGui.QApplication.translate("plot_series", "Line width",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.size.setToolTip(QtGui.QApplication.translate("plot_series", "Marker size",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.color.setToolTip(QtGui.QApplication.translate("plot_series", "Line and marker color",
- None,QtGui.QApplication.UnicodeUTF8))
- self.form.remove.setToolTip(QtGui.QApplication.translate("plot_series", "Removes this serie",
- None,QtGui.QApplication.UnicodeUTF8))
-
- def fillStyles(self):
- """ Fill style combo boxes. """
- # Line styles
- linestyles = Line2D.lineStyles.keys()
- for i in range(0,len(linestyles)):
- style = linestyles[i]
- string = "\'" + str(style) + "\' (" + Line2D.lineStyles[style] + ")"
- self.form.style.addItem(string)
- # Markers
- markers = Line2D.markers.keys()
- for i in range(0,len(markers)):
- marker = markers[i]
- string = "\'" + str(marker) + "\' (" + Line2D.markers[marker] + ")"
- self.form.marker.addItem(string)
-
- def onItem(self, row):
- """ Executed when selected item is modified. """
- if not self.skip:
- self.skip = True
- # Get selected item
- self.item = row
- # Call to update
- self.updateUI()
- self.skip = False
-
- def onData(self):
- """ Executed when selected item data is modified. """
- if not self.skip:
- self.skip = True
- plt = Plot.getPlot()
- if not plt:
- self.updateUI()
- return
- # Ensure that selected serie exist
- if self.item >= len(Plot.series()):
- self.updateUI()
- return
- # Set label
- serie = Plot.series()[self.item]
- if(self.form.isLabel.isChecked()):
- serie.name = None
- self.form.label.setEnabled(False)
- else:
- serie.name = self.form.label.text()
- self.form.label.setEnabled(True)
- # Set line style and marker
- style = self.form.style.currentIndex()
- linestyles = Line2D.lineStyles.keys()
- serie.line.set_linestyle(linestyles[style])
- marker = self.form.marker.currentIndex()
- markers = Line2D.markers.keys()
- serie.line.set_marker(markers[marker])
- # Set line width and marker size
- serie.line.set_linewidth(self.form.width.value())
- serie.line.set_markersize(self.form.size.value())
- plt.update()
- # Regenerate series labels
- self.setList()
- self.skip = False
-
- def onColor(self):
- """ Executed when color pallete is requested. """
- plt = Plot.getPlot()
- if not plt:
- self.updateUI()
- return
- # Ensure that selected serie exist
- if self.item >= len(Plot.series()):
- self.updateUI()
- return
- # Show widget to select color
- col = QtGui.QColorDialog.getColor()
- # Send color to widget and serie
- if col.isValid():
- serie = plt.series[self.item]
- self.form.color.setStyleSheet("background-color: rgb(%d, %d, %d);" % (col.red(),
- col.green(), col.blue()))
- serie.line.set_color((col.redF(), col.greenF(), col.blueF()))
- plt.update()
-
- def onRemove(self):
- """ Executed when data serie must be removed. """
- plt = Plot.getPlot()
- if not plt:
- self.updateUI()
- return
- # Ensure that selected serie exist
- if self.item >= len(Plot.series()):
- self.updateUI()
- return
- # Remove serie
- Plot.removeSerie(self.item)
- self.setList()
- self.updateUI()
- plt.update()
-
- def onMdiArea(self, subWin):
- """ Executed when window is selected on mdi area.
- @param subWin Selected window.
- """
- plt = Plot.getPlot()
- if plt != subWin:
- self.updateUI()
-
- def updateUI(self):
- """ Setup UI controls values if possible """
- plt = Plot.getPlot()
- self.form.items.setEnabled(bool(plt))
- self.form.label.setEnabled(bool(plt))
- self.form.isLabel.setEnabled(bool(plt))
- self.form.style.setEnabled(bool(plt))
- self.form.marker.setEnabled(bool(plt))
- self.form.width.setEnabled(bool(plt))
- self.form.size.setEnabled(bool(plt))
- self.form.color.setEnabled(bool(plt))
- self.form.remove.setEnabled(bool(plt))
- if not plt:
- self.plt = plt
- self.form.items.clear()
- return
- self.skip = True
- # Refill list
- if self.plt != plt or len(Plot.series()) != self.form.items.count():
- self.plt = plt
- self.setList()
- # Ensure that have series
- if not len(Plot.series()):
- self.form.label.setEnabled(False)
- self.form.isLabel.setEnabled(False)
- self.form.style.setEnabled(False)
- self.form.marker.setEnabled(False)
- self.form.width.setEnabled(False)
- self.form.size.setEnabled(False)
- self.form.color.setEnabled(False)
- self.form.remove.setEnabled(False)
- return
- # Set label
- serie = Plot.series()[self.item]
- if serie.name == None:
- self.form.isLabel.setChecked(True)
- self.form.label.setEnabled(False)
- self.form.label.setText("")
- else:
- self.form.isLabel.setChecked(False)
- self.form.label.setText(serie.name)
- # Set line style and marker
- self.form.style.setCurrentIndex(0)
- linestyles = Line2D.lineStyles.keys()
- for i in range(0,len(linestyles)):
- style = linestyles[i]
- if style == serie.line.get_linestyle():
- self.form.style.setCurrentIndex(i)
- self.form.marker.setCurrentIndex(0)
- markers = Line2D.markers.keys()
- for i in range(0,len(markers)):
- marker = markers[i]
- if marker == serie.line.get_marker():
- self.form.marker.setCurrentIndex(i)
- # Set line width and marker size
- self.form.width.setValue(serie.line.get_linewidth())
- self.form.size.setValue(serie.line.get_markersize())
- # Set color
- color = Colors.colorConverter.to_rgb(serie.line.get_color())
- self.form.color.setStyleSheet("background-color: rgb(%d, %d, %d);" % (int(color[0]*255),
- int(color[1]*255), int(color[2]*255)))
- self.skip = False
-
- def setList(self):
- """ Setup UI controls values if possible """
- self.form.items.clear()
- series = Plot.series()
- for i in range(0,len(series)):
- serie = series[i]
- string = 'serie ' + str(i) + ': '
- if serie.name == None:
- string = string + '\"No label\"'
- else:
- string = string + serie.name
- self.form.items.addItem(string)
- # Ensure that selected item is correct
- if len(series) and self.item >= len(series):
- self.item = len(series)-1
- self.form.items.setCurrentIndex(self.item)
+ def __init__(self):
+ self.ui = Paths.modulePath() + "/plotSeries/TaskPanel.ui"
+ self.skip = False
+ self.item = 0
+ self.plt = None
+
+ def accept(self):
+ return True
+
+ def reject(self):
+ return True
+
+ def clicked(self, index):
+ pass
+
+ def open(self):
+ pass
+
+ def needsFullSpace(self):
+ return True
+
+ def isAllowedAlterSelection(self):
+ return False
+
+ def isAllowedAlterView(self):
+ return True
+
+ def isAllowedAlterDocument(self):
+ return False
+
+ def helpRequested(self):
+ pass
+
+ def setupUi(self):
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.items = self.widget(QtGui.QListWidget, "items")
+ form.label = self.widget(QtGui.QLineEdit, "label")
+ form.isLabel = self.widget(QtGui.QCheckBox, "isLabel")
+ form.style = self.widget(QtGui.QComboBox, "lineStyle")
+ form.marker = self.widget(QtGui.QComboBox, "markers")
+ form.width = self.widget(QtGui.QDoubleSpinBox, "lineWidth")
+ form.size = self.widget(QtGui.QSpinBox, "markerSize")
+ form.color = self.widget(QtGui.QPushButton, "color")
+ form.remove = self.widget(QtGui.QPushButton, "remove")
+ self.form = form
+ self.retranslateUi()
+ self.fillStyles()
+ self.updateUI()
+ QtCore.QObject.connect(
+ form.items,
+ QtCore.SIGNAL("currentRowChanged(int)"),
+ self.onItem)
+ QtCore.QObject.connect(
+ form.label,
+ QtCore.SIGNAL("editingFinished()"),
+ self.onData)
+ QtCore.QObject.connect(
+ form.isLabel,
+ QtCore.SIGNAL("stateChanged(int)"),
+ self.onData)
+ QtCore.QObject.connect(
+ form.style,
+ QtCore.SIGNAL("currentIndexChanged(int)"),
+ self.onData)
+ QtCore.QObject.connect(
+ form.marker,
+ QtCore.SIGNAL("currentIndexChanged(int)"),
+ self.onData)
+ QtCore.QObject.connect(
+ form.width,
+ QtCore.SIGNAL("valueChanged(double)"),
+ self.onData)
+ QtCore.QObject.connect(
+ form.size,
+ QtCore.SIGNAL("valueChanged(int)"),
+ self.onData)
+ QtCore.QObject.connect(
+ form.color,
+ QtCore.SIGNAL("pressed()"),
+ self.onColor)
+ QtCore.QObject.connect(
+ form.remove,
+ QtCore.SIGNAL("pressed()"),
+ self.onRemove)
+ QtCore.QObject.connect(
+ Plot.getMdiArea(),
+ QtCore.SIGNAL("subWindowActivated(QMdiSubWindow*)"),
+ self.onMdiArea)
+ return False
+
+ def getMainWindow(self):
+ toplevel = QtGui.qApp.topLevelWidgets()
+ for i in toplevel:
+ if i.metaObject().className() == "Gui::MainWindow":
+ return i
+ raise Exception("No main window found")
+
+ def widget(self, class_id, name):
+ """Return the selected widget.
+
+ Keyword arguments:
+ class_id -- Class identifier
+ name -- Name of the widget
+ """
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ return form.findChild(class_id, name)
+
+ def retranslateUi(self):
+ """Set the user interface locale strings."""
+ self.form.setWindowTitle(QtGui.QApplication.translate(
+ "plot_series",
+ "Configure series",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QCheckBox, "isLabel").setText(
+ QtGui.QApplication.translate(
+ "plot_series",
+ "No label",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QPushButton, "remove").setText(
+ QtGui.QApplication.translate(
+ "plot_series",
+ "Remove serie",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "styleLabel").setText(
+ QtGui.QApplication.translate(
+ "plot_series",
+ "Line style",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLabel, "markerLabel").setText(
+ QtGui.QApplication.translate(
+ "plot_series",
+ "Marker",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QListWidget, "items").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_series",
+ "List of available series",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QLineEdit, "label").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_series",
+ "Line title",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QCheckBox, "isLabel").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_series",
+ "If checked serie will not be considered for legend",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QComboBox, "lineStyle").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_series",
+ "Line style",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QComboBox, "markers").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_series",
+ "Marker style",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QDoubleSpinBox, "lineWidth").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_series",
+ "Line width",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QSpinBox, "markerSize").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_series",
+ "Marker size",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QPushButton, "color").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_series",
+ "Line and marker color",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+ self.widget(QtGui.QPushButton, "remove").setToolTip(
+ QtGui.QApplication.translate(
+ "plot_series",
+ "Removes this serie",
+ None,
+ QtGui.QApplication.UnicodeUTF8))
+
+ def fillStyles(self):
+ """Fill the style combo boxes with the availabel ones."""
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.style = self.widget(QtGui.QComboBox, "lineStyle")
+ form.marker = self.widget(QtGui.QComboBox, "markers")
+ # Line styles
+ linestyles = Line2D.lineStyles.keys()
+ for i in range(0, len(linestyles)):
+ style = linestyles[i]
+ string = "\'" + str(style) + "\'"
+ string += " (" + Line2D.lineStyles[style] + ")"
+ form.style.addItem(string)
+ # Markers
+ markers = Line2D.markers.keys()
+ for i in range(0, len(markers)):
+ marker = markers[i]
+ string = "\'" + str(marker) + "\'"
+ string += " (" + Line2D.markers[marker] + ")"
+ form.marker.addItem(string)
+
+ def onItem(self, row):
+ """Executed when the selected item is modified."""
+ if not self.skip:
+ self.skip = True
+
+ self.item = row
+
+ self.updateUI()
+ self.skip = False
+
+ def onData(self):
+ """Executed when the selected item data is modified."""
+ if not self.skip:
+ self.skip = True
+ plt = Plot.getPlot()
+ if not plt:
+ self.updateUI()
+ return
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.label = self.widget(QtGui.QLineEdit, "label")
+ form.isLabel = self.widget(QtGui.QCheckBox, "isLabel")
+ form.style = self.widget(QtGui.QComboBox, "lineStyle")
+ form.marker = self.widget(QtGui.QComboBox, "markers")
+ form.width = self.widget(QtGui.QDoubleSpinBox, "lineWidth")
+ form.size = self.widget(QtGui.QSpinBox, "markerSize")
+ # Ensure that selected serie exist
+ if self.item >= len(Plot.series()):
+ self.updateUI()
+ return
+ # Set label
+ serie = Plot.series()[self.item]
+ if(form.isLabel.isChecked()):
+ serie.name = None
+ form.label.setEnabled(False)
+ else:
+ serie.name = form.label.text()
+ form.label.setEnabled(True)
+ # Set line style and marker
+ style = form.style.currentIndex()
+ linestyles = Line2D.lineStyles.keys()
+ serie.line.set_linestyle(linestyles[style])
+ marker = form.marker.currentIndex()
+ markers = Line2D.markers.keys()
+ serie.line.set_marker(markers[marker])
+ # Set line width and marker size
+ serie.line.set_linewidth(form.width.value())
+ serie.line.set_markersize(form.size.value())
+ plt.update()
+ # Regenerate series labels
+ self.setList()
+ self.skip = False
+
+ def onColor(self):
+ """ Executed when color pallete is requested. """
+ plt = Plot.getPlot()
+ if not plt:
+ self.updateUI()
+ return
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.color = self.widget(QtGui.QPushButton, "color")
+
+ # Ensure that selected serie exist
+ if self.item >= len(Plot.series()):
+ self.updateUI()
+ return
+ # Show widget to select color
+ col = QtGui.QColorDialog.getColor()
+ # Send color to widget and serie
+ if col.isValid():
+ serie = plt.series[self.item]
+ form.color.setStyleSheet(
+ "background-color: rgb({}, {}, {});".format(col.red(),
+ col.green(),
+ col.blue()))
+ serie.line.set_color((col.redF(), col.greenF(), col.blueF()))
+ plt.update()
+
+ def onRemove(self):
+ """Executed when the data serie must be removed."""
+ plt = Plot.getPlot()
+ if not plt:
+ self.updateUI()
+ return
+ # Ensure that selected serie exist
+ if self.item >= len(Plot.series()):
+ self.updateUI()
+ return
+ # Remove serie
+ Plot.removeSerie(self.item)
+ self.setList()
+ self.updateUI()
+ plt.update()
+
+ def onMdiArea(self, subWin):
+ """Executed when a new window is selected on the mdi area.
+
+ Keyword arguments:
+ subWin -- Selected window.
+ """
+ plt = Plot.getPlot()
+ if plt != subWin:
+ self.updateUI()
+
+ def updateUI(self):
+ """ Setup UI controls values if possible """
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.items = self.widget(QtGui.QListWidget, "items")
+ form.label = self.widget(QtGui.QLineEdit, "label")
+ form.isLabel = self.widget(QtGui.QCheckBox, "isLabel")
+ form.style = self.widget(QtGui.QComboBox, "lineStyle")
+ form.marker = self.widget(QtGui.QComboBox, "markers")
+ form.width = self.widget(QtGui.QDoubleSpinBox, "lineWidth")
+ form.size = self.widget(QtGui.QSpinBox, "markerSize")
+ form.color = self.widget(QtGui.QPushButton, "color")
+ form.remove = self.widget(QtGui.QPushButton, "remove")
+ plt = Plot.getPlot()
+ form.items.setEnabled(bool(plt))
+ form.label.setEnabled(bool(plt))
+ form.isLabel.setEnabled(bool(plt))
+ form.style.setEnabled(bool(plt))
+ form.marker.setEnabled(bool(plt))
+ form.width.setEnabled(bool(plt))
+ form.size.setEnabled(bool(plt))
+ form.color.setEnabled(bool(plt))
+ form.remove.setEnabled(bool(plt))
+ if not plt:
+ self.plt = plt
+ form.items.clear()
+ return
+ self.skip = True
+ # Refill list
+ if self.plt != plt or len(Plot.series()) != form.items.count():
+ self.plt = plt
+ self.setList()
+ # Ensure that have series
+ if not len(Plot.series()):
+ form.label.setEnabled(False)
+ form.isLabel.setEnabled(False)
+ form.style.setEnabled(False)
+ form.marker.setEnabled(False)
+ form.width.setEnabled(False)
+ form.size.setEnabled(False)
+ form.color.setEnabled(False)
+ form.remove.setEnabled(False)
+ return
+ # Set label
+ serie = Plot.series()[self.item]
+ if serie.name is None:
+ form.isLabel.setChecked(True)
+ form.label.setEnabled(False)
+ form.label.setText("")
+ else:
+ form.isLabel.setChecked(False)
+ form.label.setText(serie.name)
+ # Set line style and marker
+ form.style.setCurrentIndex(0)
+ linestyles = Line2D.lineStyles.keys()
+ for i in range(0, len(linestyles)):
+ style = linestyles[i]
+ if style == serie.line.get_linestyle():
+ form.style.setCurrentIndex(i)
+ form.marker.setCurrentIndex(0)
+ markers = Line2D.markers.keys()
+ for i in range(0, len(markers)):
+ marker = markers[i]
+ if marker == serie.line.get_marker():
+ form.marker.setCurrentIndex(i)
+ # Set line width and marker size
+ form.width.setValue(serie.line.get_linewidth())
+ form.size.setValue(serie.line.get_markersize())
+ # Set color
+ color = Colors.colorConverter.to_rgb(serie.line.get_color())
+ form.color.setStyleSheet("background-color: rgb({}, {}, {});".format(
+ int(color[0] * 255),
+ int(color[1] * 255),
+ int(color[2] * 255)))
+ self.skip = False
+
+ def setList(self):
+ """Setup the UI control values if it is possible."""
+ mw = self.getMainWindow()
+ form = mw.findChild(QtGui.QWidget, "TaskPanel")
+ form.items = self.widget(QtGui.QListWidget, "items")
+ form.items.clear()
+ series = Plot.series()
+ for i in range(0, len(series)):
+ serie = series[i]
+ string = 'serie ' + str(i) + ': '
+ if serie.name is None:
+ string = string + '\"No label\"'
+ else:
+ string = string + serie.name
+ form.items.addItem(string)
+ # Ensure that selected item is correct
+ if len(series) and self.item >= len(series):
+ self.item = len(series) - 1
+ form.items.setCurrentIndex(self.item)
+
def createTask():
- panel = TaskPanel()
- Gui.Control.showDialog(panel)
- if panel.setupUi():
- Gui.Control.closeDialog(panel)
- return None
- return panel
+ panel = TaskPanel()
+ Gui.Control.showDialog(panel)
+ if panel.setupUi():
+ Gui.Control.closeDialog(panel)
+ return None
+ return panel
diff --git a/src/Mod/Plot/plotSeries/__init__.py b/src/Mod/Plot/plotSeries/__init__.py
index 24058d7a93ee..6a97f58b26af 100644
--- a/src/Mod/Plot/plotSeries/__init__.py
+++ b/src/Mod/Plot/plotSeries/__init__.py
@@ -1,7 +1,7 @@
#***************************************************************************
#* *
-#* Copyright (c) 2011, 2012 *
-#* Jose Luis Cercos Pita *
+#* Copyright (c) 2011, 2012 *
+#* Jose Luis Cercos Pita *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
@@ -21,16 +21,9 @@
#* *
#***************************************************************************
-# FreeCAD modules
-import FreeCAD
-import FreeCADGui
-
-# Qt libraries
-from PyQt4 import QtGui,QtCore
-
-# Main object
import TaskPanel
+
def load():
- """ Loads the tool """
- TaskPanel.createTask()
+ """Load the tool"""
+ TaskPanel.createTask()
diff --git a/src/Mod/Plot/plotUtils/Paths.py b/src/Mod/Plot/plotUtils/Paths.py
index b03f3f64aafd..800ed4c5a6f9 100644
--- a/src/Mod/Plot/plotUtils/Paths.py
+++ b/src/Mod/Plot/plotUtils/Paths.py
@@ -1,7 +1,7 @@
#***************************************************************************
#* *
-#* Copyright (c) 2011, 2012 *
-#* Jose Luis Cercos Pita *
+#* Copyright (c) 2011, 2012 *
+#* Jose Luis Cercos Pita *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
@@ -21,11 +21,13 @@
#* *
#***************************************************************************
-import FreeCAD, FreeCADGui, os
+import FreeCAD
+import FreeCADGui
+import os
+
def modulePath():
- """returns the current Plot module path
- @return Module path"""
+ """returns the current Plot module path."""
path1 = FreeCAD.ConfigGet("AppHomePath") + "Mod/Plot"
path2 = FreeCAD.ConfigGet("UserAppData") + "Mod/Plot"
if os.path.exists(path2):
@@ -33,29 +35,14 @@ def modulePath():
else:
return path1
+
def iconsPath():
- """returns the current Plot module icons path
- @return Icons path"""
+ """returns the current Plot module icons path."""
path = modulePath() + "/resources/icons"
return path
+
def translationsPath():
- """returns the current Plot module translations path
- @return Icons path"""
+ """returns the current Plot module translations path."""
path = modulePath() + "/resources/translations"
return path
-
-def getPathFromFile(fileName):
- """ Gets the directory path from a file name
- @param fileName Name of the file
- @return Directory path.
- """
- if not fileName:
- return ''
- i = 1
- try:
- while 1:
- i = fileName.index("/", i+1)
- except ValueError:
- pass
- return fileName[0:i+1]
diff --git a/src/Mod/Plot/plotUtils/__init__.py b/src/Mod/Plot/plotUtils/__init__.py
index 00b200f140cf..70392f2ea174 100644
--- a/src/Mod/Plot/plotUtils/__init__.py
+++ b/src/Mod/Plot/plotUtils/__init__.py
@@ -1,7 +1,7 @@
#***************************************************************************
#* *
-#* Copyright (c) 2011, 2012 *
-#* Jose Luis Cercos Pita *
+#* Copyright (c) 2011, 2012 *
+#* Jose Luis Cercos Pita *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
@@ -20,6 +20,3 @@
#* USA *
#* *
#***************************************************************************
-
-# Empty file to treat the folder as a package
-