00001
00002
00003
00004
00005
00006
00007 #include "CmdMediator.h"
00008 #include "CmdSettingsSegments.h"
00009 #include "DlgSettingsSegments.h"
00010 #include "EngaugeAssert.h"
00011 #include "Logger.h"
00012 #include "MainWindow.h"
00013 #include "PointStyle.h"
00014 #include <QCheckBox>
00015 #include <QComboBox>
00016 #include <QGridLayout>
00017 #include <QGraphicsScene>
00018 #include <QLabel>
00019 #include <qmath.h>
00020 #include <QSpinBox>
00021 #include "Segment.h"
00022 #include "SegmentFactory.h"
00023 #include "ViewPreview.h"
00024
00025 const int MIN_LENGTH_MIN = 1;
00026 const int MIN_LENGTH_MAX = 10000;
00027 const int POINT_SEPARATION_MIN = 5;
00028 const int POINT_SEPARATION_MAX = 10000;
00029
00030 const int IMAGE_WIDTH = 400;
00031 const int IMAGE_HEIGHT = 300;
00032
00033 const double TWOPI = 2.0 * 3.1415926535;
00034
00035 const double BRUSH_WIDTH = 2.0;
00036
00037 DlgSettingsSegments::DlgSettingsSegments(MainWindow &mainWindow) :
00038 DlgSettingsAbstractBase (tr ("Segment Fill"),
00039 "DlgSettingsSegments",
00040 mainWindow),
00041 m_scenePreview (0),
00042 m_viewPreview (0),
00043 m_modelSegmentsBefore (0),
00044 m_modelSegmentsAfter (0),
00045 m_loading (false)
00046 {
00047 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsSegments::DlgSettingsSegments";
00048
00049 QWidget *subPanel = createSubPanel ();
00050 finishPanel (subPanel);
00051 }
00052
00053 DlgSettingsSegments::~DlgSettingsSegments()
00054 {
00055 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsSegments::~DlgSettingsSegments";
00056 }
00057
00058 void DlgSettingsSegments::clearPoints ()
00059 {
00060 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsSegments::clearPoints";
00061
00062 QList<GraphicsPoint*>::iterator itrP;
00063 for (itrP = m_points.begin(); itrP != m_points.end(); itrP++) {
00064 GraphicsPoint *point = *itrP;
00065 delete point;
00066 }
00067
00068 m_points.clear();
00069 }
00070
00071 void DlgSettingsSegments::createControls (QGridLayout *layout,
00072 int &row)
00073 {
00074 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsSegments::createControls";
00075
00076 QLabel *labelMinLength = new QLabel(tr ("Minimum length (points):"));
00077 layout->addWidget(labelMinLength, row, 1);
00078
00079 m_spinMinLength = new QSpinBox;
00080 m_spinMinLength->setRange (MIN_LENGTH_MIN, MIN_LENGTH_MAX);
00081 m_spinMinLength->setWhatsThis (tr ("Select a minimum number of points in a segment.\n\n"
00082 "Only segments with more points will be created.\n\n"
00083 "This value should be as large as possible to reduce memory usage. This value has "
00084 "a lower limit"));
00085 connect (m_spinMinLength, SIGNAL (valueChanged (const QString &)), this, SLOT (slotMinLength (const QString &)));
00086 layout->addWidget(m_spinMinLength, row++, 2);
00087
00088 QLabel *labelPointSeparation = new QLabel(tr ("Point separation (pixels):"));
00089 layout->addWidget (labelPointSeparation, row, 1);
00090
00091 m_spinPointSeparation = new QSpinBox;
00092 m_spinPointSeparation->setRange (POINT_SEPARATION_MIN, POINT_SEPARATION_MAX);
00093 m_spinPointSeparation->setWhatsThis (tr ("Select a point separation in pixels.\n\n"
00094 "Successive points added to a segment will be separated by this number of pixels. "
00095 "If Fill Corners is enabled, then additional points will be inserted at corners so some points "
00096 "will be closer.\n\n"
00097 "This value has a lower limit"));
00098 connect (m_spinPointSeparation, SIGNAL (valueChanged (const QString &)), this, SLOT (slotPointSeparation (const QString &)));
00099 layout->addWidget (m_spinPointSeparation, row++, 2);
00100
00101 QLabel *labelFillCorners = new QLabel (tr ("Fill corners:"));
00102 layout->addWidget (labelFillCorners, row, 1);
00103
00104 m_chkFillCorners = new QCheckBox;
00105 m_chkFillCorners->setWhatsThis (tr ("Fill corners.\n\n"
00106 "In addition to the points placed at regular intervals, this option causes a point to be "
00107 "placed at each corner. This option can capture important information in piecewise linear graphs, "
00108 "but gradually curving graphs may not benefit from the additional points"));
00109 connect (m_chkFillCorners, SIGNAL (stateChanged (int)), this, SLOT (slotFillCorners (int)));
00110 layout->addWidget (m_chkFillCorners, row++, 2);
00111
00112 QLabel *labelLineWidth = new QLabel(tr ("Line width:"));
00113 layout->addWidget (labelLineWidth, row, 1);
00114
00115 m_spinLineWidth = new QSpinBox;
00116 m_spinLineWidth->setWhatsThis (tr ("Select a size for the lines drawn along a segment"));
00117 m_spinLineWidth->setMinimum(1);
00118 connect (m_spinLineWidth, SIGNAL (valueChanged (int)), this, SLOT (slotLineWidth (int)));
00119 layout->addWidget (m_spinLineWidth, row++, 2);
00120
00121 QLabel *labelLineColor = new QLabel(tr ("Line color:"));
00122 layout->addWidget (labelLineColor, row, 1);
00123
00124 m_cmbLineColor = new QComboBox;
00125 m_cmbLineColor->setWhatsThis (tr ("Select a color for the lines drawn along a segment"));
00126 populateColorComboWithTransparent (*m_cmbLineColor);
00127 connect (m_cmbLineColor, SIGNAL (activated (const QString &)), this, SLOT (slotLineColor (const QString &)));
00128 layout->addWidget (m_cmbLineColor, row++, 2);
00129 }
00130
00131 void DlgSettingsSegments::createOptionalSaveDefault (QHBoxLayout * )
00132 {
00133 }
00134
00135 void DlgSettingsSegments::createPreview (QGridLayout *layout,
00136 int &row)
00137 {
00138 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsSegments::createPreview";
00139
00140 QLabel *labelPreview = new QLabel (tr ("Preview"));
00141 layout->addWidget (labelPreview, row++, 0, 1, 4);
00142
00143 m_scenePreview = new QGraphicsScene (this);
00144 m_viewPreview = new ViewPreview (m_scenePreview,
00145 ViewPreview::VIEW_ASPECT_RATIO_VARIABLE,
00146 this);
00147 m_viewPreview->setWhatsThis (tr ("Preview window shows the shortest line that can be segment filled, "
00148 "and the effects of current settings on segments and points generated by segment fill"));
00149 m_viewPreview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00150 m_viewPreview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00151 m_viewPreview->setMinimumHeight (MINIMUM_PREVIEW_HEIGHT);
00152
00153 layout->addWidget (m_viewPreview, row++, 0, 1, 4);
00154 }
00155
00156 QImage DlgSettingsSegments::createPreviewImage () const
00157 {
00158 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsSegments::createPreviewImage";
00159
00160 QImage image (IMAGE_WIDTH,
00161 IMAGE_HEIGHT,
00162 QImage::Format_RGB32);
00163 image.fill (Qt::white);
00164 QPainter painter (&image);
00165 painter.setRenderHint(QPainter::Antialiasing);
00166 painter.setPen (QPen (QBrush (Qt::black), BRUSH_WIDTH));
00167
00168 int margin = IMAGE_WIDTH / 15;
00169 int yCenter = IMAGE_HEIGHT / 2;
00170 int yHeight = IMAGE_HEIGHT / 4;
00171 int x, y, xLast, yLast;
00172 bool isFirst;
00173
00174
00175 isFirst = true;
00176 int xStart = margin, xEnd = IMAGE_WIDTH / 2 - margin;
00177 for (x = xStart; x < xEnd; x++) {
00178 double s = (double) (x - xStart) / (double) (xEnd - xStart);
00179 int y = yCenter - yHeight * qSin (TWOPI * s);
00180
00181 if (!isFirst) {
00182 painter.drawLine (xLast, yLast, x, y);
00183 }
00184 isFirst = false;
00185 xLast = x;
00186 yLast = y;
00187 }
00188
00189
00190 isFirst = true;
00191 xStart = IMAGE_WIDTH / 2 + margin, xEnd = IMAGE_WIDTH - margin;
00192 for (x = xStart; x < xEnd; x++) {
00193 double s = (double) (x - xStart) / (double) (xEnd - xStart);
00194 if (s <= 0.25) {
00195 y = yCenter - yHeight * (4.0 * s);
00196 } else if (s < 0.75) {
00197 y = yCenter - yHeight * (1.0 - 4.0 * (s - 0.25));
00198 } else {
00199 y = yCenter + yHeight * (1.0 - 4 * (s - 0.75));
00200 }
00201
00202 if (!isFirst) {
00203 painter.drawLine (xLast, yLast, x, y);
00204 }
00205 isFirst = false;
00206 xLast = x;
00207 yLast = y;
00208 }
00209
00210 return image;
00211 }
00212
00213 QWidget *DlgSettingsSegments::createSubPanel ()
00214 {
00215 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsSegments::createSubPanel";
00216
00217 QWidget *subPanel = new QWidget ();
00218 QGridLayout *layout = new QGridLayout (subPanel);
00219 subPanel->setLayout (layout);
00220
00221 layout->setColumnStretch (0, 1);
00222 layout->setColumnStretch (1, 0);
00223 layout->setColumnStretch (2, 0);
00224 layout->setColumnStretch (3, 1);
00225
00226 int row = 0;
00227 createControls(layout, row);
00228 createPreview (layout, row);
00229 QPixmap pixmap = QPixmap::fromImage (createPreviewImage());
00230 m_scenePreview->addPixmap (pixmap);
00231
00232 return subPanel;
00233 }
00234
00235 void DlgSettingsSegments::handleOk ()
00236 {
00237 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsSegments::handleOk";
00238
00239 CmdSettingsSegments *cmd = new CmdSettingsSegments (mainWindow (),
00240 cmdMediator ().document(),
00241 *m_modelSegmentsBefore,
00242 *m_modelSegmentsAfter);
00243 cmdMediator ().push (cmd);
00244
00245 hide ();
00246 }
00247
00248 void DlgSettingsSegments::load (CmdMediator &cmdMediator)
00249 {
00250 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsSegments::load";
00251
00252
00253 m_loading = true;
00254
00255 setCmdMediator (cmdMediator);
00256
00257
00258 if (m_modelSegmentsBefore != 0) {
00259 delete m_modelSegmentsBefore;
00260 }
00261 if (m_modelSegmentsAfter != 0) {
00262 delete m_modelSegmentsAfter;
00263 }
00264
00265
00266 m_modelSegmentsBefore = new DocumentModelSegments (cmdMediator.document());
00267 m_modelSegmentsAfter = new DocumentModelSegments (cmdMediator.document());
00268
00269
00270 ENGAUGE_ASSERT (MIN_LENGTH_MIN <= m_modelSegmentsAfter->minLength ());
00271 ENGAUGE_ASSERT (MIN_LENGTH_MAX >= m_modelSegmentsAfter->minLength ());
00272 ENGAUGE_ASSERT (POINT_SEPARATION_MIN <= m_modelSegmentsAfter->pointSeparation());
00273 ENGAUGE_ASSERT (POINT_SEPARATION_MAX >= m_modelSegmentsAfter->pointSeparation());
00274
00275
00276 m_spinPointSeparation->setValue (m_modelSegmentsAfter->pointSeparation());
00277 m_spinMinLength->setValue (m_modelSegmentsAfter->minLength());
00278 m_chkFillCorners->setChecked (m_modelSegmentsAfter->fillCorners ());
00279 m_spinLineWidth->setValue (m_modelSegmentsAfter->lineWidth());
00280
00281 int indexLineColor = m_cmbLineColor->findData(QVariant (m_modelSegmentsAfter->lineColor()));
00282 ENGAUGE_ASSERT (indexLineColor >= 0);
00283 m_cmbLineColor->setCurrentIndex(indexLineColor);
00284
00285
00286 m_loading = false;
00287
00288 updateControls();
00289 enableOk (false);
00290 updatePreview();
00291 }
00292
00293 void DlgSettingsSegments::slotFillCorners (int state)
00294 {
00295 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsSegments::slotFillCorner";
00296
00297 m_modelSegmentsAfter->setFillCorners(state == Qt::Checked);
00298 updateControls();
00299 updatePreview();
00300 }
00301
00302 void DlgSettingsSegments::slotLineColor (const QString &)
00303 {
00304 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsSegments::slotLineColor";
00305
00306 m_modelSegmentsAfter->setLineColor((ColorPalette) m_cmbLineColor->currentData().toInt());
00307 updateControls();
00308 updatePreview();
00309 }
00310
00311 void DlgSettingsSegments::slotLineWidth (int lineWidth)
00312 {
00313 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsSegments::slotLineWidth";
00314
00315 m_modelSegmentsAfter->setLineWidth(lineWidth);
00316 updateControls();
00317 updatePreview();
00318 }
00319
00320 void DlgSettingsSegments::slotMinLength (const QString &minLength)
00321 {
00322 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsSegments::slotMinLength";
00323
00324 m_modelSegmentsAfter->setMinLength(minLength.toDouble());
00325 updateControls();
00326 updatePreview();
00327 }
00328
00329 void DlgSettingsSegments::slotPointSeparation (const QString &pointSeparation)
00330 {
00331 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsSegments::slotPointSeparation";
00332
00333 m_modelSegmentsAfter->setPointSeparation(pointSeparation.toDouble());
00334 updateControls();
00335 updatePreview();
00336 }
00337
00338 void DlgSettingsSegments::updateControls()
00339 {
00340 enableOk (true);
00341 }
00342
00343 void DlgSettingsSegments::updatePreview()
00344 {
00345 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsSegments::updatePreview"
00346 << " loading=" << (m_loading ? "true" : "false");
00347
00348 const QString ARBITRARY_IDENTIFIER ("");
00349 const QColor COLOR (Qt::blue);
00350 const int RADIUS = 5;
00351
00352 if (!m_loading) {
00353
00354 SegmentFactory segmentFactory (*m_scenePreview,
00355 mainWindow().isGnuplot());
00356
00357 clearPoints();
00358 segmentFactory.clearSegments (m_segments);
00359
00360
00361 segmentFactory.makeSegments (createPreviewImage(),
00362 *m_modelSegmentsAfter,
00363 m_segments);
00364
00365
00366 QList<Segment*>::iterator itrS;
00367 for (itrS = m_segments.begin(); itrS != m_segments.end(); itrS++) {
00368 Segment *segment = *itrS;
00369 segment->slotHover (true);
00370 }
00371
00372
00373 PointStyle pointStyle (POINT_SHAPE_CROSS,
00374 RADIUS,
00375 BRUSH_WIDTH,
00376 COLOR_PALETTE_BLUE);
00377 QPolygonF polygon = pointStyle.polygon();
00378 QList<QPoint> points = segmentFactory.fillPoints (*m_modelSegmentsAfter,
00379 m_segments);
00380 QList<QPoint>::iterator itrP;
00381 for (itrP = points.begin(); itrP != points.end(); itrP++) {
00382 QPoint pos = *itrP;
00383 GraphicsPoint *graphicsPoint = new GraphicsPoint (*m_scenePreview,
00384 ARBITRARY_IDENTIFIER,
00385 pos,
00386 COLOR,
00387 polygon,
00388 BRUSH_WIDTH);
00389 m_points.push_back (graphicsPoint);
00390 }
00391 }
00392 }