File indexing completed on 2024-12-22 04:18:17

0001 /***************************************************************************
0002  *                                                                         *
0003  *   copyright : (C) 2007 The University of Toronto                        *
0004  *                   netterfield@astro.utoronto.ca                         *
0005  *                                                                         *
0006  *   This program is free software; you can redistribute it and/or modify  *
0007  *   it under the terms of the GNU General Public License as published by  *
0008  *   the Free Software Foundation; either version 2 of the License, or     *
0009  *   (at your option) any later version.                                   *
0010  *                                                                         *
0011  ***************************************************************************/
0012 
0013 #include "curveappearance.h"
0014 
0015 #include "curvepointsymbol.h"
0016 #include "linestyle.h"
0017 #include <QPainter>
0018 #include "dialogdefaults.h"
0019 #include <QColorDialog>
0020 
0021 #include "colorsequence.h"
0022 
0023 namespace Kst {
0024 
0025 CurveAppearance::CurveAppearance(QWidget *parent)
0026   : QWidget(parent) {
0027   setupUi(this);  
0028   populateSymbolCombos();
0029   populateLineStyleCombo();
0030 
0031   drawSampleLine();
0032 
0033   connect(_showPoints, SIGNAL(stateChanged(int)), this, SLOT(enableSettings()));
0034   connect(_showLines, SIGNAL(stateChanged(int)), this, SLOT(enableSettings()));
0035   connect(_showBars, SIGNAL(stateChanged(int)), this, SLOT(enableSettings()));
0036   connect(_showHead, SIGNAL(stateChanged(int)), this, SLOT(enableSettings()));
0037 
0038   connect(_color, SIGNAL(changed(QColor)), this, SLOT(populateSymbolCombos()));
0039   connect(_color, SIGNAL(changed(QColor)), this, SLOT(populateLineStyleCombo()));
0040   connect(_headColor, SIGNAL(changed(QColor)), this, SLOT(populateSymbolCombos()));
0041   connect(_headColor, SIGNAL(changed(QColor)), this, SLOT(populateLineStyleCombo()));
0042 
0043   connect(_color, SIGNAL(changed(QColor)), this, SLOT(drawSampleLine()));
0044   connect(_headColor, SIGNAL(changed(QColor)), this, SLOT(drawSampleLine()));
0045   connect(_barFillColor, SIGNAL(changed(QColor)), this, SLOT(drawSampleLine()));
0046   connect(_showLines, SIGNAL(clicked()), this, SLOT(drawSampleLine()));
0047   connect(_showPoints, SIGNAL(clicked()), this, SLOT(drawSampleLine()));
0048   connect(_showHead, SIGNAL(clicked()), this, SLOT(drawSampleLine()));
0049   connect(_comboPointSymbol, SIGNAL(currentIndexChanged(int)), this, SLOT(drawSampleLine()));
0050   connect(_comboLineStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(drawSampleLine()));
0051   connect(_comboHeadSymbol, SIGNAL(currentIndexChanged(int)), this, SLOT(drawSampleLine()));
0052   connect(_spinBoxLineWidth, SIGNAL(valueChanged(int)), this, SLOT(drawSampleLine()));
0053   connect(_spinBoxPointSize, SIGNAL(valueChanged(double)), this, SLOT(drawSampleLine()));
0054   connect(_showBars, SIGNAL(clicked()), this, SLOT(drawSampleLine()));
0055 
0056   connect(_color, SIGNAL(changed(QColor)), this, SIGNAL(modified()));
0057   connect(_headColor, SIGNAL(changed(QColor)), this, SIGNAL(modified()));
0058   connect(_barFillColor, SIGNAL(changed(QColor)), this, SIGNAL(modified()));
0059   connect(_showLines, SIGNAL(clicked()), this, SIGNAL(modified()));
0060   connect(_showPoints, SIGNAL(clicked()), this, SIGNAL(modified()));
0061   connect(_showHead, SIGNAL(clicked()), this, SIGNAL(modified()));
0062   connect(_comboPointDensity, SIGNAL(currentIndexChanged(int)), this, SIGNAL(modified()));
0063   connect(_comboPointSymbol, SIGNAL(currentIndexChanged(int)), this, SIGNAL(modified()));
0064   connect(_comboHeadSymbol, SIGNAL(currentIndexChanged(int)), this, SIGNAL(modified()));
0065   connect(_comboLineStyle, SIGNAL(currentIndexChanged(int)), this, SIGNAL(modified()));
0066   connect(_spinBoxLineWidth, SIGNAL(valueChanged(int)), this, SIGNAL(modified()));
0067   connect(_spinBoxPointSize, SIGNAL(valueChanged(double)), this, SIGNAL(modified()));
0068   connect(_showBars, SIGNAL(clicked()), this, SIGNAL(modified()));
0069 
0070   // Set default colors for the color selection dialog.
0071   for (int i=0; i< 6*8; i++) {
0072     // the display is a 8x6 grid, but is numbered row first, then col.
0073     // so flip it, so the colors go across
0074     int ix = i%8;
0075     int iy = i/8;
0076     int j = ix*6 + iy;
0077 
0078     if (i < ColorSequence::self().count()) {
0079       QColorDialog::setStandardColor(j, ColorSequence::self().entry(i));
0080     } else if (i == ColorSequence::self().count()) {
0081       QColorDialog::setStandardColor(j, Qt::black);
0082     } else if (i == ColorSequence::self().count() + 1) {
0083       QColorDialog::setStandardColor(j, Qt::white);
0084     } else {
0085       QColorDialog::setStandardColor(j, Qt::gray);
0086     }
0087   }
0088 }
0089 
0090 
0091 CurveAppearance::~CurveAppearance() {
0092 }
0093 
0094 
0095 void CurveAppearance::populateSymbolCombos() {
0096   populateSymbolCombo(_comboPointSymbol, color());
0097   populateSymbolCombo(_comboHeadSymbol, headColor());
0098 }
0099 
0100 
0101 void CurveAppearance::populateSymbolCombo(QComboBox *combo, QColor symbolColor) {
0102 #ifdef QT5
0103   int pixel_ratio = combo->devicePixelRatio();
0104 #else
0105   int pixel_ratio = 1;
0106 #endif
0107 
0108   if (symbolColor == Qt::transparent) {
0109     symbolColor = Qt::black;
0110   }
0111   int h = fontMetrics().lineSpacing();
0112 
0113   combo->setIconSize(QSize(4*h, h));
0114 
0115   // fill the point type dialog with point types
0116   QPixmap ppix( 4*h*pixel_ratio, h*pixel_ratio );
0117 
0118 #ifdef QT5
0119   ppix.setDevicePixelRatio(pixel_ratio);
0120 #endif
0121 
0122   int pix_w = ppix.width()/pixel_ratio;
0123   int pix_h = ppix.height()/pixel_ratio;
0124 
0125 
0126   QPainter pp( &ppix );
0127 
0128   int currentItem = combo->currentIndex();
0129   combo->clear();
0130   QPen pen(symbolColor);
0131   pen.setWidthF(h/18.0);
0132   pp.setPen(pen);
0133 
0134   for (int ptype = 0; ptype < KSTPOINT_MAXTYPE; ptype++) {
0135     pp.fillRect(pp.window(), QColor("white"));
0136     CurvePointSymbol::draw(ptype, &pp, pix_w/2, pix_h/2, h/4);
0137     combo->addItem(QIcon(ppix), QString());
0138   }
0139 
0140   if (currentItem > 0) {
0141     combo->setCurrentIndex( currentItem );
0142   }
0143 }
0144 
0145 
0146 void CurveAppearance::enableSettings() {
0147   bool enable;
0148 
0149   // Use an intermediate boolean to avoid having to use setEnabled(true) and setEnabled(false)
0150   enable = showLines() || showBars();
0151 
0152   // Line appearance options common to lines and bars
0153   _comboLineStyle->setEnabled(enable);
0154 
0155   // Option specific to bars
0156   enable = showBars();
0157   _barFillColor->setEnabled(enable);
0158 
0159   // Now point options
0160   enable = showPoints();
0161   _comboPointSymbol->setEnabled(enable);
0162   _spinBoxPointSize->setEnabled(enable);
0163   _textLabelPointSize->setEnabled(enable);
0164 
0165   // and disable widget if not using lines, as using only points and not plotting all of them sounds weird
0166   enable = enable && showLines();
0167   _comboPointDensity->setEnabled(enable);
0168   _textLabelPointDensity->setEnabled(enable);
0169 
0170   // Heads
0171   enable = showHead();
0172   _comboHeadSymbol->setEnabled(enable);
0173   _headColor->setEnabled(enable);
0174 
0175 }
0176 
0177 
0178 bool CurveAppearance::showLines() const {
0179   return _showLines->checkState() == Qt::Checked;
0180 
0181 }
0182 
0183 
0184 bool CurveAppearance::showLinesDirty() const {
0185   return _showLines->checkState() != Qt::PartiallyChecked;
0186 }
0187 
0188 
0189 void CurveAppearance::setShowLines(const bool showLines) {
0190   _showLines->setChecked(showLines);
0191   _showLines->setTristate(false);
0192   enableSettings();
0193   drawSampleLine();
0194 }
0195 
0196 
0197 bool CurveAppearance::showPoints() const {
0198   return _showPoints->checkState() == Qt::Checked;
0199 }
0200 
0201 
0202 bool CurveAppearance::showPointsDirty() const {
0203   return _showPoints->checkState() != Qt::PartiallyChecked;
0204 }
0205 
0206 
0207 void CurveAppearance::setShowPoints(const bool showPoints) {
0208   _showPoints->setChecked(showPoints);
0209   _showPoints->setTristate(false);
0210   enableSettings();
0211   drawSampleLine();
0212 }
0213 
0214 
0215 bool CurveAppearance::showHead() const {
0216   return _showHead->checkState() == Qt::Checked;
0217 }
0218 
0219 
0220 bool CurveAppearance::showHeadDirty() const {
0221   return _showHead->checkState() != Qt::PartiallyChecked;
0222 }
0223 
0224 
0225 void CurveAppearance::setShowHead(const bool showHead) {
0226   _showHead->setChecked(showHead);
0227   _showHead->setTristate(false);
0228   enableSettings();
0229   drawSampleLine();
0230 }
0231 
0232 
0233 bool CurveAppearance::showBars() const {
0234   return _showBars->checkState() == Qt::Checked;
0235 }
0236 
0237 
0238 bool CurveAppearance::showBarsDirty() const {
0239   return _showBars->checkState() != Qt::PartiallyChecked;
0240 }
0241 
0242 
0243 void CurveAppearance::setShowBars(const bool showBars) {
0244   _showBars->setChecked(showBars);
0245   _showBars->setTristate(false);
0246   enableSettings();
0247   drawSampleLine();
0248 }
0249 
0250 
0251 QColor CurveAppearance::color() const {
0252   return _color->color();
0253 }
0254 
0255 
0256 bool CurveAppearance::colorDirty() const {
0257   return _color->colorDirty();
0258 }
0259 
0260 
0261 void CurveAppearance::setColor(const QColor & c) {
0262   _color->setColor(c);
0263   enableSettings();
0264   drawSampleLine();
0265 }
0266 
0267 QColor CurveAppearance::headColor() const {
0268   return _headColor->color();
0269 }
0270 
0271 
0272 bool CurveAppearance::headColorDirty() const {
0273   return _headColor->colorDirty();
0274 }
0275 
0276 
0277 void CurveAppearance::setHeadColor(const QColor & c) {
0278   _headColor->setColor(c);
0279   enableSettings();
0280   drawSampleLine();
0281 }
0282 
0283 
0284 QColor CurveAppearance::barFillColor() const {
0285   return _barFillColor->color();
0286 }
0287 
0288 
0289 bool CurveAppearance::barFillColorDirty() const {
0290   return _barFillColor->colorDirty();
0291 }
0292 
0293 
0294 void CurveAppearance::setBarFillColor(const QColor & c) {
0295   _barFillColor->setColor(c);
0296   enableSettings();
0297   drawSampleLine();
0298 }
0299 
0300 
0301 
0302 int CurveAppearance::pointType() const {
0303   return _comboPointSymbol->currentIndex();
0304 }
0305 
0306 
0307 bool CurveAppearance::pointTypeDirty() const {
0308   return _comboPointSymbol->currentIndex() != -1;
0309 }
0310 
0311 
0312 void CurveAppearance::setPointType(const int pointType) {
0313   _comboPointSymbol->setCurrentIndex(pointType);
0314   enableSettings();
0315   drawSampleLine();
0316 }
0317 
0318 int CurveAppearance::headType() const {
0319   return _comboHeadSymbol->currentIndex();
0320 }
0321 
0322 
0323 bool CurveAppearance::headTypeDirty() const {
0324   return _comboHeadSymbol->currentIndex() != -1;
0325 }
0326 
0327 
0328 void CurveAppearance::setHeadType(const int pointType) {
0329   _comboHeadSymbol->setCurrentIndex(pointType);
0330   enableSettings();
0331   drawSampleLine();
0332 }
0333 
0334 
0335 int CurveAppearance::lineStyle() const {
0336   return _comboLineStyle->currentIndex();
0337 }
0338 
0339 
0340 bool CurveAppearance::lineStyleDirty() const {
0341   return _comboLineStyle->currentIndex() != -1;
0342 }
0343 
0344 
0345 void CurveAppearance::setLineStyle(int lineStyle) {
0346   if (lineStyle < 0 || lineStyle >= (int)LINESTYLE_MAXTYPE) {
0347     lineStyle = 0;
0348   }
0349   _comboLineStyle->setCurrentIndex(lineStyle);
0350   enableSettings();
0351   drawSampleLine();
0352 }
0353 
0354 
0355 int CurveAppearance::pointDensity() const {
0356   return _comboPointDensity->currentIndex();
0357 }
0358 
0359 
0360 bool CurveAppearance::pointDensityDirty() const {
0361   return _comboPointDensity->currentIndex() != -1;
0362 }
0363 
0364 
0365 void CurveAppearance::setPointDensity(int pointDensity) {
0366   if (pointDensity < 0 || pointDensity >= POINTDENSITY_MAXTYPE) {
0367     pointDensity = 0;
0368   }
0369   _comboPointDensity->setCurrentIndex(pointDensity);
0370   enableSettings();
0371   drawSampleLine();
0372 }
0373 
0374 
0375 int CurveAppearance::lineWidth() const {
0376   if (_spinBoxLineWidth->text() == " ") {
0377     return 0;
0378   } else {
0379     return _spinBoxLineWidth->value();
0380   }
0381 }
0382 
0383 
0384 bool CurveAppearance::lineWidthDirty() const {
0385   return !_spinBoxLineWidth->text().isEmpty();
0386 }
0387 
0388 
0389 void CurveAppearance::setLineWidth(const int lineWidth) {
0390   _spinBoxLineWidth->setValue(lineWidth);
0391   enableSettings();
0392   drawSampleLine();
0393 }
0394 
0395 
0396 double CurveAppearance::pointSize() const {
0397   if (_spinBoxPointSize->text() == " ") {
0398     return CURVE_DEFAULT_POINT_SIZE;
0399   } else {
0400     return _spinBoxPointSize->value();
0401   }
0402 }
0403 
0404 
0405 bool CurveAppearance::pointSizeDirty() const {
0406   return !_spinBoxPointSize->text().isEmpty();
0407 }
0408 
0409 
0410 void CurveAppearance::setPointSize(double pointSize) {
0411   if (pointSize<0.1) {
0412     pointSize = CURVE_DEFAULT_POINT_SIZE;
0413   }
0414   _spinBoxPointSize->setValue(pointSize);
0415   enableSettings();
0416   drawSampleLine();
0417 }
0418 
0419 
0420 void CurveAppearance::clearValues() {
0421   _color->clearSelection();
0422   _headColor->clearSelection();
0423   _barFillColor->clearSelection();
0424   _spinBoxLineWidth->clear();
0425   _spinBoxPointSize->clear();
0426   _comboHeadSymbol->setCurrentIndex(-1);
0427   _comboPointSymbol->setCurrentIndex(-1);
0428   _comboPointDensity->setCurrentIndex(-1);
0429   _comboLineStyle->setCurrentIndex(-1);
0430   _showPoints->setCheckState(Qt::PartiallyChecked);
0431   _showLines->setCheckState(Qt::PartiallyChecked);
0432   _showBars->setCheckState(Qt::PartiallyChecked);
0433   drawSampleLine();
0434 }
0435 
0436 
0437 void CurveAppearance::populateLineStyleCombo() {
0438   int h = fontMetrics().lineSpacing();
0439 
0440   _comboLineStyle->setIconSize(QSize(4*h, h));
0441 
0442   // fill the point type dialog with point types
0443   QPixmap ppix(4*h, h);
0444   QPainter pp(&ppix);
0445 
0446   QColor lineColor(color());
0447   if (lineColor == Qt::transparent) {
0448     lineColor = Qt::black;
0449   }
0450 
0451 
0452   QPen pen(lineColor, 1);
0453   pen.setWidthF(h/18.0);
0454 
0455   int currentItem = _comboLineStyle->currentIndex();
0456   _comboLineStyle->clear();
0457 
0458   for (int style = 0; style < (int)LINESTYLE_MAXTYPE; style++) {
0459     pen.setStyle(LineStyle[style]);
0460     pp.setPen(pen);
0461     pp.fillRect( pp.window(), QColor("white"));
0462     pp.drawLine(1,ppix.height()/2,ppix.width()-1, ppix.height()/2);
0463     _comboLineStyle->addItem(QIcon(ppix), QString());
0464   }
0465 
0466   if (currentItem > 0) {
0467     _comboLineStyle->setCurrentIndex( currentItem );
0468   }
0469 }
0470 
0471 
0472 void CurveAppearance::drawSampleLine() {
0473   // In some OSs, HiDPI is handled by setting the device pixel ratio so that
0474   // logical pixels are not physical pixels.  However, not all Qt functions
0475   // seem to play well in this universe, requiring some... entertainment.
0476 
0477 #ifdef QT5
0478   int pixel_ratio = _label->devicePixelRatio();
0479 #else
0480   int pixel_ratio = 1;
0481 #endif
0482 
0483   int h = fontMetrics().lineSpacing()*3/2;
0484   _label->resize(h*5, h);
0485   QPixmap pix(_label->contentsRect().width()*pixel_ratio,
0486               _label->contentsRect().height()*pixel_ratio);
0487 
0488 #ifdef QT5
0489   pix.setDevicePixelRatio(pixel_ratio);
0490 #endif
0491 
0492   int pix_w = pix.width()/pixel_ratio;
0493   int pix_h = pix.height()/pixel_ratio;
0494 
0495 
0496   QPainter p(&pix);
0497 
0498   int line_width = lineWidth()*fontMetrics().lineSpacing()/18;
0499 
0500   QPen pen(color(),line_width,LineStyle[lineStyle()]);
0501 
0502   p.fillRect(p.window(), QColor("white"));
0503 
0504 
0505   if (showBars()) {
0506     QRect rectBar((pix_w-pix_h)/2,
0507                   pix_h/2,
0508                   pix_h,
0509                   (pix_h/2)+1);
0510 
0511 
0512     p.fillRect(rectBar,QBrush(QColor(barFillColor())));
0513     p.setPen(QPen(QColor(color()),line_width, LineStyle[lineStyle()]));
0514     p.drawRect(rectBar);
0515   }
0516 
0517 #ifdef Q_OS_WIN32
0518   // Note:  This modification was made in response to an apparent bug in Qt 4.4.0 in which any
0519   // painting done with a cosmetic pen resulted in a crash.
0520 
0521   // When this is no longer required similar code should also be removed in ViewItemDialog.cpp and
0522   // curve.cpp - setLineWidth().
0523   if (pen.isCosmetic()) {
0524     pen.setWidth(1);
0525   }
0526 #endif
0527   p.setPen(pen);
0528   if (showLines()) {
0529     if (showHead()) {
0530       p.drawLine(1, pix_h/2, pix_w-10, pix_h/2);
0531     } else {
0532       p.drawLine(1, pix_h/2, pix_w-1, pix_h/2);
0533     }
0534   }
0535 
0536   h = fontMetrics().lineSpacing() * pointSize()*12/font().pointSizeF()/56;
0537 
0538   if (showPoints()) {
0539     pen.setStyle(Qt::SolidLine);
0540     p.setPen(pen);
0541     CurvePointSymbol::draw(pointType(), &p, pix_w/2, pix_h/2, h);
0542   }
0543 
0544   if (showHead()) {
0545     pen.setStyle(Qt::SolidLine);
0546     pen.setColor(headColor());
0547     p.setPen(pen);
0548     CurvePointSymbol::draw(headType(), &p, pix_w-10, pix_h/2, h);
0549   }
0550   _label->setPixmap(pix);
0551 }
0552 
0553 // store the current state of the widget as the default 
0554 void CurveAppearance::setWidgetDefaults(bool nextColor) {
0555   if (nextColor) {
0556     ColorSequence::self().incIndex();
0557   }
0558   dialogDefaults().setValue("curves/showPoints",showPoints());
0559   dialogDefaults().setValue("curves/showLines", showLines());
0560   dialogDefaults().setValue("curves/showBars",showBars());
0561   dialogDefaults().setValue("curves/lineWidth",lineWidth());
0562   dialogDefaults().setValue("curves/pointSize",pointSize());
0563   dialogDefaults().setValue("curves/lineStyle",lineStyle());
0564   dialogDefaults().setValue("curves/pointType", pointType());
0565   dialogDefaults().setValue("curves/headType", headType());
0566   dialogDefaults().setValue("curves/pointDensity", pointDensity());
0567   dialogDefaults().setValue("curves/showHead", showHead());
0568 }
0569 
0570 // set the widget to the stored default values
0571 void CurveAppearance::loadWidgetDefaults() {
0572   int i_color = ColorSequence::self().index();
0573   setColor(ColorSequence::self().entry(i_color));
0574   setHeadColor(ColorSequence::self().entry(i_color+1));
0575   setBarFillColor(ColorSequence::self().entry(i_color+2));
0576 
0577   setShowPoints(dialogDefaults().value("curves/showPoints",false).toBool());
0578   setShowLines(dialogDefaults().value("curves/showLines",true).toBool());
0579   setShowBars(dialogDefaults().value("curves/showBars",false).toBool());
0580   setShowHead(dialogDefaults().value("curves/showHead",false).toBool());
0581   setLineWidth(dialogDefaults().value("curves/lineWidth",0).toInt());
0582   setPointSize(dialogDefaults().value("curves/pointSize",0).toInt());
0583   setLineStyle(dialogDefaults().value("curves/lineStyle",0).toInt());
0584   setPointType(dialogDefaults().value("curves/pointType",0).toInt());
0585   setHeadType(dialogDefaults().value("curves/headType",0).toInt());
0586   setPointDensity(dialogDefaults().value("curves/pointDensity",0).toInt());
0587 }
0588 
0589 }
0590 // vim: ts=2 sw=2 et