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