dynDrawer.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /*
  2. This file is part of QTau
  3. Copyright (C) 2013-2018 Tobias "Tomoko" Platen <tplaten@posteo.de>
  4. Copyright (C) 2013 digited <https://github.com/digited>
  5. Copyright (C) 2010-2013 HAL@ShurabaP <https://github.com/haruneko>
  6. QTau is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. SPDX-License-Identifier: GPL-3.0+
  17. */
  18. #define __devloglevel__ 4
  19. #include "ui/dynDrawer.h"
  20. #include "ui/Config.h"
  21. #include "ui/noteEditor.h"
  22. // FIXME dynamics not supported yet, need synth/storeage support
  23. // scalars: VEL,
  24. #include <qevent.h>
  25. #include <QPainter>
  26. #include <QPixmap>
  27. #include "assert.h"
  28. #include "tempomap.h"
  29. #include <QDebug>
  30. #include <QTextEdit>
  31. #include <QVBoxLayout>
  32. // TODO: this class is a dummy
  33. qtauDynLabel::qtauDynLabel(const QString &txt, QWidget *parent)
  34. : QLabel(txt, parent), _state(off) {}
  35. qtauDynLabel::~qtauDynLabel() {}
  36. void qtauDynLabel::mousePressEvent(QMouseEvent *event) {
  37. if (event->button() == Qt::LeftButton)
  38. emit leftClicked();
  39. else if (event->button() == Qt::RightButton)
  40. emit rightClicked();
  41. }
  42. qtauDynLabel::EState qtauDynLabel::state() { return _state; }
  43. void qtauDynLabel::setState(EState s) { _state = s; }
  44. //===========================================================================
  45. #define SLIDE 5
  46. #define WIDTH 10
  47. qtauDynDrawer::qtauDynDrawer(qtauNoteEditor *qne, QWidget *parent)
  48. : QWidget(parent), _offset(0), _bgCache(nullptr) {
  49. _editor = qne;
  50. connect(_editor, &qtauNoteEditor::repaintDynDrawer, this,
  51. &qtauDynDrawer::onRepaintDynDrawer);
  52. }
  53. qtauDynDrawer::~qtauDynDrawer() {
  54. //
  55. }
  56. void qtauDynDrawer::onRepaintDynDrawer(void) { update(); }
  57. void qtauDynDrawer::setOffset(int off) {
  58. if (off != _offset) {
  59. _offset = off;
  60. update();
  61. }
  62. }
  63. void qtauDynDrawer::configure(const SNoteSetup &newSetup) {
  64. _ns = newSetup;
  65. updateCache();
  66. update();
  67. }
  68. //------------------------------------
  69. void qtauDynDrawer::paintEvent(QPaintEvent *event) {
  70. // draw bg
  71. int hSt = event->rect().x() + _offset;
  72. _hSt = hSt;
  73. int barWidth = _ns.note.width() * 4;
  74. int firstBar = hSt / barWidth;
  75. int cacheOffset = hSt - firstBar * barWidth;
  76. QRect screenRect(event->rect());
  77. QRect cacheRect(screenRect);
  78. cacheRect.moveLeft(cacheRect.x() + cacheOffset);
  79. QPainter p(this);
  80. p.drawPixmap(screenRect, *_bgCache, cacheRect);
  81. if (_velSelected) // draw vel
  82. {
  83. _h = event->rect().height();
  84. foreach (quint64 key, _editor->_notes.idMap.keys()) {
  85. qne::editorNote &n = _editor->_notes.idMap[key];
  86. double pulsesToPixels = (double)_ns.note.width() / c_midi_ppq;
  87. int notePos = n.pulseOffset * pulsesToPixels;
  88. notePos -= SLIDE;
  89. notePos -= hSt;
  90. float velocity = 100 / 128.0;
  91. if (key == _noteUnderCursor) velocity = _velocity;
  92. int width = WIDTH;
  93. int height = _h * (1 - velocity);
  94. QRect noteRect(notePos, _h, width, height - _h);
  95. if (key == _noteUnderCursor)
  96. p.fillRect(noteRect, QBrush(Qt::blue));
  97. else
  98. p.fillRect(noteRect, QBrush(Qt::green));
  99. }
  100. }
  101. }
  102. void qtauDynDrawer::resizeEvent(QResizeEvent *) { updateCache(); }
  103. // incomplete :: editing needs to be done
  104. void qtauDynDrawer::mouseDoubleClickEvent(QMouseEvent *) {
  105. _edit = new QTextEdit(this);
  106. // _edit->setGeometry(r);
  107. _edit->setVisible(true);
  108. _edit->setText("TODO");
  109. _edit->setFocus();
  110. _edit->selectAll();
  111. QVBoxLayout *layout = new QVBoxLayout;
  112. layout->addWidget(_edit);
  113. setLayout(layout);
  114. }
  115. void qtauDynDrawer::mouseMoveEvent(QMouseEvent *event) {
  116. (void)event;
  117. #if TODO
  118. //refactoring needed
  119. // if (!(_noteUnderCursor !=)) {
  120. if (event->x() > _notePos && event->x() < _notePos + WIDTH &&
  121. _velSelected) {
  122. _velocity = (_h - event->y()) / (1.0 * _h);
  123. // }
  124. update();
  125. }
  126. #endif
  127. }
  128. void qtauDynDrawer::mousePressEvent(QMouseEvent *event) {
  129. //
  130. if (_velSelected) // draw vel
  131. {
  132. foreach (quint64 key, _editor->_notes.idMap.keys()) {
  133. qne::editorNote &n = _editor->_notes.idMap[key];
  134. double pulsesToPixels = (double)_ns.note.width() / c_midi_ppq;
  135. int notePos = n.pulseOffset * pulsesToPixels;
  136. notePos -= SLIDE;
  137. notePos -= _hSt;
  138. if (event->x() > notePos && event->x() < notePos + WIDTH) {
  139. _noteUnderCursor = key;
  140. _notePos = notePos;
  141. update();
  142. }
  143. _velocity = (_h - event->y()) / (1.0 * _h);
  144. }
  145. }
  146. }
  147. void qtauDynDrawer::mouseReleaseEvent(QMouseEvent *) {
  148. _noteUnderCursor = -1;
  149. // if(_velSelected) updateModel()
  150. update();
  151. }
  152. void qtauDynDrawer::wheelEvent(QWheelEvent *event) {
  153. if (event->modifiers() & Qt::ControlModifier)
  154. emit zoomed(event->delta());
  155. else
  156. emit scrolled(event->delta());
  157. }
  158. void qtauDynDrawer::updateCache() {
  159. // DEVLOG_DEBUG("updateCache()");
  160. if (geometry().height() == 0) {
  161. DEVLOG_ERROR(
  162. "Zero height of dynDrawer in updateCache()... This definitely "
  163. "shouldn't happen.");
  164. return;
  165. }
  166. // bars fully fit in + 2 for partially visible bars
  167. int requiredCacheWidth =
  168. _ns.barScreenOffsets[_ns.numBars - 1] + _ns.note.width() * 8;
  169. if (!_bgCache || (_bgCache->width() < requiredCacheWidth ||
  170. _bgCache->height() < geometry().height())) {
  171. if (_bgCache) delete _bgCache;
  172. _bgCache = new QPixmap(requiredCacheWidth, geometry().height());
  173. }
  174. // prepare painting data
  175. int vSt = 0;
  176. int vEnd = geometry().height();
  177. int mSt = vEnd / 2 - 10;
  178. int mEnd = mSt + 20;
  179. int bar = 0;
  180. int beat = 0;
  181. int pxOff = 0;
  182. QVector<QPoint> noteLines;
  183. QVector<QPoint> barLines;
  184. assert(_ns.tmap);
  185. while (true) {
  186. if (pxOff >= requiredCacheWidth) break;
  187. fraction time = _ns.tmap->getTimeSignatureForBar(bar);
  188. if (beat == time.numerator) {
  189. barLines.append(QPoint(pxOff, vSt));
  190. barLines.append(QPoint(pxOff, vEnd));
  191. beat = 1;
  192. bar++;
  193. time = _ns.tmap->getTimeSignatureForBar(bar);
  194. } else {
  195. noteLines.append(QPoint(pxOff, mSt));
  196. noteLines.append(QPoint(pxOff, mEnd));
  197. beat++;
  198. }
  199. pxOff += _ns.note.width() * 4.0 / time.denominator;
  200. }
  201. // paint 'em!
  202. _bgCache->fill(Qt::white);
  203. QPainter p(_bgCache);
  204. p.setPen(QColor(cdef_color_inner_line));
  205. p.drawLines(noteLines);
  206. p.setPen(QColor(cdef_color_outer_line));
  207. p.drawLines(barLines);
  208. }