annotate widgets/LevelPanWidget.cpp @ 1496:d09345e578a7

Separate out handling of alignment progress bar from the layer progress bars and fix tendency to have them hanging around even when alignment has completed
author Chris Cannam
date Wed, 14 Aug 2019 10:58:24 +0100
parents 5af5c611f4cb
children
rev   line source
Chris@923 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@923 2
Chris@923 3 /*
Chris@923 4 Sonic Visualiser
Chris@923 5 An audio file viewer and annotation editor.
Chris@923 6 Centre for Digital Music, Queen Mary, University of London.
Chris@923 7
Chris@923 8 This program is free software; you can redistribute it and/or
Chris@923 9 modify it under the terms of the GNU General Public License as
Chris@923 10 published by the Free Software Foundation; either version 2 of the
Chris@923 11 License, or (at your option) any later version. See the file
Chris@923 12 COPYING included with this distribution for more information.
Chris@923 13 */
Chris@923 14
Chris@923 15 #include "LevelPanWidget.h"
Chris@923 16
Chris@923 17 #include <QPainter>
Chris@923 18 #include <QMouseEvent>
Chris@923 19 #include <QWheelEvent>
Chris@923 20
Chris@923 21 #include "layer/ColourMapper.h"
Chris@925 22 #include "base/AudioLevel.h"
Chris@923 23
Chris@1176 24 #include "WidgetScale.h"
Chris@1176 25
Chris@923 26 #include <iostream>
Chris@926 27 #include <cmath>
Chris@940 28 #include <cassert>
Chris@923 29
Chris@923 30 using std::cerr;
Chris@923 31 using std::endl;
Chris@923 32
Chris@1301 33 /**
Chris@1301 34 * Gain and pan scales:
Chris@1301 35 *
Chris@1301 36 * Gain: we have 5 circles vertically in the display, each of which
Chris@1301 37 * has half-circle and full-circle versions, and we also have "no
Chris@1301 38 * circles", so there are in total 11 distinct levels, which we refer
Chris@1301 39 * to as "notches" and number 0-10. (We use "notch" because "level" is
Chris@1301 40 * used by the external API to refer to audio gain.)
Chris@1301 41 *
Chris@1301 42 * i.e. the levels are represented by these (schematic, rotated to
Chris@1301 43 * horizontal) displays:
Chris@1301 44 *
Chris@1301 45 * 0 X
Chris@1301 46 * 1 [
Chris@1301 47 * 2 []
Chris@1301 48 * 3 [][
Chris@1301 49 * ...
Chris@1301 50 * 9 [][][][][
Chris@1301 51 * 10 [][][][][]
Chris@1301 52 *
Chris@1301 53 * If we have mute enabled, then we map the range 0-10 to gain using
Chris@1301 54 * AudioLevel::fader_to_* with the ShortFader type, which treats fader
Chris@1301 55 * 0 as muted. If mute is disabled, then we map the range 1-10.
Chris@1301 56 *
Chris@1301 57 * We can also disable half-circles, which leaves the range unchanged
Chris@1301 58 * but limits the notches to even values.
Chris@1301 59 *
Chris@1301 60 * Pan: we have 5 columns with no finer resolution, so we only have 2
Chris@1301 61 * possible pan values on each side of centre.
Chris@1301 62 */
Chris@1301 63
Chris@923 64 static const int maxPan = 2; // range is -maxPan to maxPan
Chris@923 65
Chris@923 66 LevelPanWidget::LevelPanWidget(QWidget *parent) :
Chris@923 67 QWidget(parent),
Chris@1301 68 m_minNotch(0),
Chris@1301 69 m_maxNotch(10),
Chris@1301 70 m_notch(m_maxNotch),
Chris@923 71 m_pan(0),
Chris@1177 72 m_monitorLeft(-1),
Chris@1177 73 m_monitorRight(-1),
Chris@940 74 m_editable(true),
Chris@1249 75 m_editing(false),
Chris@1301 76 m_includeMute(true),
Chris@1303 77 m_includeHalfSteps(true)
Chris@923 78 {
Chris@1191 79 setToolTip(tr("Drag vertically to adjust level, horizontally to adjust pan"));
Chris@1201 80 setLevel(1.0);
Chris@1201 81 setPan(0.0);
Chris@923 82 }
Chris@923 83
Chris@923 84 LevelPanWidget::~LevelPanWidget()
Chris@923 85 {
Chris@923 86 }
Chris@923 87
Chris@1249 88 void
Chris@1249 89 LevelPanWidget::setToDefault()
Chris@1249 90 {
Chris@1249 91 setLevel(1.0);
Chris@1249 92 setPan(0.0);
Chris@1250 93 emitLevelChanged();
Chris@1250 94 emitPanChanged();
Chris@1249 95 }
Chris@1249 96
Chris@929 97 QSize
Chris@929 98 LevelPanWidget::sizeHint() const
Chris@929 99 {
Chris@1176 100 return WidgetScale::scaleQSize(QSize(40, 40));
Chris@929 101 }
Chris@929 102
Chris@1301 103 int
Chris@1301 104 LevelPanWidget::clampNotch(int notch) const
Chris@940 105 {
Chris@1301 106 if (notch < m_minNotch) notch = m_minNotch;
Chris@1301 107 if (notch > m_maxNotch) notch = m_maxNotch;
Chris@1301 108 if (!m_includeHalfSteps) {
Chris@1301 109 notch = (notch / 2) * 2;
Chris@1301 110 }
Chris@1301 111 return notch;
Chris@940 112 }
Chris@940 113
Chris@1177 114 int
Chris@1302 115 LevelPanWidget::clampPan(int pan) const
Chris@1302 116 {
Chris@1302 117 if (pan < -maxPan) pan = -maxPan;
Chris@1302 118 if (pan > maxPan) pan = maxPan;
Chris@1302 119 return pan;
Chris@1302 120 }
Chris@1302 121
Chris@1302 122 int
Chris@1301 123 LevelPanWidget::audioLevelToNotch(float audioLevel) const
Chris@1177 124 {
Chris@1301 125 int notch = AudioLevel::multiplier_to_fader
Chris@1301 126 (audioLevel, m_maxNotch, AudioLevel::ShortFader);
Chris@1301 127 return clampNotch(notch);
Chris@1177 128 }
Chris@1177 129
Chris@1177 130 float
Chris@1301 131 LevelPanWidget::notchToAudioLevel(int notch) const
Chris@1177 132 {
Chris@1301 133 return float(AudioLevel::fader_to_multiplier
Chris@1301 134 (notch, m_maxNotch, AudioLevel::ShortFader));
Chris@1177 135 }
Chris@1177 136
Chris@923 137 void
Chris@1301 138 LevelPanWidget::setLevel(float level)
Chris@923 139 {
Chris@1301 140 int notch = audioLevelToNotch(level);
Chris@1301 141 if (notch != m_notch) {
Chris@1301 142 m_notch = notch;
Chris@1266 143 float convertsTo = getLevel();
Chris@1301 144 if (fabsf(convertsTo - level) > 1e-5) {
Chris@1266 145 emitLevelChanged();
Chris@1266 146 }
Chris@1266 147 update();
Chris@925 148 }
Chris@923 149 }
Chris@923 150
Chris@940 151 float
Chris@940 152 LevelPanWidget::getLevel() const
Chris@940 153 {
Chris@1301 154 return notchToAudioLevel(m_notch);
Chris@1177 155 }
Chris@1177 156
Chris@1177 157 int
Chris@1301 158 LevelPanWidget::audioPanToPan(float audioPan) const
Chris@1177 159 {
Chris@1177 160 int pan = int(round(audioPan * maxPan));
Chris@1302 161 pan = clampPan(pan);
Chris@1177 162 return pan;
Chris@1177 163 }
Chris@1177 164
Chris@1177 165 float
Chris@1301 166 LevelPanWidget::panToAudioPan(int pan) const
Chris@1177 167 {
Chris@1177 168 return float(pan) / float(maxPan);
Chris@1177 169 }
Chris@1177 170
Chris@1177 171 void
Chris@1177 172 LevelPanWidget::setPan(float fpan)
Chris@1177 173 {
Chris@1177 174 int pan = audioPanToPan(fpan);
Chris@1177 175 if (pan != m_pan) {
Chris@1177 176 m_pan = pan;
Chris@1177 177 update();
Chris@940 178 }
Chris@940 179 }
Chris@940 180
Chris@1177 181 float
Chris@1177 182 LevelPanWidget::getPan() const
Chris@1177 183 {
Chris@1177 184 return panToAudioPan(m_pan);
Chris@1177 185 }
Chris@1177 186
Chris@923 187 void
Chris@1177 188 LevelPanWidget::setMonitoringLevels(float left, float right)
Chris@923 189 {
Chris@1177 190 m_monitorLeft = left;
Chris@1177 191 m_monitorRight = right;
Chris@923 192 update();
Chris@923 193 }
Chris@923 194
Chris@940 195 bool
Chris@940 196 LevelPanWidget::isEditable() const
Chris@940 197 {
Chris@940 198 return m_editable;
Chris@940 199 }
Chris@940 200
Chris@940 201 bool
Chris@940 202 LevelPanWidget::includesMute() const
Chris@940 203 {
Chris@940 204 return m_includeMute;
Chris@940 205 }
Chris@940 206
Chris@923 207 void
Chris@923 208 LevelPanWidget::setEditable(bool editable)
Chris@923 209 {
Chris@923 210 m_editable = editable;
Chris@923 211 update();
Chris@923 212 }
Chris@923 213
Chris@940 214 void
Chris@940 215 LevelPanWidget::setIncludeMute(bool include)
Chris@923 216 {
Chris@940 217 m_includeMute = include;
Chris@1301 218 if (m_includeMute) {
Chris@1301 219 m_minNotch = 0;
Chris@1301 220 } else {
Chris@1301 221 m_minNotch = 1;
Chris@1301 222 }
Chris@940 223 emitLevelChanged();
Chris@940 224 update();
Chris@923 225 }
Chris@923 226
Chris@923 227 void
Chris@923 228 LevelPanWidget::emitLevelChanged()
Chris@923 229 {
Chris@923 230 emit levelChanged(getLevel());
Chris@923 231 }
Chris@923 232
Chris@923 233 void
Chris@923 234 LevelPanWidget::emitPanChanged()
Chris@923 235 {
Chris@923 236 emit panChanged(getPan());
Chris@923 237 }
Chris@923 238
Chris@923 239 void
Chris@923 240 LevelPanWidget::mousePressEvent(QMouseEvent *e)
Chris@923 241 {
Chris@1249 242 if (e->button() == Qt::MidButton ||
Chris@1249 243 ((e->button() == Qt::LeftButton) &&
Chris@1249 244 (e->modifiers() & Qt::ControlModifier))) {
Chris@1249 245 setToDefault();
Chris@1249 246 } else if (e->button() == Qt::LeftButton) {
Chris@1249 247 m_editing = true;
Chris@1249 248 mouseMoveEvent(e);
Chris@1249 249 }
Chris@1249 250 }
Chris@1249 251
Chris@1249 252 void
Chris@1249 253 LevelPanWidget::mouseReleaseEvent(QMouseEvent *e)
Chris@1249 254 {
Chris@923 255 mouseMoveEvent(e);
Chris@1249 256 m_editing = false;
Chris@923 257 }
Chris@923 258
Chris@923 259 void
Chris@923 260 LevelPanWidget::mouseMoveEvent(QMouseEvent *e)
Chris@923 261 {
Chris@923 262 if (!m_editable) return;
Chris@1249 263 if (!m_editing) return;
Chris@923 264
Chris@1301 265 int notch = coordsToNotch(rect(), e->pos());
Chris@1301 266 int pan = coordsToPan(rect(), e->pos());
Chris@1301 267
Chris@1301 268 if (notch == m_notch && pan == m_pan) {
Chris@1266 269 return;
Chris@923 270 }
Chris@1301 271 if (notch != m_notch) {
Chris@1301 272 m_notch = notch;
Chris@1266 273 emitLevelChanged();
Chris@923 274 }
Chris@923 275 if (pan != m_pan) {
Chris@1266 276 m_pan = pan;
Chris@1266 277 emitPanChanged();
Chris@923 278 }
Chris@923 279 update();
Chris@923 280 }
Chris@923 281
Chris@923 282 void
Chris@923 283 LevelPanWidget::wheelEvent(QWheelEvent *e)
Chris@923 284 {
Chris@1303 285 int delta = m_wheelCounter.count(e);
Chris@1303 286
Chris@1303 287 if (delta == 0) {
Chris@1302 288 return;
Chris@1302 289 }
Chris@1302 290
Chris@1303 291 if (e->modifiers() & Qt::ControlModifier) {
Chris@1303 292 m_pan = clampPan(m_pan + delta);
Chris@1303 293 emitPanChanged();
Chris@1303 294 update();
Chris@1302 295 } else {
Chris@1303 296 m_notch = clampNotch(m_notch + delta);
Chris@1303 297 emitLevelChanged();
Chris@1303 298 update();
Chris@923 299 }
Chris@923 300 }
Chris@923 301
Chris@1301 302 int
Chris@1301 303 LevelPanWidget::coordsToNotch(QRectF rect, QPointF loc) const
Chris@923 304 {
Chris@1301 305 double h = rect.height();
Chris@1301 306
Chris@1301 307 int nnotch = m_maxNotch + 1;
Chris@1301 308 double cell = h / nnotch;
Chris@1301 309
Chris@1301 310 int notch = int((h - (loc.y() - rect.y())) / cell);
Chris@1301 311 notch = clampNotch(notch);
Chris@1301 312
Chris@1301 313 return notch;
Chris@1301 314 }
Chris@1301 315
Chris@1301 316 int
Chris@1301 317 LevelPanWidget::coordsToPan(QRectF rect, QPointF loc) const
Chris@1301 318 {
Chris@1301 319 double w = rect.width();
Chris@929 320
Chris@923 321 int npan = maxPan * 2 + 1;
Chris@1301 322 double cell = w / npan;
Chris@929 323
Chris@1301 324 int pan = int((loc.x() - rect.x()) / cell) - maxPan;
Chris@1302 325 pan = clampPan(pan);
Chris@1301 326
Chris@1301 327 return pan;
Chris@923 328 }
Chris@923 329
Chris@923 330 QSizeF
Chris@929 331 LevelPanWidget::cellSize(QRectF rect) const
Chris@923 332 {
Chris@929 333 double w = rect.width(), h = rect.height();
Chris@1301 334 int ncol = maxPan * 2 + 1;
Chris@1301 335 int nrow = m_maxNotch/2;
Chris@1301 336 double wcell = w / ncol, hcell = h / nrow;
Chris@923 337 return QSizeF(wcell, hcell);
Chris@923 338 }
Chris@923 339
Chris@923 340 QPointF
Chris@1301 341 LevelPanWidget::cellCentre(QRectF rect, int row, int col) const
Chris@923 342 {
Chris@929 343 QSizeF cs = cellSize(rect);
Chris@1301 344 return QPointF(rect.x() +
Chris@1301 345 cs.width() * (col + maxPan) + cs.width() / 2.,
Chris@1301 346 rect.y() + rect.height() -
Chris@1301 347 cs.height() * (row + 1) + cs.height() / 2.);
Chris@923 348 }
Chris@923 349
Chris@923 350 QSizeF
Chris@929 351 LevelPanWidget::cellLightSize(QRectF rect) const
Chris@923 352 {
cannam@1307 353 double extent = 0.7;
Chris@929 354 QSizeF cs = cellSize(rect);
Chris@923 355 double m = std::min(cs.width(), cs.height());
Chris@923 356 return QSizeF(m * extent, m * extent);
Chris@923 357 }
Chris@923 358
Chris@923 359 QRectF
Chris@1301 360 LevelPanWidget::cellLightRect(QRectF rect, int row, int col) const
Chris@923 361 {
Chris@929 362 QSizeF cls = cellLightSize(rect);
Chris@1301 363 QPointF cc = cellCentre(rect, row, col);
Chris@923 364 return QRectF(cc.x() - cls.width() / 2.,
Chris@1266 365 cc.y() - cls.height() / 2.,
Chris@1266 366 cls.width(),
Chris@1266 367 cls.height());
Chris@923 368 }
Chris@923 369
Chris@923 370 double
Chris@929 371 LevelPanWidget::thinLineWidth(QRectF rect) const
Chris@923 372 {
Chris@929 373 double tw = ceil(rect.width() / (maxPan * 2. * 10.));
Chris@1301 374 double th = ceil(rect.height() / (m_maxNotch/2 * 10.));
Chris@923 375 return std::min(th, tw);
Chris@923 376 }
Chris@923 377
Chris@1304 378 double
Chris@1304 379 LevelPanWidget::cornerRadius(QRectF rect) const
Chris@1304 380 {
Chris@1304 381 QSizeF cs = cellSize(rect);
Chris@1304 382 double m = std::min(cs.width(), cs.height());
Chris@1304 383 return m / 5;
Chris@1304 384 }
Chris@1304 385
Chris@1301 386 QRectF
Chris@1301 387 LevelPanWidget::cellOutlineRect(QRectF rect, int row, int col) const
Chris@941 388 {
Chris@1301 389 QRectF clr = cellLightRect(rect, row, col);
cannam@1307 390 double adj = thinLineWidth(rect)/2 + 0.5;
Chris@1301 391 return clr.adjusted(-adj, -adj, adj, adj);
Chris@1301 392 }
Chris@1301 393
Chris@1301 394 QColor
Chris@1306 395 LevelPanWidget::cellToColour(int cell) const
Chris@1301 396 {
Chris@1306 397 if (cell < 1) return Qt::black;
Chris@1306 398 if (cell < 2) return QColor(80, 0, 0);
Chris@1306 399 if (cell < 3) return QColor(160, 0, 0);
Chris@1306 400 if (cell < 4) return QColor(255, 0, 0);
Chris@1301 401 return QColor(255, 255, 0);
Chris@941 402 }
Chris@941 403
Chris@923 404 void
Chris@929 405 LevelPanWidget::renderTo(QPaintDevice *dev, QRectF rect, bool asIfEditable) const
Chris@923 406 {
Chris@929 407 QPainter paint(dev);
Chris@923 408
Chris@923 409 paint.setRenderHint(QPainter::Antialiasing, true);
Chris@923 410
Chris@929 411 double thin = thinLineWidth(rect);
Chris@1304 412 double radius = cornerRadius(rect);
Chris@938 413
Chris@1301 414 QColor columnBackground = QColor(180, 180, 180);
Chris@1306 415
Chris@1306 416 bool monitoring = (m_monitorLeft > 0.f || m_monitorRight > 0.f);
Chris@1306 417
Chris@1306 418 QPen pen;
Chris@1306 419 if (isEnabled()) {
Chris@1306 420 pen.setColor(Qt::black);
Chris@1306 421 } else {
Chris@1306 422 pen.setColor(Qt::darkGray);
Chris@1306 423 }
Chris@1306 424 pen.setWidthF(thin);
Chris@1306 425 pen.setCapStyle(Qt::FlatCap);
Chris@1306 426 pen.setJoinStyle(Qt::MiterJoin);
Chris@923 427
Chris@923 428 for (int pan = -maxPan; pan <= maxPan; ++pan) {
Chris@1306 429
Chris@1306 430 paint.setPen(Qt::NoPen);
Chris@1306 431 paint.setBrush(columnBackground);
Chris@1306 432
Chris@1304 433 QRectF top = cellOutlineRect(rect, m_maxNotch/2 - 1, pan);
Chris@1304 434 QRectF bottom = cellOutlineRect(rect, 0, pan);
Chris@1304 435 paint.drawRoundedRect(QRectF(top.x(),
Chris@1304 436 top.y(),
Chris@1304 437 top.width(),
Chris@1304 438 bottom.y() + bottom.height() - top.y()),
Chris@1304 439 radius, radius);
Chris@924 440
Chris@1306 441 if (!asIfEditable && m_includeMute && m_notch == 0) {
Chris@1306 442 // We will instead be drawing a single big X for mute,
Chris@1306 443 // after this loop
Chris@1306 444 continue;
Chris@1306 445 }
Chris@1306 446
Chris@1306 447 if (!monitoring && m_pan != pan) {
Chris@1306 448 continue;
Chris@1306 449 }
Chris@1306 450
Chris@1306 451 int monitorNotch = 0;
Chris@1306 452 if (monitoring) {
Chris@1306 453 float rprop = float(pan - (-maxPan)) / float(maxPan * 2);
Chris@1306 454 float lprop = float(maxPan - pan) / float(maxPan * 2);
Chris@1306 455 float monitorLevel =
Chris@1306 456 lprop * m_monitorLeft * m_monitorLeft +
Chris@1306 457 rprop * m_monitorRight * m_monitorRight;
Chris@1306 458 monitorNotch = audioLevelToNotch(monitorLevel);
Chris@1306 459 }
Chris@1306 460
Chris@1306 461 int firstCell = 0;
Chris@1306 462 int lastCell = m_maxNotch / 2 - 1;
Chris@1306 463
Chris@1306 464 for (int cell = firstCell; cell <= lastCell; ++cell) {
Chris@1306 465
Chris@1306 466 QRectF clr = cellLightRect(rect, cell, pan);
Chris@1306 467
Chris@1306 468 if (m_includeMute && m_pan == pan && m_notch == 0) {
Chris@1306 469 // X for mute in the bottom cell
Chris@1306 470 paint.setPen(pen);
Chris@1306 471 paint.drawLine(clr.topLeft(), clr.bottomRight());
Chris@1306 472 paint.drawLine(clr.bottomLeft(), clr.topRight());
Chris@1306 473 break;
Chris@1306 474 }
Chris@1306 475
Chris@1306 476 const int none = 0, half = 1, full = 2;
Chris@1306 477
Chris@1306 478 int fill = none;
Chris@1306 479
Chris@1306 480 int outline = none;
Chris@1306 481 if (m_pan == pan && m_notch > cell * 2 + 1) {
Chris@1306 482 outline = full;
Chris@1306 483 } else if (m_pan == pan && m_notch == cell * 2 + 1) {
Chris@1306 484 outline = half;
Chris@1306 485 }
Chris@1306 486
Chris@1306 487 if (monitoring) {
Chris@1306 488 if (monitorNotch > cell * 2 + 1) {
Chris@1306 489 fill = full;
Chris@1306 490 } else if (monitorNotch == cell * 2 + 1) {
Chris@1306 491 fill = half;
Chris@1306 492 }
Chris@1306 493 } else {
Chris@1306 494 if (isEnabled()) {
Chris@1306 495 fill = outline;
Chris@1306 496 }
Chris@1306 497 }
Chris@1306 498
Chris@1306 499 // If one of {fill, outline} is "full" and the other is
Chris@1306 500 // "half", then we draw the "half" one first (because we
Chris@1306 501 // need to erase half of it)
Chris@1306 502
Chris@1306 503 if (fill == half || outline == half) {
Chris@1306 504 if (fill == half) {
Chris@1306 505 paint.setBrush(cellToColour(cell));
Chris@1306 506 } else {
Chris@1306 507 paint.setBrush(Qt::NoBrush);
Chris@1306 508 }
Chris@1306 509 if (outline == half) {
Chris@1306 510 paint.setPen(pen);
Chris@1306 511 } else {
Chris@1306 512 paint.setPen(Qt::NoPen);
Chris@1306 513 }
Chris@1306 514
Chris@1306 515 paint.drawRoundedRect(clr, radius, radius);
Chris@1306 516
Chris@1306 517 paint.setBrush(columnBackground);
Chris@1306 518
Chris@1306 519 if (cell == lastCell) {
Chris@1306 520 QPen bgpen(pen);
Chris@1306 521 bgpen.setColor(columnBackground);
Chris@1306 522 paint.setPen(bgpen);
Chris@1306 523 paint.drawRoundedRect(QRectF(clr.x(),
Chris@1306 524 clr.y(),
Chris@1306 525 clr.width(),
Chris@1306 526 clr.height()/4),
Chris@1306 527 radius, radius);
Chris@1306 528 paint.drawRect(QRectF(clr.x(),
Chris@1306 529 clr.y() + clr.height()/4,
Chris@1306 530 clr.width(),
Chris@1306 531 clr.height()/4));
Chris@1306 532 } else {
Chris@1306 533 paint.setPen(Qt::NoPen);
cannam@1307 534 QRectF cor = cellOutlineRect(rect, cell, pan);
cannam@1307 535 paint.drawRect(QRectF(cor.x(),
cannam@1307 536 cor.y() - 0.5,
cannam@1307 537 cor.width(),
cannam@1307 538 cor.height()/2));
Chris@1306 539 }
Chris@1306 540 }
Chris@1306 541
Chris@1306 542 if (outline == full || fill == full) {
Chris@1306 543
Chris@1306 544 if (fill == full) {
Chris@1306 545 paint.setBrush(cellToColour(cell));
Chris@1306 546 } else {
Chris@1306 547 paint.setBrush(Qt::NoBrush);
Chris@1306 548 }
Chris@1306 549 if (outline == full) {
Chris@1306 550 paint.setPen(pen);
Chris@1306 551 } else {
Chris@1306 552 paint.setPen(Qt::NoPen);
Chris@1306 553 }
Chris@1306 554
Chris@1306 555 paint.drawRoundedRect(clr, radius, radius);
Chris@1306 556 }
Chris@1306 557 }
Chris@1301 558 }
Chris@1301 559
Chris@1301 560 if (!asIfEditable && m_includeMute && m_notch == 0) {
Chris@1301 561 // The X for mute takes up the whole display when we're not
Chris@1301 562 // being rendered in editable style
Chris@1306 563 pen.setColor(Qt::black);
Chris@1301 564 pen.setWidthF(thin * 2);
Chris@1301 565 pen.setCapStyle(Qt::RoundCap);
Chris@1301 566 paint.setPen(pen);
Chris@1301 567 paint.drawLine(cellCentre(rect, 0, -maxPan),
Chris@1301 568 cellCentre(rect, m_maxNotch/2 - 1, maxPan));
Chris@1301 569 paint.drawLine(cellCentre(rect, m_maxNotch/2 - 1, -maxPan),
Chris@1301 570 cellCentre(rect, 0, maxPan));
Chris@1177 571 }
Chris@923 572 }
Chris@923 573
Chris@929 574 void
Chris@929 575 LevelPanWidget::paintEvent(QPaintEvent *)
Chris@929 576 {
Chris@929 577 renderTo(this, rect(), m_editable);
Chris@929 578 }
Chris@923 579
Chris@1180 580 void
Chris@1180 581 LevelPanWidget::enterEvent(QEvent *e)
Chris@1180 582 {
Chris@1180 583 QWidget::enterEvent(e);
Chris@1180 584 emit mouseEntered();
Chris@1180 585 }
Chris@929 586
Chris@1180 587 void
Chris@1180 588 LevelPanWidget::leaveEvent(QEvent *e)
Chris@1180 589 {
Chris@1180 590 QWidget::enterEvent(e);
Chris@1180 591 emit mouseLeft();
Chris@1180 592 }
Chris@929 593