diff --git a/src/libs/core/CMakeLists.txt b/src/libs/core/CMakeLists.txt index 17521e43be19adf2ad3326110787777b8f3991aa..b496a3d4abfbc31e4183f46e9405a993d4aba845 100644 --- a/src/libs/core/CMakeLists.txt +++ b/src/libs/core/CMakeLists.txt @@ -37,6 +37,8 @@ set(LIB_NOOTKACORE_SRC score/tnoteobject.cpp score/tnotepair.cpp + instruments/tguitarbg.cpp + # exam/tqatype.cpp # exam/tqaunit.cpp # exam/tqagroup.cpp diff --git a/src/libs/score/declarative/checktime.h b/src/libs/core/checktime.h similarity index 100% rename from src/libs/score/declarative/checktime.h rename to src/libs/core/checktime.h diff --git a/src/libs/core/instruments/tguitarbg.cpp b/src/libs/core/instruments/tguitarbg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..517c6870b4024b738eb59bdfb58041bbe8c7e95d --- /dev/null +++ b/src/libs/core/instruments/tguitarbg.cpp @@ -0,0 +1,156 @@ +/*************************************************************************** + * Copyright (C) 2017 by Tomasz Bojczuk * + * seelook@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 <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "tguitarbg.h" +#include "tglobals.h" +#include "music/ttune.h" +#include "tpath.h" + +#include <QtGui/qguiapplication.h> +#include <QtGui/qpainter.h> +#include <QtGui/qpalette.h> +#include <QtCore/qdebug.h> + + +TguitarBg::TguitarBg(QQuickItem* parent) : + QQuickPaintedItem(parent) +{ + setRenderTarget(QQuickPaintedItem::FramebufferObject); + // setPerformanceHint(QQuickPaintedItem::FastFBOResizing); + setAntialiasing(true); +} + + +#include <QtCore/qelapsedtimer.h> +QElapsedTimer elti; +void TguitarBg::paint(QPainter* painter) { + elti.restart(); + +// painter->setRenderHint(QPainter::Antialiasing, true); +// painter->setRenderHint(QPainter::TextAntialiasing, true); +// painter->fillRect(painter->viewport(), qApp->palette().window().color()); + +// FINGERBOARD + painter->setPen(QPen(Qt::black, 0, Qt::NoPen)); + if (GLOB->instrument == e_classicalGuitar) + painter->setBrush(QBrush(Qt::black, Qt::SolidPattern)); + else { + QColor fbEdgeColor = QColor("#AFA072"); + fbEdgeColor.setAlpha(220); + painter->setBrush(QBrush(fbEdgeColor, Qt::SolidPattern)); + } + QPolygon a; + int fbThick = ((m_strGap * GLOB->Gtune()->stringNr()) / 6) / 4; // thickness of fretboard + a.setPoints(6, m_fbRect.x(), m_fbRect.y(), + m_fbRect.x() + qRound(m_fbRect.width() * 0.005), m_fbRect.y() - fbThick, + m_fbRect.x() + m_fbRect.width() + fbThick, m_fbRect.y() - fbThick, + m_fbRect.x() + m_fbRect.width() + fbThick, height() - fbThick, + m_fbRect.x() + m_fbRect.width(), height(), + m_fbRect.x(), height()); + painter->drawPolygon(a); + if (GLOB->instrument == e_classicalGuitar) + painter->setBrush(QBrush(QPixmap(Tpath::img("fingbg")))); + else + painter->setBrush(QBrush(QPixmap(Tpath::img("fingbg-el")))); + painter->drawRect(m_fbRect); +// FRETS + // zero fret (upper bridge or HUESO) + int huesoW = qRound(m_fbRect.width() * 0.01); + if (GLOB->instrument == e_classicalGuitar) { + painter->setPen(Qt::NoPen); + painter->setBrush(QBrush(QColor("#FFFBF0"),Qt::SolidPattern)); // #FFFBF0 cream color for hueso + painter->drawRect(m_fbRect.x() - 8, m_fbRect.y() + 4, huesoW, m_fbRect.height()); + a.setPoints(4, m_fbRect.x() - 8, m_fbRect.y() + 4, + m_fbRect.x() - 8 + huesoW, m_fbRect.y() + 4, + m_fbRect.x() + m_strGap / 3 - 8 + huesoW, m_fbRect.y() - m_strGap / 3, + m_fbRect.x() + m_strGap / 3 - 8, m_fbRect.y() - m_strGap / 3); + painter->setBrush(QBrush(QColor("#FFEEBC"),Qt::SolidPattern)); // a bit darker for its rant + painter->drawPolygon(a); + } else { + QLinearGradient fretGrad(m_fbRect.x() - 8, 10.0, m_fbRect.x() - 8 + huesoW, 10.0); + fretGrad.setColorAt(0.0, QColor("#DAE4E4")); + fretGrad.setColorAt(0.4, QColor("#7F806E")); + fretGrad.setColorAt(0.7, QColor("#3B382B")); + fretGrad.setColorAt(0.9, QColor("#000000")); + painter->setBrush(fretGrad); + painter->drawRoundedRect(m_fbRect.x() - 8, m_fbRect.y() + 2, huesoW, m_fbRect.height() - 4, 2, 2); + } + // others frets + qint8 fretMarks[GLOB->GfretsNumber]; // array keeps whether fret is marked with dots (1) or two (2) + for (int i = 0; i < GLOB->GfretsNumber; ++i) + fretMarks[i] = 0; + for (int fr = 0; fr < GLOB->GmarkedFrets.size(); ++fr) { + QString exMark, frTxt = GLOB->GmarkedFrets[fr].toString(); + if (frTxt.contains(QLatin1String("!"))) { + exMark = QStringLiteral("!"); + frTxt.replace(QLatin1String("!"), QString()); + } + bool ok; + int frNr = frTxt.toInt(&ok); + if (ok && frNr > 0 && frNr <= GLOB->GfretsNumber) { + if (exMark.isEmpty()) + fretMarks[frNr - 1] = 1; + else + fretMarks[frNr - 1] = 2; + } + } + for (int i = 0; i < GLOB->GfretsNumber; i++) { + QLinearGradient fretGrad(0.0, 0.0, 1.0, 0.0); + fretGrad.setCoordinateMode(QGradient::ObjectBoundingMode); + fretGrad.setColorAt(0.0, QColor("#DAE4E4")); + fretGrad.setColorAt(0.4, QColor("#7F806E")); + fretGrad.setColorAt(0.7, QColor("#3B382B")); + fretGrad.setColorAt(0.9, QColor("#000000")); + painter->setBrush(fretGrad); + painter->drawRoundedRect(m_fretsPos[i], m_fbRect.y() + 2, m_fbRect.width() * 0.0085, m_fbRect.height() - 4, 2, 2); + + if (fretMarks[i]) { + int markW = m_strGap / 3; + painter->setBrush(QBrush(Qt::white, Qt::SolidPattern)); //white color for circles marking 5, 7, 9... frets + if (fretMarks[i] == 1) + painter->drawEllipse(m_fretsPos[i] - markW / 2 - (m_fretsPos[i] - m_fretsPos[i - 1]) / 2, + m_fbRect.y() + m_strGap * int((GLOB->Gtune()->stringNr() / 2)) - markW / 2, markW, markW); + else { + painter->drawEllipse(m_fretsPos[i - 1] + 2 + ((m_fretsPos[i] - m_fretsPos[i - 1]) - 2 * markW) / 3, + m_fbRect.y() + m_strGap * int((GLOB->Gtune()->stringNr() / 2)) - markW / 2, markW, markW); + painter->drawEllipse(m_fretsPos[i - 1] + 2 + (((m_fretsPos[i] - m_fretsPos[i - 1]) - 2 * markW) / 3) * 2 + markW, + m_fbRect.y() + m_strGap * int((GLOB->Gtune()->stringNr() / 2)) - markW / 2, markW, markW); + } + } + } + + qDebug() << "[TguitarBg] painting time" << elti.nsecsElapsed() / 1000 << "[μs]"; +} + +void TguitarBg::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) { + if (oldGeometry.width() != newGeometry.width() || oldGeometry.height() != newGeometry.height()) { + QSize newSize = newGeometry.size().toSize(); + m_fbRect = QRect(10, newSize.height() / 18, (6 * newSize.width()) / 7, newSize.height() - newSize.height() / 18); + m_fretWidth = ((m_fbRect.width() + ((GLOB->GfretsNumber / 2) * (GLOB->GfretsNumber / 2 + 1)) + + GLOB->GfretsNumber / 4) / (GLOB->GfretsNumber+1)) + 1; + m_strGap = m_fbRect.height() / GLOB->Gtune()->stringNr(); + m_fretsPos[0] = m_fbRect.x() + m_fretWidth; + for (int i = 2; i < GLOB->GfretsNumber + 1; i++) + m_fretsPos[i - 1] = m_fretsPos[i - 2] + (m_fretWidth - (i / 2)); + m_lastFret = m_fretsPos[GLOB->GfretsNumber - 1]; + if (m_lastFret > (m_fbRect.width() + 10)) + m_fbRect.setWidth(m_lastFret - 8); + + update(); + } +} diff --git a/src/libs/core/instruments/tguitarbg.h b/src/libs/core/instruments/tguitarbg.h new file mode 100644 index 0000000000000000000000000000000000000000..0f3244f8aa29796c2e819ea7a996687dcb245623 --- /dev/null +++ b/src/libs/core/instruments/tguitarbg.h @@ -0,0 +1,57 @@ +/*************************************************************************** + * Copyright (C) 2017 by Tomasz Bojczuk * + * seelook@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 <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef TGUITARBG_H +#define TGUITARBG_H + + +#include "nootkacoreglobal.h" +#include <QtQuick/qquickpainteditem.h> + + +/** + * This is static background of guitar QML component. + * It re-paints its content only when size changes (user scales main window) + */ +class NOOTKACORE_EXPORT TguitarBg : public QQuickPaintedItem +{ + Q_OBJECT + +public: + TguitarBg(QQuickItem* parent = nullptr); + + virtual void paint(QPainter* painter); + + /** + * Guitar fingerboard rectangle + */ + QRect fbRect() { return m_fbRect; } + +protected: + virtual void geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry); + +private: + QRect m_fbRect; /**< Represents top left positions and size of a fingerboard */ + int m_strGap; /**< Distance between strings */ + int m_fretWidth; /**< Average width of fret */ + int m_lastFret; /**< Position of the last fret (in whole widget coordinates) */ + int m_fretsPos[24]; /**< @p fretsPos stores X positions of frets in global widget coordinates */ + +}; + +#endif // TGUITARBG_H diff --git a/src/libs/core/tnootkaqml.cpp b/src/libs/core/tnootkaqml.cpp index 043d280b698bf3d230958f4ae632fcc7d9950076..74f7e25e1c4f3f50c343f537cfb33e024c5e27e3 100644 --- a/src/libs/core/tnootkaqml.cpp +++ b/src/libs/core/tnootkaqml.cpp @@ -25,6 +25,8 @@ #include "music/tkeysignature.h" #include "score/tscoreobject.h" #include "score/tstaffobject.h" +#include "instruments/tguitarbg.h" + #include <QtQml/qqmlengine.h> #include <QtCore/qfile.h> #include <QtCore/qdir.h> @@ -53,6 +55,8 @@ TnootkaQML::TnootkaQML(QObject* parent) : qmlRegisterType<TstaffObject>("Score", 1, 0, "TstaffObject"); qmlRegisterType<TtickColors>("TtickColors", 1, 0, "TtickColors"); + + qmlRegisterType<TguitarBg>("Instruments", 1, 0, "GuitarBackground"); } diff --git a/src/nootka.qrc b/src/nootka.qrc index 52189790b1f8e7096843429ace06e33c74501787..275edbb5296533533d0660e5b5c83a8a663f1f51 100644 --- a/src/nootka.qrc +++ b/src/nootka.qrc @@ -18,6 +18,9 @@ <file alias="KeySignature.qml">qml/score/KeySignature.qml</file> <file alias="Meter.qml">qml/score/Meter.qml</file> + <file alias="Instrument.qml">qml/instruments/Instrument.qml</file> + <file alias="Guitar.qml">qml/instruments/Guitar.qml</file> + <file alias="TaboutNootka.qml">qml/about/TaboutNootka.qml</file> <file alias="AboutPage.qml">qml/about/AboutPage.qml</file> <file alias="HelpPage.qml">qml/about/HelpPage.qml</file> diff --git a/src/qml/MainWindow.qml b/src/qml/MainWindow.qml index a0ac946aa1e0cdeb105ac31aec0fb38519794426..a15b6239b74b45013ea1515d603be5db049834b2 100644 --- a/src/qml/MainWindow.qml +++ b/src/qml/MainWindow.qml @@ -18,7 +18,6 @@ import QtQuick 2.7 import QtQuick.Controls 2.0 -import QtQuick.Layouts 1.3 import QtQuick.Window 2.0 @@ -54,7 +53,7 @@ ApplicationWindow { } } - ColumnLayout { + Column { anchors.fill: parent Row { @@ -79,8 +78,8 @@ ApplicationWindow { Score { id: score - Layout.fillWidth: true - Layout.fillHeight: true + width: parent.width + height: parent.height - header.height - instrument.height Component.onCompleted: { for (var n = 1; n < 8; ++n) { addNote(Noo.note(1 + Math.random() * 7, -2 + Math.random() * 5, Math.min(Math.max(-2, -3 + Math.random() * 6), 2), @@ -89,8 +88,12 @@ ApplicationWindow { } } - // space for an instrument - Rectangle { height: nootkaWindow.height / 4; Layout.fillWidth: true; color: activPal.window; border { width: 1; color: activPal.text } } + Instrument { + id: instrument + height: nootkaWindow.height / 4 + width: parent.width + + } } // Timer { diff --git a/src/qml/instruments/Guitar.qml b/src/qml/instruments/Guitar.qml new file mode 100644 index 0000000000000000000000000000000000000000..3ed90ad3a009a1120e2c00c62681bf447a76e576 --- /dev/null +++ b/src/qml/instruments/Guitar.qml @@ -0,0 +1,26 @@ +/*************************************************************************** + * Copyright (C) 2017 by Tomasz Bojczuk * + * seelook@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 <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +import QtQuick 2.7 + +import Instruments 1.0 + + +GuitarBackground { + +} diff --git a/src/qml/instruments/Instrument.qml b/src/qml/instruments/Instrument.qml new file mode 100644 index 0000000000000000000000000000000000000000..8356a9cd84449e86ba2b23a7dee4275a1a574029 --- /dev/null +++ b/src/qml/instruments/Instrument.qml @@ -0,0 +1,26 @@ +/*************************************************************************** + * Copyright (C) 2017 by Tomasz Bojczuk * + * seelook@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 <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +import QtQuick 2.7 + +Item { + + Guitar { + anchors.fill: parent + } +}