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