|
|
@@ -1,15 +1,15 @@ |
|
|
|
/* |
|
|
|
* Pixmap Keyboard, a custom Qt4 widget |
|
|
|
* Copyright (C) 2011-2012 Filipe Coelho <falktx@falktx.com> |
|
|
|
* Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.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 2 of the License, or |
|
|
|
* any later version. |
|
|
|
* 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 2 of |
|
|
|
* the License, or 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 |
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
|
* GNU General Public License for more details. |
|
|
|
* |
|
|
|
* For a full copy of the GNU General Public License see the COPYING file |
|
|
@@ -17,141 +17,129 @@ |
|
|
|
|
|
|
|
#include "pixmapkeyboard.hpp" |
|
|
|
|
|
|
|
#include <QtCore/QMap> |
|
|
|
#include <QtCore/QTimer> |
|
|
|
#include <QtGui/QKeyEvent> |
|
|
|
#include <QtGui/QMouseEvent> |
|
|
|
#include <QtGui/QPainter> |
|
|
|
|
|
|
|
QMap<int, QRectF> midi_key2rect_map_horizontal; |
|
|
|
QMap<int, QRectF> midi_key2rect_map_vertical; |
|
|
|
QMap<int, int> midi_keyboard2key_map; |
|
|
|
QVector<int> blackNotes; |
|
|
|
|
|
|
|
static bool pixmapkeyboard_initiated = false; |
|
|
|
void pixmapkeyboard_init() |
|
|
|
{ |
|
|
|
if (pixmapkeyboard_initiated) |
|
|
|
return; |
|
|
|
|
|
|
|
pixmapkeyboard_initiated = true; |
|
|
|
|
|
|
|
// midi_key2rect_map_horizontal ------ |
|
|
|
midi_key2rect_map_horizontal[0] = QRectF(0, 0, 18, 64); // C |
|
|
|
midi_key2rect_map_horizontal[1] = QRectF(13, 0, 11, 42); // C# |
|
|
|
midi_key2rect_map_horizontal[2] = QRectF(18, 0, 25, 64); // D |
|
|
|
midi_key2rect_map_horizontal[3] = QRectF(37, 0, 11, 42); // D# |
|
|
|
midi_key2rect_map_horizontal[4] = QRectF(42, 0, 18, 64); // E |
|
|
|
midi_key2rect_map_horizontal[5] = QRectF(60, 0, 18, 64); // F |
|
|
|
midi_key2rect_map_horizontal[6] = QRectF(73, 0, 11, 42); // F# |
|
|
|
midi_key2rect_map_horizontal[7] = QRectF(78, 0, 25, 64); // G |
|
|
|
midi_key2rect_map_horizontal[8] = QRectF(97, 0, 11, 42); // G# |
|
|
|
midi_key2rect_map_horizontal[9] = QRectF(102, 0, 25, 64); // A |
|
|
|
midi_key2rect_map_horizontal[10] = QRectF(121, 0, 11, 42); // A# |
|
|
|
midi_key2rect_map_horizontal[11] = QRectF(126, 0, 18, 64); // B |
|
|
|
|
|
|
|
// midi_key2rect_map_vertical -------- |
|
|
|
midi_key2rect_map_vertical[11] = QRectF(0, 0, 64, 18); // B |
|
|
|
midi_key2rect_map_vertical[10] = QRectF(0, 14, 42, 7); // A# |
|
|
|
midi_key2rect_map_vertical[9] = QRectF(0, 18, 64, 24); // A |
|
|
|
midi_key2rect_map_vertical[8] = QRectF(0, 38, 42, 7); // G# |
|
|
|
midi_key2rect_map_vertical[7] = QRectF(0, 42, 64, 24); // G |
|
|
|
midi_key2rect_map_vertical[6] = QRectF(0, 62, 42, 7); // F# |
|
|
|
midi_key2rect_map_vertical[5] = QRectF(0, 66, 64, 18); // F |
|
|
|
midi_key2rect_map_vertical[4] = QRectF(0, 84, 64, 18); // E |
|
|
|
midi_key2rect_map_vertical[3] = QRectF(0, 98, 42, 7); // D# |
|
|
|
midi_key2rect_map_vertical[2] = QRectF(0, 102, 64, 24); // D |
|
|
|
midi_key2rect_map_vertical[1] = QRectF(0, 122, 42, 7); // C# |
|
|
|
midi_key2rect_map_vertical[0] = QRectF(0, 126, 64, 18); // C |
|
|
|
|
|
|
|
// midi_keyboard2key_map ------------- |
|
|
|
static std::map<int, QRectF> kMidiKey2RectMapHorizontal = { |
|
|
|
{0, QRectF(0, 0, 18, 64)}, // C |
|
|
|
{1, QRectF(13, 0, 11, 42)}, // C# |
|
|
|
{2, QRectF(18, 0, 25, 64)}, // D |
|
|
|
{3, QRectF(37, 0, 11, 42)}, // D# |
|
|
|
{4, QRectF(42, 0, 18, 64)}, // E |
|
|
|
{5, QRectF(60, 0, 18, 64)}, // F |
|
|
|
{6, QRectF(73, 0, 11, 42)}, // F# |
|
|
|
{7, QRectF(78, 0, 25, 64)}, // G |
|
|
|
{8, QRectF(97, 0, 11, 42)}, // G# |
|
|
|
{9, QRectF(102, 0, 25, 64)}, // A |
|
|
|
{10, QRectF(121, 0, 11, 42)}, // A# |
|
|
|
{11, QRectF(126, 0, 18, 64)} // B |
|
|
|
}; |
|
|
|
|
|
|
|
static std::map<int, QRectF> kMidiKey2RectMapVertical = { |
|
|
|
{11, QRectF(0, 0, 64, 18)}, // B |
|
|
|
{10, QRectF(0, 14, 42, 7)}, // A# |
|
|
|
{9, QRectF(0, 18, 64, 24)}, // A |
|
|
|
{8, QRectF(0, 38, 42, 7)}, // G# |
|
|
|
{7, QRectF(0, 42, 64, 24)}, // G |
|
|
|
{6, QRectF(0, 62, 42, 7)}, // F# |
|
|
|
{5, QRectF(0, 66, 64, 18)}, // F |
|
|
|
{4, QRectF(0, 84, 64, 18)}, // E |
|
|
|
{3, QRectF(0, 98, 42, 7)}, // D# |
|
|
|
{2, QRectF(0, 102, 64, 24)}, // D |
|
|
|
{1, QRectF(0, 122, 42, 7)}, // C# |
|
|
|
{0, QRectF(0, 126, 64, 18)} // C |
|
|
|
}; |
|
|
|
|
|
|
|
static const std::map<int, int> kMidiKeyboard2KeyMap = { |
|
|
|
// 3th octave |
|
|
|
midi_keyboard2key_map[Qt::Key_Z] = 48; |
|
|
|
midi_keyboard2key_map[Qt::Key_S] = 49; |
|
|
|
midi_keyboard2key_map[Qt::Key_X] = 50; |
|
|
|
midi_keyboard2key_map[Qt::Key_D] = 51; |
|
|
|
midi_keyboard2key_map[Qt::Key_C] = 52; |
|
|
|
midi_keyboard2key_map[Qt::Key_V] = 53; |
|
|
|
midi_keyboard2key_map[Qt::Key_G] = 54; |
|
|
|
midi_keyboard2key_map[Qt::Key_B] = 55; |
|
|
|
midi_keyboard2key_map[Qt::Key_H] = 56; |
|
|
|
midi_keyboard2key_map[Qt::Key_N] = 57; |
|
|
|
midi_keyboard2key_map[Qt::Key_J] = 58; |
|
|
|
midi_keyboard2key_map[Qt::Key_M] = 59; |
|
|
|
{Qt::Key_Z, 48}, |
|
|
|
{Qt::Key_S, 49}, |
|
|
|
{Qt::Key_X, 50}, |
|
|
|
{Qt::Key_D, 51}, |
|
|
|
{Qt::Key_C, 52}, |
|
|
|
{Qt::Key_V, 53}, |
|
|
|
{Qt::Key_G, 54}, |
|
|
|
{Qt::Key_B, 55}, |
|
|
|
{Qt::Key_H, 56}, |
|
|
|
{Qt::Key_N, 57}, |
|
|
|
{Qt::Key_J, 58}, |
|
|
|
{Qt::Key_M, 59}, |
|
|
|
// 4th octave |
|
|
|
midi_keyboard2key_map[Qt::Key_Q] = 60; |
|
|
|
midi_keyboard2key_map[Qt::Key_2] = 61; |
|
|
|
midi_keyboard2key_map[Qt::Key_W] = 62; |
|
|
|
midi_keyboard2key_map[Qt::Key_3] = 63; |
|
|
|
midi_keyboard2key_map[Qt::Key_E] = 64; |
|
|
|
midi_keyboard2key_map[Qt::Key_R] = 65; |
|
|
|
midi_keyboard2key_map[Qt::Key_5] = 66; |
|
|
|
midi_keyboard2key_map[Qt::Key_T] = 67; |
|
|
|
midi_keyboard2key_map[Qt::Key_6] = 68; |
|
|
|
midi_keyboard2key_map[Qt::Key_Y] = 69; |
|
|
|
midi_keyboard2key_map[Qt::Key_7] = 70; |
|
|
|
midi_keyboard2key_map[Qt::Key_U] = 71; |
|
|
|
|
|
|
|
blackNotes << 1; |
|
|
|
blackNotes << 3; |
|
|
|
blackNotes << 6; |
|
|
|
blackNotes << 8; |
|
|
|
blackNotes << 10; |
|
|
|
} |
|
|
|
{Qt::Key_Q, 60}, |
|
|
|
{Qt::Key_2, 61}, |
|
|
|
{Qt::Key_W, 62}, |
|
|
|
{Qt::Key_3, 63}, |
|
|
|
{Qt::Key_E, 64}, |
|
|
|
{Qt::Key_R, 65}, |
|
|
|
{Qt::Key_5, 66}, |
|
|
|
{Qt::Key_T, 67}, |
|
|
|
{Qt::Key_6, 68}, |
|
|
|
{Qt::Key_Y, 69}, |
|
|
|
{Qt::Key_7, 70}, |
|
|
|
{Qt::Key_U, 71} |
|
|
|
}; |
|
|
|
|
|
|
|
static const QVector<int> kBlackNotes = {1, 3, 6, 8, 10}; |
|
|
|
|
|
|
|
PixmapKeyboard::PixmapKeyboard(QWidget* parent) |
|
|
|
: QWidget(parent), |
|
|
|
m_font("Monospace", 8, QFont::Normal) |
|
|
|
fPixmap(""), |
|
|
|
fPixmapMode(HORIZONTAL), |
|
|
|
fColorStr("orange"), |
|
|
|
fFont("Monospace", 8, QFont::Normal), |
|
|
|
fOctaves(6), |
|
|
|
fLastMouseNote(-1), |
|
|
|
fWidth(0), |
|
|
|
fHeight(0), |
|
|
|
fNeedsUpdate(false), |
|
|
|
fMidiMap(kMidiKey2RectMapHorizontal) |
|
|
|
{ |
|
|
|
pixmapkeyboard_init(); |
|
|
|
|
|
|
|
m_octaves = 6; |
|
|
|
m_lastMouseNote = -1; |
|
|
|
m_needsUpdate = false; |
|
|
|
|
|
|
|
setCursor(Qt::PointingHandCursor); |
|
|
|
setMode(HORIZONTAL); |
|
|
|
} |
|
|
|
|
|
|
|
void PixmapKeyboard::allNotesOff() |
|
|
|
{ |
|
|
|
m_enabledKeys.clear(); |
|
|
|
|
|
|
|
m_needsUpdate = true; |
|
|
|
QTimer::singleShot(0, this, SLOT(updateOnce())); |
|
|
|
fEnabledKeys.clear(); |
|
|
|
fNeedsUpdate = true; |
|
|
|
|
|
|
|
emit notesOff(); |
|
|
|
QTimer::singleShot(0, this, SLOT(updateOnce())); |
|
|
|
} |
|
|
|
|
|
|
|
void PixmapKeyboard::sendNoteOn(int note, bool sendSignal) |
|
|
|
{ |
|
|
|
if (0 <= note && note <= 127 && ! m_enabledKeys.contains(note)) |
|
|
|
if (0 <= note && note <= 127 && ! fEnabledKeys.contains(note)) |
|
|
|
{ |
|
|
|
m_enabledKeys.append(note); |
|
|
|
fEnabledKeys.append(note); |
|
|
|
|
|
|
|
if (sendSignal) |
|
|
|
emit noteOn(note); |
|
|
|
|
|
|
|
m_needsUpdate = true; |
|
|
|
fNeedsUpdate = true; |
|
|
|
QTimer::singleShot(0, this, SLOT(updateOnce())); |
|
|
|
} |
|
|
|
|
|
|
|
if (m_enabledKeys.count() == 1) |
|
|
|
if (fEnabledKeys.count() == 1) |
|
|
|
emit notesOn(); |
|
|
|
} |
|
|
|
|
|
|
|
void PixmapKeyboard::sendNoteOff(int note, bool sendSignal) |
|
|
|
{ |
|
|
|
if (note >= 0 && note <= 127 && m_enabledKeys.contains(note)) |
|
|
|
if (note >= 0 && note <= 127 && fEnabledKeys.contains(note)) |
|
|
|
{ |
|
|
|
m_enabledKeys.removeOne(note); |
|
|
|
fEnabledKeys.removeOne(note); |
|
|
|
|
|
|
|
if (sendSignal) |
|
|
|
emit noteOff(note); |
|
|
|
|
|
|
|
m_needsUpdate = true; |
|
|
|
fNeedsUpdate = true; |
|
|
|
QTimer::singleShot(0, this, SLOT(updateOnce())); |
|
|
|
} |
|
|
|
|
|
|
|
if (m_enabledKeys.count() == 0) |
|
|
|
if (fEnabledKeys.count() == 0) |
|
|
|
emit notesOff(); |
|
|
|
} |
|
|
|
|
|
|
@@ -159,11 +147,11 @@ void PixmapKeyboard::setMode(Orientation mode, Color color) |
|
|
|
{ |
|
|
|
if (color == COLOR_CLASSIC) |
|
|
|
{ |
|
|
|
m_colorStr = "classic"; |
|
|
|
fColorStr = "classic"; |
|
|
|
} |
|
|
|
else if (color == COLOR_ORANGE) |
|
|
|
{ |
|
|
|
m_colorStr = "orange"; |
|
|
|
fColorStr = "orange"; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
@@ -173,19 +161,19 @@ void PixmapKeyboard::setMode(Orientation mode, Color color) |
|
|
|
|
|
|
|
if (mode == HORIZONTAL) |
|
|
|
{ |
|
|
|
m_midi_map = &midi_key2rect_map_horizontal; |
|
|
|
m_pixmap.load(QString(":/bitmaps/kbd_h_%1.png").arg(m_colorStr)); |
|
|
|
m_pixmap_mode = HORIZONTAL; |
|
|
|
p_width = m_pixmap.width(); |
|
|
|
p_height = m_pixmap.height() / 2; |
|
|
|
fMidiMap = kMidiKey2RectMapHorizontal; |
|
|
|
fPixmap.load(QString(":/bitmaps/kbd_h_%1.png").arg(fColorStr)); |
|
|
|
fPixmapMode = HORIZONTAL; |
|
|
|
fWidth = fPixmap.width(); |
|
|
|
fHeight = fPixmap.height() / 2; |
|
|
|
} |
|
|
|
else if (mode == VERTICAL) |
|
|
|
{ |
|
|
|
m_midi_map = &midi_key2rect_map_vertical; |
|
|
|
m_pixmap.load(QString(":/bitmaps/kbd_v_%1.png").arg(m_colorStr)); |
|
|
|
m_pixmap_mode = VERTICAL; |
|
|
|
p_width = m_pixmap.width() / 2; |
|
|
|
p_height = m_pixmap.height(); |
|
|
|
fMidiMap = kMidiKey2RectMapVertical; |
|
|
|
fPixmap.load(QString(":/bitmaps/kbd_v_%1.png").arg(fColorStr)); |
|
|
|
fPixmapMode = VERTICAL; |
|
|
|
fWidth = fPixmap.width() / 2; |
|
|
|
fHeight = fPixmap.height(); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
@@ -193,28 +181,29 @@ void PixmapKeyboard::setMode(Orientation mode, Color color) |
|
|
|
return setMode(HORIZONTAL); |
|
|
|
} |
|
|
|
|
|
|
|
setOctaves(m_octaves); |
|
|
|
setOctaves(fOctaves); |
|
|
|
} |
|
|
|
|
|
|
|
void PixmapKeyboard::setOctaves(int octaves) |
|
|
|
{ |
|
|
|
Q_ASSERT(octaves >= 1 && octaves <= 6); |
|
|
|
Q_ASSERT(octaves >= 1 && octaves <= 8); |
|
|
|
|
|
|
|
if (octaves < 1) |
|
|
|
octaves = 1; |
|
|
|
else if (octaves > 6) |
|
|
|
octaves = 6; |
|
|
|
m_octaves = octaves; |
|
|
|
else if (octaves > 8) |
|
|
|
octaves = 8; |
|
|
|
|
|
|
|
if (m_pixmap_mode == HORIZONTAL) |
|
|
|
fOctaves = octaves; |
|
|
|
|
|
|
|
if (fPixmapMode == HORIZONTAL) |
|
|
|
{ |
|
|
|
setMinimumSize(p_width * m_octaves, p_height); |
|
|
|
setMaximumSize(p_width * m_octaves, p_height); |
|
|
|
setMinimumSize(fWidth * fOctaves, fHeight); |
|
|
|
setMaximumSize(fWidth * fOctaves, fHeight); |
|
|
|
} |
|
|
|
else if (m_pixmap_mode == VERTICAL) |
|
|
|
else if (fPixmapMode == VERTICAL) |
|
|
|
{ |
|
|
|
setMinimumSize(p_width, p_height * m_octaves); |
|
|
|
setMaximumSize(p_width, p_height * m_octaves); |
|
|
|
setMinimumSize(fWidth, fHeight * fOctaves); |
|
|
|
setMaximumSize(fWidth, fHeight * fOctaves); |
|
|
|
} |
|
|
|
|
|
|
|
update(); |
|
|
@@ -222,53 +211,54 @@ void PixmapKeyboard::setOctaves(int octaves) |
|
|
|
|
|
|
|
void PixmapKeyboard::handleMousePos(const QPoint& pos) |
|
|
|
{ |
|
|
|
int note, octave; |
|
|
|
QPointF n_pos; |
|
|
|
int note; |
|
|
|
int octave; |
|
|
|
QPointF keyPos; |
|
|
|
|
|
|
|
if (m_pixmap_mode == HORIZONTAL) |
|
|
|
if (fPixmapMode == HORIZONTAL) |
|
|
|
{ |
|
|
|
if (pos.x() < 0 or pos.x() > m_octaves * 144) |
|
|
|
if (pos.x() < 0 or pos.x() > fOctaves * 144) |
|
|
|
return; |
|
|
|
int posX = pos.x() - 1; |
|
|
|
octave = posX / p_width; |
|
|
|
n_pos = QPointF(posX % p_width, pos.y()); |
|
|
|
octave = posX / fWidth; |
|
|
|
keyPos = QPointF(posX % fWidth, pos.y()); |
|
|
|
} |
|
|
|
else if (m_pixmap_mode == VERTICAL) |
|
|
|
else if (fPixmapMode == VERTICAL) |
|
|
|
{ |
|
|
|
if (pos.y() < 0 or pos.y() > m_octaves * 144) |
|
|
|
if (pos.y() < 0 or pos.y() > fOctaves * 144) |
|
|
|
return; |
|
|
|
int posY = pos.y() - 1; |
|
|
|
octave = m_octaves - posY / p_height; |
|
|
|
n_pos = QPointF(pos.x(), posY % p_height); |
|
|
|
octave = fOctaves - posY / fHeight; |
|
|
|
keyPos = QPointF(pos.x(), posY % fHeight); |
|
|
|
} |
|
|
|
else |
|
|
|
return; |
|
|
|
|
|
|
|
octave += 3; |
|
|
|
|
|
|
|
if ((*m_midi_map)[1].contains(n_pos)) // C# |
|
|
|
if (fMidiMap[1].contains(keyPos)) // C# |
|
|
|
note = 1; |
|
|
|
else if ((*m_midi_map)[3].contains(n_pos)) // D# |
|
|
|
else if (fMidiMap[3].contains(keyPos)) // D# |
|
|
|
note = 3; |
|
|
|
else if ((*m_midi_map)[6].contains(n_pos)) // F# |
|
|
|
else if (fMidiMap[6].contains(keyPos)) // F# |
|
|
|
note = 6; |
|
|
|
else if ((*m_midi_map)[8].contains(n_pos)) // G# |
|
|
|
else if (fMidiMap[8].contains(keyPos)) // G# |
|
|
|
note = 8; |
|
|
|
else if ((*m_midi_map)[10].contains(n_pos))// A# |
|
|
|
else if (fMidiMap[10].contains(keyPos))// A# |
|
|
|
note = 10; |
|
|
|
else if ((*m_midi_map)[0].contains(n_pos)) // C |
|
|
|
else if (fMidiMap[0].contains(keyPos)) // C |
|
|
|
note = 0; |
|
|
|
else if ((*m_midi_map)[2].contains(n_pos)) // D |
|
|
|
else if (fMidiMap[2].contains(keyPos)) // D |
|
|
|
note = 2; |
|
|
|
else if ((*m_midi_map)[4].contains(n_pos)) // E |
|
|
|
else if (fMidiMap[4].contains(keyPos)) // E |
|
|
|
note = 4; |
|
|
|
else if ((*m_midi_map)[5].contains(n_pos)) // F |
|
|
|
else if (fMidiMap[5].contains(keyPos)) // F |
|
|
|
note = 5; |
|
|
|
else if ((*m_midi_map)[7].contains(n_pos)) // G |
|
|
|
else if (fMidiMap[7].contains(keyPos)) // G |
|
|
|
note = 7; |
|
|
|
else if ((*m_midi_map)[9].contains(n_pos)) // A |
|
|
|
else if (fMidiMap[9].contains(keyPos)) // A |
|
|
|
note = 9; |
|
|
|
else if ((*m_midi_map)[11].contains(n_pos))// B |
|
|
|
else if (fMidiMap[11].contains(keyPos))// B |
|
|
|
note = 11; |
|
|
|
else |
|
|
|
note = -1; |
|
|
@@ -276,16 +266,17 @@ void PixmapKeyboard::handleMousePos(const QPoint& pos) |
|
|
|
if (note != -1) |
|
|
|
{ |
|
|
|
note += octave * 12; |
|
|
|
if (m_lastMouseNote != note) |
|
|
|
|
|
|
|
if (fLastMouseNote != note) |
|
|
|
{ |
|
|
|
sendNoteOff(m_lastMouseNote); |
|
|
|
sendNoteOff(fLastMouseNote); |
|
|
|
sendNoteOn(note); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
sendNoteOff(m_lastMouseNote); |
|
|
|
else if (fLastMouseNote != -1) |
|
|
|
sendNoteOff(fLastMouseNote); |
|
|
|
|
|
|
|
m_lastMouseNote = note; |
|
|
|
fLastMouseNote = note; |
|
|
|
} |
|
|
|
|
|
|
|
void PixmapKeyboard::keyPressEvent(QKeyEvent* event) |
|
|
@@ -293,8 +284,9 @@ void PixmapKeyboard::keyPressEvent(QKeyEvent* event) |
|
|
|
if (! event->isAutoRepeat()) |
|
|
|
{ |
|
|
|
int qKey = event->key(); |
|
|
|
if (midi_keyboard2key_map.keys().contains(qKey)) |
|
|
|
sendNoteOn(midi_keyboard2key_map[qKey]); |
|
|
|
std::map<int, int>::const_iterator it = kMidiKeyboard2KeyMap.find(qKey); |
|
|
|
if (it != kMidiKeyboard2KeyMap.end()) |
|
|
|
sendNoteOn(it->second); |
|
|
|
} |
|
|
|
QWidget::keyPressEvent(event); |
|
|
|
} |
|
|
@@ -304,15 +296,16 @@ void PixmapKeyboard::keyReleaseEvent(QKeyEvent* event) |
|
|
|
if (! event->isAutoRepeat()) |
|
|
|
{ |
|
|
|
int qKey = event->key(); |
|
|
|
if (midi_keyboard2key_map.keys().contains(qKey)) |
|
|
|
sendNoteOff(midi_keyboard2key_map[qKey]); |
|
|
|
std::map<int, int>::const_iterator it = kMidiKeyboard2KeyMap.find(qKey); |
|
|
|
if (it != kMidiKeyboard2KeyMap.end()) |
|
|
|
sendNoteOff(it->second); |
|
|
|
} |
|
|
|
QWidget::keyReleaseEvent(event); |
|
|
|
} |
|
|
|
|
|
|
|
void PixmapKeyboard::mousePressEvent(QMouseEvent* event) |
|
|
|
{ |
|
|
|
m_lastMouseNote = -1; |
|
|
|
fLastMouseNote = -1; |
|
|
|
handleMousePos(event->pos()); |
|
|
|
setFocus(); |
|
|
|
QWidget::mousePressEvent(event); |
|
|
@@ -326,34 +319,35 @@ void PixmapKeyboard::mouseMoveEvent(QMouseEvent* event) |
|
|
|
|
|
|
|
void PixmapKeyboard::mouseReleaseEvent(QMouseEvent* event) |
|
|
|
{ |
|
|
|
if (m_lastMouseNote != -1) |
|
|
|
if (fLastMouseNote != -1) |
|
|
|
{ |
|
|
|
sendNoteOff(m_lastMouseNote); |
|
|
|
m_lastMouseNote = -1; |
|
|
|
sendNoteOff(fLastMouseNote); |
|
|
|
fLastMouseNote = -1; |
|
|
|
} |
|
|
|
QWidget::mouseReleaseEvent(event); |
|
|
|
} |
|
|
|
|
|
|
|
void PixmapKeyboard::paintEvent(QPaintEvent*) |
|
|
|
void PixmapKeyboard::paintEvent(QPaintEvent* event) |
|
|
|
{ |
|
|
|
QPainter painter(this); |
|
|
|
event->accept(); |
|
|
|
|
|
|
|
// ------------------------------------------------------------- |
|
|
|
// Paint clean keys (as background) |
|
|
|
|
|
|
|
for (int octave=0; octave < m_octaves; octave++) |
|
|
|
for (int octave=0; octave < fOctaves; octave++) |
|
|
|
{ |
|
|
|
QRectF target; |
|
|
|
|
|
|
|
if (m_pixmap_mode == HORIZONTAL) |
|
|
|
target = QRectF(p_width * octave, 0, p_width, p_height); |
|
|
|
else if (m_pixmap_mode == VERTICAL) |
|
|
|
target = QRectF(0, p_height * octave, p_width, p_height); |
|
|
|
if (fPixmapMode == HORIZONTAL) |
|
|
|
target = QRectF(fWidth * octave, 0, fWidth, fHeight); |
|
|
|
else if (fPixmapMode == VERTICAL) |
|
|
|
target = QRectF(0, fHeight * octave, fWidth, fHeight); |
|
|
|
else |
|
|
|
return; |
|
|
|
|
|
|
|
QRectF source = QRectF(0, 0, p_width, p_height); |
|
|
|
painter.drawPixmap(target, m_pixmap, source); |
|
|
|
QRectF source = QRectF(0, 0, fWidth, fHeight); |
|
|
|
painter.drawPixmap(target, fPixmap, source); |
|
|
|
} |
|
|
|
|
|
|
|
// ------------------------------------------------------------- |
|
|
@@ -361,10 +355,10 @@ void PixmapKeyboard::paintEvent(QPaintEvent*) |
|
|
|
|
|
|
|
bool paintedWhite = false; |
|
|
|
|
|
|
|
for (int i=0; i < m_enabledKeys.count(); i++) |
|
|
|
for (int i=0, count=fEnabledKeys.count(); i < count; i++) |
|
|
|
{ |
|
|
|
int octave, note = m_enabledKeys[i]; |
|
|
|
QRectF pos = _getRectFromMidiNote(note); |
|
|
|
int octave, note = fEnabledKeys[i]; |
|
|
|
const QRectF& pos(_getRectFromMidiNote(note)); |
|
|
|
|
|
|
|
if (_isNoteBlack(note)) |
|
|
|
continue; |
|
|
@@ -384,30 +378,34 @@ void PixmapKeyboard::paintEvent(QPaintEvent*) |
|
|
|
octave = 4; |
|
|
|
else if (note < 108) |
|
|
|
octave = 5; |
|
|
|
else if (note < 120) |
|
|
|
octave = 6; |
|
|
|
else if (note < 132) |
|
|
|
octave = 7; |
|
|
|
else |
|
|
|
// cannot paint this note either |
|
|
|
continue; |
|
|
|
|
|
|
|
if (m_pixmap_mode == VERTICAL) |
|
|
|
octave = m_octaves - octave - 1; |
|
|
|
if (fPixmapMode == VERTICAL) |
|
|
|
octave = fOctaves - octave - 1; |
|
|
|
|
|
|
|
QRectF target, source; |
|
|
|
|
|
|
|
if (m_pixmap_mode == HORIZONTAL) |
|
|
|
if (fPixmapMode == HORIZONTAL) |
|
|
|
{ |
|
|
|
target = QRectF(pos.x() + (p_width * octave), 0, pos.width(), pos.height()); |
|
|
|
source = QRectF(pos.x(), p_height, pos.width(), pos.height()); |
|
|
|
target = QRectF(pos.x() + (fWidth * octave), 0, pos.width(), pos.height()); |
|
|
|
source = QRectF(pos.x(), fHeight, pos.width(), pos.height()); |
|
|
|
} |
|
|
|
else if (m_pixmap_mode == VERTICAL) |
|
|
|
else if (fPixmapMode == VERTICAL) |
|
|
|
{ |
|
|
|
target = QRectF(pos.x(), pos.y() + (p_height * octave), pos.width(), pos.height()); |
|
|
|
source = QRectF(p_width, pos.y(), pos.width(), pos.height()); |
|
|
|
target = QRectF(pos.x(), pos.y() + (fHeight * octave), pos.width(), pos.height()); |
|
|
|
source = QRectF(fWidth, pos.y(), pos.width(), pos.height()); |
|
|
|
} |
|
|
|
else |
|
|
|
return; |
|
|
|
|
|
|
|
paintedWhite = true; |
|
|
|
painter.drawPixmap(target, m_pixmap, source); |
|
|
|
painter.drawPixmap(target, fPixmap, source); |
|
|
|
} |
|
|
|
|
|
|
|
// ------------------------------------------------------------- |
|
|
@@ -415,26 +413,27 @@ void PixmapKeyboard::paintEvent(QPaintEvent*) |
|
|
|
|
|
|
|
if (paintedWhite) |
|
|
|
{ |
|
|
|
for (int octave=0; octave < m_octaves; octave++) |
|
|
|
for (int octave=0; octave < fOctaves; octave++) |
|
|
|
{ |
|
|
|
foreach (int note, blackNotes) |
|
|
|
foreach (int note, kBlackNotes) |
|
|
|
{ |
|
|
|
QRectF target, source; |
|
|
|
QRectF pos = _getRectFromMidiNote(note); |
|
|
|
if (m_pixmap_mode == HORIZONTAL) |
|
|
|
const QRectF& pos(_getRectFromMidiNote(note)); |
|
|
|
|
|
|
|
if (fPixmapMode == HORIZONTAL) |
|
|
|
{ |
|
|
|
target = QRectF(pos.x() + (p_width * octave), 0, pos.width(), pos.height()); |
|
|
|
target = QRectF(pos.x() + (fWidth * octave), 0, pos.width(), pos.height()); |
|
|
|
source = QRectF(pos.x(), 0, pos.width(), pos.height()); |
|
|
|
} |
|
|
|
else if (m_pixmap_mode == VERTICAL) |
|
|
|
else if (fPixmapMode == VERTICAL) |
|
|
|
{ |
|
|
|
target = QRectF(pos.x(), pos.y() + (p_height * octave), pos.width(), pos.height()); |
|
|
|
target = QRectF(pos.x(), pos.y() + (fHeight * octave), pos.width(), pos.height()); |
|
|
|
source = QRectF(0, pos.y(), pos.width(), pos.height()); |
|
|
|
} |
|
|
|
else |
|
|
|
return; |
|
|
|
|
|
|
|
painter.drawPixmap(target, m_pixmap, source); |
|
|
|
painter.drawPixmap(target, fPixmap, source); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@@ -442,10 +441,10 @@ void PixmapKeyboard::paintEvent(QPaintEvent*) |
|
|
|
// ------------------------------------------------------------- |
|
|
|
// Paint (black) pressed keys |
|
|
|
|
|
|
|
for (int i=0; i < m_enabledKeys.count(); i++) |
|
|
|
for (int i=0, count=fEnabledKeys.count(); i < count; i++) |
|
|
|
{ |
|
|
|
int octave, note = m_enabledKeys[i]; |
|
|
|
QRectF pos = _getRectFromMidiNote(note); |
|
|
|
int octave, note = fEnabledKeys[i]; |
|
|
|
const QRectF& pos(_getRectFromMidiNote(note)); |
|
|
|
|
|
|
|
if (! _isNoteBlack(note)) |
|
|
|
continue; |
|
|
@@ -465,60 +464,64 @@ void PixmapKeyboard::paintEvent(QPaintEvent*) |
|
|
|
octave = 4; |
|
|
|
else if (note < 108) |
|
|
|
octave = 5; |
|
|
|
else if (note < 120) |
|
|
|
octave = 6; |
|
|
|
else if (note < 132) |
|
|
|
octave = 7; |
|
|
|
else |
|
|
|
// cannot paint this note either |
|
|
|
continue; |
|
|
|
|
|
|
|
if (m_pixmap_mode == VERTICAL) |
|
|
|
octave = m_octaves - octave - 1; |
|
|
|
if (fPixmapMode == VERTICAL) |
|
|
|
octave = fOctaves - octave - 1; |
|
|
|
|
|
|
|
QRectF target, source; |
|
|
|
|
|
|
|
if (m_pixmap_mode == HORIZONTAL) |
|
|
|
if (fPixmapMode == HORIZONTAL) |
|
|
|
{ |
|
|
|
target = QRectF(pos.x() + (p_width * octave), 0, pos.width(), pos.height()); |
|
|
|
source = QRectF(pos.x(), p_height, pos.width(), pos.height()); |
|
|
|
target = QRectF(pos.x() + (fWidth * octave), 0, pos.width(), pos.height()); |
|
|
|
source = QRectF(pos.x(), fHeight, pos.width(), pos.height()); |
|
|
|
} |
|
|
|
else if (m_pixmap_mode == VERTICAL) |
|
|
|
else if (fPixmapMode == VERTICAL) |
|
|
|
{ |
|
|
|
target = QRectF(pos.x(), pos.y() + (p_height * octave), pos.width(), pos.height()); |
|
|
|
source = QRectF(p_width, pos.y(), pos.width(), pos.height()); |
|
|
|
target = QRectF(pos.x(), pos.y() + (fHeight * octave), pos.width(), pos.height()); |
|
|
|
source = QRectF(fWidth, pos.y(), pos.width(), pos.height()); |
|
|
|
} |
|
|
|
else |
|
|
|
return; |
|
|
|
|
|
|
|
painter.drawPixmap(target, m_pixmap, source); |
|
|
|
painter.drawPixmap(target, fPixmap, source); |
|
|
|
} |
|
|
|
|
|
|
|
// Paint C-number note info |
|
|
|
painter.setFont(m_font); |
|
|
|
painter.setFont(fFont); |
|
|
|
painter.setPen(Qt::black); |
|
|
|
|
|
|
|
for (int i=0; i < m_octaves; i++) |
|
|
|
for (int i=0; i < fOctaves; i++) |
|
|
|
{ |
|
|
|
if (m_pixmap_mode == HORIZONTAL) |
|
|
|
if (fPixmapMode == HORIZONTAL) |
|
|
|
painter.drawText(i * 144, 48, 18, 18, Qt::AlignCenter, QString("C%1").arg(i + 2)); |
|
|
|
else if (m_pixmap_mode == VERTICAL) |
|
|
|
painter.drawText(45, (m_octaves * 144) - (i * 144) - 16, 18, 18, Qt::AlignCenter, QString("C%1").arg(i + 2)); |
|
|
|
else if (fPixmapMode == VERTICAL) |
|
|
|
painter.drawText(45, (fOctaves * 144) - (i * 144) - 16, 18, 18, Qt::AlignCenter, QString("C%1").arg(i + 2)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void PixmapKeyboard::updateOnce() |
|
|
|
{ |
|
|
|
if (m_needsUpdate) |
|
|
|
if (fNeedsUpdate) |
|
|
|
{ |
|
|
|
update(); |
|
|
|
m_needsUpdate = false; |
|
|
|
fNeedsUpdate = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
bool PixmapKeyboard::_isNoteBlack(int note) |
|
|
|
bool PixmapKeyboard::_isNoteBlack(int note) const |
|
|
|
{ |
|
|
|
int baseNote = note % 12; |
|
|
|
return blackNotes.contains(baseNote); |
|
|
|
return kBlackNotes.contains(baseNote); |
|
|
|
} |
|
|
|
|
|
|
|
QRectF PixmapKeyboard::_getRectFromMidiNote(int note) |
|
|
|
const QRectF& PixmapKeyboard::_getRectFromMidiNote(int note) const |
|
|
|
{ |
|
|
|
return (*m_midi_map)[note % 12]; |
|
|
|
return fMidiMap[note % 12]; |
|
|
|
} |