From b2ea6ab22a1ca46b1d036e459bb0f35a373fb167 Mon Sep 17 00:00:00 2001 From: Chris Cochrun Date: Thu, 24 Feb 2022 15:20:56 -0600 Subject: [PATCH] Song editor is functional and library adds new songs --- src/qml/presenter/Library.qml | 69 ++++++++++++++-- src/qml/presenter/MainWindow.qml | 23 +++++- src/qml/presenter/SlideEditor.qml | 1 + src/qml/presenter/SongEditor.qml | 28 +++++-- src/songsqlmodel.cpp | 129 +++++++++++++++++++++++++++--- src/songsqlmodel.h | 19 ++++- 6 files changed, 240 insertions(+), 29 deletions(-) diff --git a/src/qml/presenter/Library.qml b/src/qml/presenter/Library.qml index bdf943d..0297a4b 100644 --- a/src/qml/presenter/Library.qml +++ b/src/qml/presenter/Library.qml @@ -103,9 +103,43 @@ Item { } } + header: Component { + Kirigami.ActionToolBar { + height: selectedLibrary == "songs" ? 40 : 0 + width: parent.width + display: IconOnly + actions: [ + Kirigami.Action { + icon.name: "document-new" + text: "New Song" + tooltip: "Add a new song" + onTriggered: songLibraryList.newSong() + }, + + Kirigami.Action { + displayComponent: Component { + Kirigami.SearchField { + id: searchField + width: parent.width - 40 + onAccepted: showPassiveNotification(searchField.text, 3000) + } + } + } + ] + + Behavior on height { + NumberAnimation { + easing.type: Easing.OutCubic + duration: 300 + } + } + } + } + + headerPositioning: ListView.OverlayHeader + Component { id: songDelegate - Kirigami.BasicListItem { id: songListItem implicitWidth: ListView.view.width @@ -114,6 +148,15 @@ Item { label: title subtitle: author hoverEnabled: true + ListView.onAdd: { + showPassiveNotification(title, 3000) + songLibraryList.currentIndex = index + song = index + songTitle = title + songLyrics = lyrics + songAuthor = author + songVorder = vorder + } Behavior on height { NumberAnimation { @@ -124,6 +167,7 @@ Item { MouseArea { id: dragHandler anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton /* width: parent.width */ /* height: parent.height */ /* Layout.alignment: Qt.AlignTop */ @@ -139,12 +183,17 @@ Item { } } onClicked: { - showPassiveNotification(title, 3000) - songLibraryList.currentIndex = index - song = index - songTitle = title - songLyrics = lyrics - songAuthor = author + if(mouse.button == Qt.RightButton) + showPassiveNotification("Delete me!"); + else{ + showPassiveNotification(title, 3000) + songLibraryList.currentIndex = index + song = index + songTitle = title + songLyrics = lyrics + songAuthor = author + songVorder = vorder + } } } @@ -176,6 +225,12 @@ Item { anchors.leftMargin: 10 active: hovered || pressed } + + function newSong() { + songsqlmodel.newSong(); + songLibraryList.currentIndex = songsqlmodel.rowCount(); + showPassiveNotification("newest song index: " + songLibraryList.currentIndex) + } } Rectangle { diff --git a/src/qml/presenter/MainWindow.qml b/src/qml/presenter/MainWindow.qml index c3a7b07..f320b9c 100644 --- a/src/qml/presenter/MainWindow.qml +++ b/src/qml/presenter/MainWindow.qml @@ -17,6 +17,7 @@ Controls.Page { property string songTitle: "" property string songLyrics: "" property string songAuthor: "" + property string songVorder: "" property int blurRadius: 0 property Item slideItem @@ -145,10 +146,26 @@ Controls.Page { } function updateLyrics(lyrics) { - showPassiveNotification("song id " + song); + songsqlmodel.updateLyrics(song, lyrics); + } - songsqlmodel.setLyrics(song, lyrics); + function updateTitle(title) { + songsqlmodel.updateTitle(song, title) + } - showPassiveNotification("did we do it?"); + function updateAuthor(author) { + songsqlmodel.updateAuthor(song, author) + } + + function updateAudio(audio) { + songsqlmodel.updateAudio(song, audio) + } + + function updateCcli(ccli) { + songsqlmodel.updateCcli(song, ccli) + } + + function updateVerseOrder(vorder) { + songsqlmodel.updateVerseOrder(song, vorder) } } diff --git a/src/qml/presenter/SlideEditor.qml b/src/qml/presenter/SlideEditor.qml index c44b057..a044d91 100644 --- a/src/qml/presenter/SlideEditor.qml +++ b/src/qml/presenter/SlideEditor.qml @@ -13,6 +13,7 @@ Item { Presenter.Slide { id: representation + textSize: 48 editMode: true } } diff --git a/src/qml/presenter/SongEditor.qml b/src/qml/presenter/SongEditor.qml index 6ca842d..088dab3 100644 --- a/src/qml/presenter/SongEditor.qml +++ b/src/qml/presenter/SongEditor.qml @@ -113,6 +113,20 @@ Item { placeholderText: "Song Title..." text: songTitle padding: 10 + onEditingFinished: updateTitle(text); + } + Controls.TextField { + id: songVorderField + + Layout.preferredWidth: 300 + Layout.fillWidth: true + Layout.leftMargin: 20 + Layout.rightMargin: 20 + + placeholderText: "verse order..." + text: songVorder + padding: 10 + onEditingFinished: updateVerseOrder(text); } Controls.ScrollView { @@ -126,15 +140,18 @@ Item { rightPadding: 20 Controls.TextArea { + id: lyricsEditor width: parent.width - placeholderText: "Put lyrics here..." persistentSelection: true text: songLyrics textFormat: TextEdit.MarkdownText padding: 10 - onEditingFinished: mainPage.updateLyrics(text) - /* onPressed: editorTimer.running = true */ + onEditingFinished: { + updateLyrics(text); + editorTimer.running = false; + } + onPressed: editorTimer.running = true } } Controls.TextField { @@ -148,6 +165,7 @@ Item { placeholderText: "Author..." text: songAuthor padding: 10 + onEditingFinished: updateAuthor(text) } } @@ -182,9 +200,9 @@ Item { } Timer { id: editorTimer - interval: 2000 + interval: 1000 repeat: true running: false - onTriggered: showPassiveNotification("updating song...") + onTriggered: updateLyrics(lyricsEditor.text) } } diff --git a/src/songsqlmodel.cpp b/src/songsqlmodel.cpp index d109480..91a6f5d 100644 --- a/src/songsqlmodel.cpp +++ b/src/songsqlmodel.cpp @@ -22,27 +22,34 @@ static void createTable() QSqlQuery query; if (!query.exec("CREATE TABLE IF NOT EXISTS 'songs' (" + " 'id' INT NOT NULL," " 'title' TEXT NOT NULL," " 'lyrics' TEXT," " 'author' TEXT," " 'ccli' TEXT," " 'audio' TEXT," - " PRIMARY KEY(title))")) { + " 'vorder' TEXT," + " PRIMARY KEY(id))")) { qFatal("Failed to query database: %s", qPrintable(query.lastError().text())); } + qDebug() << query.lastQuery(); + qDebug() << "inserting into songs"; - query.exec("INSERT INTO songs VALUES ('10,000 Reasons', '10,000 reasons for my heart to sing', 'Matt Redman', '13470183', '')"); - query.exec("INSERT INTO songs VALUES ('River', 'Im going down to the river', 'Jordan Feliz', '13470183', '')"); - query.exec("INSERT INTO songs VALUES ('Marvelous Light', 'Into marvelous light Im running', 'Chris Tomlin', '13470183', '')"); + query.exec("INSERT INTO songs VALUES (1, '10,000 Reasons', '10,000 reasons for my heart to sing', 'Matt Redman', '13470183', '', '')"); + qDebug() << query.lastQuery(); + query.exec("INSERT INTO songs VALUES (2, 'River', 'Im going down to the river', 'Jordan Feliz', '13470183', '', '')"); + query.exec("INSERT INTO songs VALUES (3, 'Marvelous Light', 'Into marvelous " + "light Im running', 'Chris Tomlin', '13470183', '', '')"); - // query.exec("select * from songs"); - // qDebug() << query.lastQuery(); + query.exec("select * from songs"); + qDebug() << query.lastQuery(); } SongSqlModel::SongSqlModel(QObject *parent) : QSqlTableModel(parent) { + qDebug() << "creating table"; createTable(); setTable(songsTableName); setEditStrategy(QSqlTableModel::OnFieldChange); @@ -64,14 +71,38 @@ QVariant SongSqlModel::data(const QModelIndex &index, int role) const { QHash SongSqlModel::roleNames() const { QHash names; - names[Qt::UserRole] = "title"; - names[Qt::UserRole + 1] = "lyrics"; - names[Qt::UserRole + 2] = "author"; - names[Qt::UserRole + 3] = "ccli"; - names[Qt::UserRole + 4] = "audio"; + names[Qt::UserRole] = "id"; + names[Qt::UserRole + 1] = "title"; + names[Qt::UserRole + 2] = "lyrics"; + names[Qt::UserRole + 3] = "author"; + names[Qt::UserRole + 4] = "ccli"; + names[Qt::UserRole + 5] = "audio"; + names[Qt::UserRole + 6] = "vorder"; return names; } +void SongSqlModel::newSong() { + qDebug() << "starting to add new song"; + int rows = rowCount(); + + qDebug() << rows; + QSqlRecord recorddata = record(rows); + recorddata.setValue("id", rows + 1); + recorddata.setValue("title", "new song"); + qDebug() << recorddata; + + if (insertRecord(rows, recorddata)) { + submitAll(); + select(); + }else { + qDebug() << lastError(); + } +} + +int SongSqlModel::id() const { + return m_id; +} + QString SongSqlModel::title() const { return m_title; } @@ -86,6 +117,18 @@ void SongSqlModel::setTitle(const QString &title) { emit titleChanged(); } +// This function is for updating the lyrics from outside the delegate +void SongSqlModel::updateTitle(const int &row, const QString &title) { + qDebug() << "Row is " << row; + QSqlRecord rowdata = record(row); + rowdata.setValue("title", title); + setRecord(row, rowdata); + submitAll(); + + select(); + emit titleChanged(); +} + QString SongSqlModel::author() const { return m_author; } @@ -100,6 +143,18 @@ void SongSqlModel::setAuthor(const QString &author) { emit authorChanged(); } +// This function is for updating the lyrics from outside the delegate +void SongSqlModel::updateAuthor(const int &row, const QString &author) { + qDebug() << "Row is " << row; + QSqlRecord rowdata = record(row); + rowdata.setValue("author", author); + setRecord(row, rowdata); + submitAll(); + + select(); + emit authorChanged(); +} + QString SongSqlModel::lyrics() const { return m_lyrics; } @@ -114,7 +169,8 @@ void SongSqlModel::setLyrics(const QString &lyrics) { emit lyricsChanged(); } -void SongSqlModel::setLyrics(const int &row, const QString &lyrics) { +// This function is for updating the lyrics from outside the delegate +void SongSqlModel::updateLyrics(const int &row, const QString &lyrics) { qDebug() << "Row is " << row; QSqlRecord rowdata = record(row); rowdata.setValue("lyrics", lyrics); @@ -123,7 +179,6 @@ void SongSqlModel::setLyrics(const int &row, const QString &lyrics) { select(); emit lyricsChanged(); - } QString SongSqlModel::ccli() const { @@ -140,6 +195,18 @@ void SongSqlModel::setCcli(const QString &ccli) { emit ccliChanged(); } +// This function is for updating the lyrics from outside the delegate +void SongSqlModel::updateCcli(const int &row, const QString &ccli) { + qDebug() << "Row is " << row; + QSqlRecord rowdata = record(row); + rowdata.setValue("ccli", ccli); + setRecord(row, rowdata); + submitAll(); + + select(); + emit ccliChanged(); +} + QString SongSqlModel::audio() const { return m_audio; } @@ -153,3 +220,39 @@ void SongSqlModel::setAudio(const QString &audio) { select(); emit audioChanged(); } + +// This function is for updating the lyrics from outside the delegate +void SongSqlModel::updateAudio(const int &row, const QString &audio) { + qDebug() << "Row is " << row; + QSqlRecord rowdata = record(row); + rowdata.setValue("audio", audio); + setRecord(row, rowdata); + submitAll(); + + select(); + emit audioChanged(); +} + +QString SongSqlModel::vorder() const { return m_vorder; } + +void SongSqlModel::setVerseOrder(const QString &vorder) { + if (vorder == m_vorder) + return; + + m_vorder = vorder; + + select(); + emit vorderChanged(); +} + +// This function is for updating the lyrics from outside the delegate +void SongSqlModel::updateVerseOrder(const int &row, const QString &vorder) { + qDebug() << "Row is " << row; + QSqlRecord rowdata = record(row); + rowdata.setValue("vorder", vorder); + setRecord(row, rowdata); + submitAll(); + + select(); + emit vorderChanged(); +} diff --git a/src/songsqlmodel.h b/src/songsqlmodel.h index 82d1c6b..b7d2d99 100644 --- a/src/songsqlmodel.h +++ b/src/songsqlmodel.h @@ -3,34 +3,48 @@ #include #include +#include #include #include class SongSqlModel : public QSqlTableModel { Q_OBJECT + Q_PROPERTY(int id READ id) Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) Q_PROPERTY(QString lyrics READ lyrics WRITE setLyrics NOTIFY lyricsChanged) Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged) Q_PROPERTY(QString ccli READ ccli WRITE setCcli NOTIFY ccliChanged) Q_PROPERTY(QString audio READ audio WRITE setAudio NOTIFY audioChanged) + Q_PROPERTY(QString vorder READ vorder WRITE setVerseOrder NOTIFY vorderChanged) QML_ELEMENT public: SongSqlModel(QObject *parent = 0); + int id() const; QString title() const; QString lyrics() const; QString author() const; QString ccli() const; QString audio() const; + QString vorder() const; void setTitle(const QString &title); void setLyrics(const QString &lyrics); - void setLyrics(const int &row, const QString &lyrics); void setAuthor(const QString &author); void setCcli(const QString &ccli); void setAudio(const QString &audio); + void setVerseOrder(const QString &vorder); + + Q_INVOKABLE void updateTitle(const int &row, const QString &title); + Q_INVOKABLE void updateLyrics(const int &row, const QString &lyrics); + Q_INVOKABLE void updateAuthor(const int &row, const QString &author); + Q_INVOKABLE void updateCcli(const int &row, const QString &ccli); + Q_INVOKABLE void updateAudio(const int &row, const QString &audio); + Q_INVOKABLE void updateVerseOrder(const int &row, const QString &vorder); + + Q_INVOKABLE void newSong(); QVariant data(const QModelIndex &index, int role) const override; QHash roleNames() const override; @@ -41,13 +55,16 @@ signals: void authorChanged(); void ccliChanged(); void audioChanged(); + void vorderChanged(); private: + int m_id; QString m_title; QString m_lyrics; QString m_author; QString m_ccli; QString m_audio; + QString m_vorder; }; #endif //SONGSQLMODEL_H