/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2016, 2017, 2018 Teunis van Beelen * * Email: teuniz@gmail.com * *************************************************************************** * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * *************************************************************************** */ #include "tdial.h" #include TDial::TDial(QWidget *w_parent) : QWidget(w_parent) { fg_color = QColor(100, 100, 100); bg_color = Qt::lightGray; notch_visible = false; wrap = false; dmin = 0; dmax = 2; step = 1; slider_down = false; dval = 1; dval_old = 1; enabled = true; mouse_grad_old=180; dial_grad = 180; degr_per_step = 1; } void TDial::paintEvent(QPaintEvent *) { int w, h, r0, hor_a, hor_b, vert_a, vert_b, gr; double r1, r2, r3, r4, dtmp; QPainter p(this); #if QT_VERSION >= 0x050000 p.setRenderHint(QPainter::Qt4CompatiblePainting, true); #endif p.save(); w = width(); h = height(); r0 = w; if(r0 > h) r0 = h; r0 /= 2; p.setRenderHint(QPainter::Antialiasing); if(enabled == true) { QRadialGradient gradient((w / 2) - (r0 * 0.5), (h / 2) - (r0 * 0.5), r0); gradient.setColorAt(0.001, QColor(250, 250, 250)); gradient.setColorAt(0.9, QColor(228, 228, 228)); gradient.setColorAt(1, QColor(215, 215, 215)); p.setBrush(gradient); draw_fill_circ(w / 2, h / 2, r0 * 0.8, &p); p.setPen(fg_color); } else { p.setPen(fg_color); draw_circ(w / 2, h / 2, r0 * 0.8, &p); } if(notch_visible == true) { r1 = r0; r2 = r0 * 0.85; r3 = r0 * 0.98; r4 = r0 * 0.9; if(r0 < 30) { step = 20; } else { step = 12; } for(gr=0; gr<360; gr+=step) { if(wrap == false) { if((gr > 240) && (gr < 300)) continue; } if(gr % 60) { vert_a = r3 * sin(gr * M_PI / 180.0); hor_a = r3 * cos(gr * M_PI / 180.0); vert_b = r4 * sin(gr * M_PI / 180.0); hor_b = r4 * cos(gr * M_PI / 180.0); } else { vert_a = r1 * sin(gr * M_PI / 180.0); hor_a = r1 * cos(gr * M_PI / 180.0); vert_b = r2 * sin(gr * M_PI / 180.0); hor_b = r2 * cos(gr * M_PI / 180.0); } p.drawLine((w / 2) - hor_b, (h / 2) - vert_b, (w / 2) - hor_a, (h / 2) - vert_a); } } dtmp = dial_grad - 90; if(dtmp < 0) dtmp += 360; vert_a = r0 * 0.55 * sin(dtmp * M_PI / 180.0); hor_a = r0 * 0.55 * cos(dtmp * M_PI / 180.0); if(enabled == true) { p.setBrush(QBrush(QColor(210, 210, 210))); } else { p.setBrush(QBrush(QColor(220, 220, 220))); } draw_fill_circ(w / 2 - hor_a, h / 2 - vert_a, r0 * 0.15, &p); p.restore(); } void TDial::mousePressEvent(QMouseEvent *press_event) { if(press_event->button()==Qt::LeftButton) { slider_down = true; setMouseTracking(true); mouse_grad_old = polar_to_degr(press_event->x() - (width() / 2), press_event->y() - (height() / 2)); } press_event->accept(); } void TDial::mouseReleaseEvent(QMouseEvent *release_event) { if(release_event->button()==Qt::LeftButton) { setMouseTracking(false); slider_down = false; emit sliderReleased(); } release_event->accept(); } void TDial::mouseMoveEvent(QMouseEvent *move_event) { double gr_new, gr_diff; if(slider_down == false) return; gr_new = polar_to_degr(move_event->x() - (width() / 2), move_event->y() - (height() / 2)); gr_diff = gr_new - mouse_grad_old; mouse_grad_old = gr_new; dial_grad += gr_diff; process_rotation(); move_event->accept(); } bool TDial::isSliderDown(void) { return slider_down; } void TDial::setWrapping(bool wr) { wrap = wr; update(); } void TDial::setNotchesVisible(bool vis) { notch_visible = vis; update(); } void TDial::setMaximum(int m) { dmax = m; if(dmax < 2) dmax = 2; if(dmin >= dmax) dmin = dmax - 1; if(dmin < 0) dmin = 0; if(wrap == true) { degr_per_step = 360.0 / ((double)(dmax - dmin) / (double)step); } else { degr_per_step = 300.0 / ((double)(dmax - dmin) / (double)step); } dval = (dmax + dmin) / 2; dval_old = dval; update(); } void TDial::setMinimum(int m) { dmin = m; if(dmin >= dmax) dmax = dmin + 1; if(dmax < 2) dmax = 2; if(dmin >= dmax) dmin = dmax - 1; if(dmin < 0) dmin = 0; if(wrap == true) { degr_per_step = 360.0 / ((double)(dmax - dmin) / (double)step); } else { degr_per_step = 300.0 / ((double)(dmax - dmin) / (double)step); } dval = (dmax + dmin) / 2; dval_old = dval; update(); } void TDial::setValue(int v) { dval = v; if(dval > dmax) dval = dmax; if(dval < dmin) dval = dmin; if(wrap == true) { dial_grad = ((double)(dval - dmin) / (double)(dmax - dmin)) * 360.0; } else { dial_grad = (((double)(dval - dmin) / (double)(dmax - dmin)) * 300.0) + 30.0; } dval_old = dval; update(); } void TDial::setSliderPosition(int v) { dval = v; if(dval > dmax) dval = dmax; if(dval < dmin) dval = dmin; if(wrap == true) { dial_grad = ((double)(dval - dmin) / (double)(dmax - dmin)) * 360.0; } else { dial_grad = (((double)(dval - dmin) / (double)(dmax - dmin)) * 300.0) + 30.0; } dval_old = dval; update(); } int TDial::value(void) { return dval; } void TDial::setSingleStep(int s) { step = s; if(step > dmax) step = dmax; if(step < 1) step = 1; if(wrap == true) { degr_per_step = 360.0 / ((double)(dmax - dmin) / (double)step); } else { degr_per_step = 300.0 / ((double)(dmax - dmin) / (double)step); } update(); } void TDial::set_fg_color(QColor new_color) { fg_color = new_color; update(); } void TDial::set_bg_color(QColor new_color) { bg_color = new_color; update(); } QColor TDial::get_fg_color(void) { return(fg_color); } QColor TDial::get_bg_color(void) { return(bg_color); } void TDial::draw_circ(int px, int py, int r, QPainter *p) { p->drawArc(px - r, py - r, r * 2, r * 2, 0, 5760); } void TDial::draw_fill_circ(int px, int py, int r, QPainter *p) { p->drawEllipse(px - r, py - r, r * 2, r * 2); } void TDial::setEnabled(bool enab) { enabled = enab; update(); } double TDial::polar_to_degr(double px, double py) { int quad=0; double gr; if(px < 0) { quad += 2; px *= -1; } if(py < 0) { quad += 1; py *= -1; } if(px < 0.01) px = 0.01; if(py < 0.01) py = 0.01; gr = atan(py / px) * 180.0 / M_PI; switch(quad) { case 0: gr += 270; break; case 1: gr = 270 - gr; break; case 2: gr = 90 - gr; break; case 3: gr += 90; break; } return gr; } void TDial::wheelEvent(QWheelEvent *wheel_event) { dial_grad += (wheel_event->delta() / 8); process_rotation(); wheel_event->accept(); } void TDial::process_rotation(void) { if(dial_grad > 360) dial_grad -= 360; if(dial_grad < 0) dial_grad += 360; if(wrap == false) { if(dial_grad > 330) { dial_grad = 330; } else if(dial_grad < 30) { dial_grad = 30; } } if(wrap == false) { dval = (dial_grad - 30) * ((double)(dmax - dmin) / 300.0); } else { dval = dial_grad * ((double)(dmax - dmin) / 360.0); } if(dval == dval_old) return; dval_old = dval; emit valueChanged(dval); update(); }