dynDrawer.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  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. #include <QPainter>
  24. #include <qevent.h>
  25. #include <QPixmap>
  26. #include "tempomap.h"
  27. #include "assert.h"
  28. //TODO: this class is a dummy
  29. qtauDynLabel::qtauDynLabel(const QString &txt, QWidget *parent) : QLabel(txt, parent), _state(off) {}
  30. qtauDynLabel::~qtauDynLabel() {}
  31. void qtauDynLabel::mousePressEvent(QMouseEvent *event)
  32. {
  33. if (event->button() == Qt::LeftButton)
  34. emit leftClicked();
  35. else if (event->button() == Qt::RightButton)
  36. emit rightClicked();
  37. }
  38. qtauDynLabel::EState qtauDynLabel::state() { return _state; }
  39. void qtauDynLabel::setState(EState s) { _state = s; }
  40. //===========================================================================
  41. #define SLIDE 5
  42. #define WIDTH 10
  43. qtauDynDrawer::qtauDynDrawer(qtauNoteEditor* qne,QWidget *parent) :
  44. QWidget(parent), _offset(0), _bgCache(nullptr)
  45. {
  46. _editor=qne;
  47. connect(_editor,&qtauNoteEditor::repaintDynDrawer,this,&qtauDynDrawer::onRepaintDynDrawer);
  48. }
  49. qtauDynDrawer::~qtauDynDrawer()
  50. {
  51. //
  52. }
  53. void qtauDynDrawer::onRepaintDynDrawer(void)
  54. {
  55. update();
  56. }
  57. void qtauDynDrawer::setOffset(int off)
  58. {
  59. if (off != _offset)
  60. {
  61. _offset = off;
  62. update();
  63. }
  64. }
  65. void qtauDynDrawer::configure(const SNoteSetup &newSetup)
  66. {
  67. _ns = newSetup;
  68. updateCache();
  69. update();
  70. }
  71. //------------------------------------
  72. void qtauDynDrawer::paintEvent(QPaintEvent *event)
  73. {
  74. // draw bg
  75. int hSt = event->rect().x() + _offset;
  76. _hSt = hSt;
  77. int barWidth = _ns.note.width() * 4;
  78. int firstBar = hSt / barWidth;
  79. int cacheOffset = hSt - firstBar * barWidth;
  80. QRect screenRect(event->rect());
  81. QRect cacheRect(screenRect);
  82. cacheRect.moveLeft(cacheRect.x() + cacheOffset);
  83. QPainter p(this);
  84. p.drawPixmap(screenRect, *_bgCache, cacheRect);
  85. if(_velSelected) //draw vel
  86. {
  87. _h = event->rect().height();
  88. foreach (quint64 key, _editor->_notes.idMap.keys())
  89. {
  90. qne::editorNote &n = _editor->_notes.idMap[key];
  91. double pulsesToPixels = (double)_ns.note.width() / c_midi_ppq;
  92. int notePos = n.pulseOffset * pulsesToPixels;
  93. notePos -=SLIDE;
  94. notePos -= hSt;
  95. float velocity = 100/128.0;
  96. if(key==_noteUnderCursor) velocity = _velocity;
  97. int width = WIDTH;
  98. int height = _h*(1-velocity);
  99. QRect noteRect(notePos,_h,width,height-_h);
  100. if(key==_noteUnderCursor) p.fillRect(noteRect,QBrush(Qt::blue));
  101. else p.fillRect(noteRect,QBrush(Qt::green));
  102. }
  103. }
  104. }
  105. void qtauDynDrawer::resizeEvent(QResizeEvent*)
  106. {
  107. updateCache();
  108. }
  109. //incomplete :: editing needs to be done
  110. void qtauDynDrawer::mouseDoubleClickEvent(QMouseEvent*)
  111. {
  112. //
  113. }
  114. void qtauDynDrawer::mouseMoveEvent(QMouseEvent* event)
  115. {
  116. (void) event;
  117. #if FIX_VOCAL_DYNAMICS
  118. //#FIXME this is broken
  119. //TODO :: move to dynDrawerHandler
  120. if(!(_noteUnderCursor!=))
  121. {
  122. if(event->x()>_notePos && event->x()<_notePos+WIDTH && _velSelected)
  123. {
  124. _velocity = (_h-event->y())/(1.0*_h);
  125. }
  126. update();
  127. }
  128. #endif
  129. }
  130. void qtauDynDrawer::mousePressEvent(QMouseEvent* event)
  131. {
  132. //
  133. if(_velSelected) //draw vel
  134. {
  135. foreach (quint64 key, _editor->_notes.idMap.keys())
  136. {
  137. qne::editorNote &n = _editor->_notes.idMap[key];
  138. double pulsesToPixels = (double)_ns.note.width() / c_midi_ppq;
  139. int notePos = n.pulseOffset * pulsesToPixels;
  140. notePos -=SLIDE;
  141. notePos -= _hSt;
  142. if(event->x()>notePos && event->x()<notePos+WIDTH)
  143. {
  144. _noteUnderCursor = key;
  145. _notePos = notePos;
  146. update();
  147. }
  148. _velocity = (_h-event->y())/(1.0*_h);
  149. }
  150. }
  151. }
  152. void qtauDynDrawer::mouseReleaseEvent(QMouseEvent*)
  153. {
  154. _noteUnderCursor = -1;
  155. //if(_velSelected) updateModel()
  156. update();
  157. }
  158. void qtauDynDrawer::wheelEvent(QWheelEvent *event)
  159. {
  160. if (event->modifiers() & Qt::ControlModifier)
  161. emit zoomed(event->delta());
  162. else
  163. emit scrolled(event->delta());
  164. }
  165. void qtauDynDrawer::updateCache()
  166. {
  167. //DEVLOG_DEBUG("updateCache()");
  168. if (geometry().height() == 0)
  169. {
  170. DEVLOG_ERROR("Zero height of dynDrawer in updateCache()... This definitely shouldn't happen.");
  171. return;
  172. }
  173. // bars fully fit in + 2 for partially visible bars
  174. int barWidth = _ns.note.width() * 4;
  175. int requiredCacheWidth = (geometry().width() / barWidth + 2) * barWidth;
  176. if (!_bgCache || (_bgCache->width() < requiredCacheWidth || _bgCache->height() < geometry().height()))
  177. {
  178. if (_bgCache)
  179. delete _bgCache;
  180. _bgCache = new QPixmap(requiredCacheWidth, geometry().height());
  181. }
  182. // prepare painting data
  183. int vSt = 0;
  184. int vEnd = geometry().height();
  185. int mSt = vEnd / 2 - 10;
  186. int mEnd = mSt + 20;
  187. int bar = 0;
  188. int beat = 0;
  189. int pxOff = 0;
  190. QVector<QPoint> noteLines;
  191. QVector<QPoint> barLines;
  192. assert(_ns.tmap);
  193. while (true)
  194. {
  195. if (pxOff >= requiredCacheWidth)
  196. break;
  197. fraction time = _ns.tmap->getTimeSignatureForBar(bar);
  198. if (beat==time.numerator)
  199. {
  200. barLines.append(QPoint(pxOff, vSt ));
  201. barLines.append(QPoint(pxOff, vEnd));
  202. beat = 1;
  203. bar++;
  204. }
  205. else
  206. {
  207. noteLines.append(QPoint(pxOff, mSt ));
  208. noteLines.append(QPoint(pxOff, mEnd));
  209. beat++;
  210. }
  211. pxOff += _ns.note.width();
  212. }
  213. // paint 'em!
  214. _bgCache->fill(Qt::white);
  215. QPainter p(_bgCache);
  216. p.setPen(QColor(cdef_color_inner_line));
  217. p.drawLines(noteLines);
  218. p.setPen(QColor(cdef_color_outer_line));
  219. p.drawLines(barLines);
  220. }