basic imagemodel and editor
This commit is contained in:
parent
09b6370153
commit
0cee5db60d
11 changed files with 432 additions and 102 deletions
14
TODO.org
14
TODO.org
|
@ -4,12 +4,8 @@
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
* Inbox
|
* Inbox
|
||||||
** TODO BUG in dropping and then selecting song will duplicate entries :dev:
|
** TODO Make an image sql model
|
||||||
SCHEDULED: <2022-04-05 Tue>
|
[[file:~/dev/church-presenter/src/videosqlmodel.h::ifndef VIDEOSQLMODEL_H]]
|
||||||
[[file:~/dev/church-presenter/src/qml/presenter/LeftDock.qml::Layout.fillHeight: true]]
|
|
||||||
|
|
||||||
or at least turns the entry above it into the same as itself while retaining it's title?
|
|
||||||
|
|
||||||
** TODO Build out a slide preview system so we can see each slide in the song or image slideshow
|
** TODO Build out a slide preview system so we can see each slide in the song or image slideshow
|
||||||
[[file:~/dev/church-presenter/src/qml/presenter/SongEditor.qml::Presenter.SlideEditor {]]
|
[[file:~/dev/church-presenter/src/qml/presenter/SongEditor.qml::Presenter.SlideEditor {]]
|
||||||
|
|
||||||
|
@ -53,6 +49,12 @@ or at least turns the entry above it into the same as itself while retaining it'
|
||||||
** DONE Parse Lyrics to create a list of strings for slides
|
** DONE Parse Lyrics to create a list of strings for slides
|
||||||
SCHEDULED: <2022-03-23 Wed 10:00>
|
SCHEDULED: <2022-03-23 Wed 10:00>
|
||||||
|
|
||||||
|
** DONE BUG in dropping and then selecting song will duplicate entries :dev:
|
||||||
|
SCHEDULED: <2022-04-05 Tue>
|
||||||
|
[[file:~/dev/church-presenter/src/qml/presenter/LeftDock.qml::Layout.fillHeight: true]]
|
||||||
|
|
||||||
|
or at least turns the entry above it into the same as itself while retaining it's title?
|
||||||
|
|
||||||
** DONE Make nextSlideText a nextAction function to incorporate other types of items
|
** DONE Make nextSlideText a nextAction function to incorporate other types of items
|
||||||
[[file:~/dev/church-presenter/src/qml/presenter/Presentation.qml::function nextSlideText() {]]
|
[[file:~/dev/church-presenter/src/qml/presenter/Presentation.qml::function nextSlideText() {]]
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ target_sources(presenter
|
||||||
serviceitemmodel.cpp serviceitemmodel.h
|
serviceitemmodel.cpp serviceitemmodel.h
|
||||||
serviceitem.cpp serviceitem.h
|
serviceitem.cpp serviceitem.h
|
||||||
videosqlmodel.cpp videosqlmodel.h
|
videosqlmodel.cpp videosqlmodel.h
|
||||||
|
imagesqlmodel.cpp imagesqlmodel.h
|
||||||
mpv/mpvobject.h mpv/mpvobject.cpp
|
mpv/mpvobject.h mpv/mpvobject.cpp
|
||||||
mpv/qthelper.hpp mpv/mpvhelpers.h
|
mpv/qthelper.hpp mpv/mpvhelpers.h
|
||||||
)
|
)
|
||||||
|
|
169
src/imagesqlmodel.cpp
Normal file
169
src/imagesqlmodel.cpp
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
#include "imagesqlmodel.h"
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QSqlError>
|
||||||
|
#include <QSqlRecord>
|
||||||
|
#include <QSqlQuery>
|
||||||
|
#include <QSql>
|
||||||
|
#include <QSqlDatabase>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <qabstractitemmodel.h>
|
||||||
|
#include <qdebug.h>
|
||||||
|
#include <qnamespace.h>
|
||||||
|
#include <qobject.h>
|
||||||
|
#include <qobjectdefs.h>
|
||||||
|
#include <qsqlrecord.h>
|
||||||
|
#include <qurl.h>
|
||||||
|
#include <qvariant.h>
|
||||||
|
|
||||||
|
static const char *imagesTableName = "images";
|
||||||
|
|
||||||
|
static void createImageTable()
|
||||||
|
{
|
||||||
|
if(QSqlDatabase::database().tables().contains(imagesTableName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery query;
|
||||||
|
if (!query.exec("CREATE TABLE IF NOT EXISTS 'images' ("
|
||||||
|
" 'id' INTEGER NOT NULL,"
|
||||||
|
" 'title' TEXT NOT NULL,"
|
||||||
|
" 'filePath' TEXT NOT NULL,"
|
||||||
|
" PRIMARY KEY(id))")) {
|
||||||
|
qFatal("Failed to query database: %s",
|
||||||
|
qPrintable(query.lastError().text()));
|
||||||
|
}
|
||||||
|
qDebug() << query.lastQuery();
|
||||||
|
qDebug() << "inserting into images";
|
||||||
|
|
||||||
|
query.exec("INSERT INTO images (title, filePath) VALUES ('Dec 180', '/home/chris/nextcloud/tfc/openlp/180-dec.png')");
|
||||||
|
qDebug() << query.lastQuery();
|
||||||
|
query.exec("INSERT INTO images (title, filePath) VALUES ('No TFC', "
|
||||||
|
"'/home/chris/nextcloud/tfc/openlp/No TFC.png')");
|
||||||
|
|
||||||
|
query.exec("select * from images");
|
||||||
|
qDebug() << query.lastQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageSqlModel::ImageSqlModel(QObject *parent) : QSqlTableModel(parent) {
|
||||||
|
qDebug() << "creating image table";
|
||||||
|
createImageTable();
|
||||||
|
setTable(imagesTableName);
|
||||||
|
setEditStrategy(QSqlTableModel::OnManualSubmit);
|
||||||
|
// make sure to call select else the model won't fill
|
||||||
|
select();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant ImageSqlModel::data(const QModelIndex &index, int role) const {
|
||||||
|
if (role < Qt::UserRole) {
|
||||||
|
return QSqlTableModel::data(index, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
// qDebug() << role;
|
||||||
|
const QSqlRecord sqlRecord = record(index.row());
|
||||||
|
return sqlRecord.value(role - Qt::UserRole);
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> ImageSqlModel::roleNames() const
|
||||||
|
{
|
||||||
|
QHash<int, QByteArray> names;
|
||||||
|
names[Qt::UserRole] = "id";
|
||||||
|
names[Qt::UserRole + 1] = "title";
|
||||||
|
names[Qt::UserRole + 2] = "filePath";
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageSqlModel::newImage(const QUrl &filePath) {
|
||||||
|
qDebug() << "adding new image";
|
||||||
|
int rows = rowCount();
|
||||||
|
|
||||||
|
qDebug() << rows;
|
||||||
|
QSqlRecord recordData = record();
|
||||||
|
QFileInfo fileInfo = filePath.toString();
|
||||||
|
QString title = fileInfo.baseName();
|
||||||
|
recordData.setValue("title", title);
|
||||||
|
recordData.setValue("filePath", filePath);
|
||||||
|
|
||||||
|
if (insertRecord(rows, recordData)) {
|
||||||
|
submitAll();
|
||||||
|
} else {
|
||||||
|
qDebug() << lastError();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageSqlModel::deleteImage(const int &row) {
|
||||||
|
QSqlRecord recordData = record(row);
|
||||||
|
if (recordData.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
removeRow(row);
|
||||||
|
submitAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ImageSqlModel::id() const {
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ImageSqlModel::title() const {
|
||||||
|
return m_title;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageSqlModel::setTitle(const QString &title) {
|
||||||
|
if (title == m_title)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_title = title;
|
||||||
|
|
||||||
|
select();
|
||||||
|
emit titleChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is for updating the title from outside the delegate
|
||||||
|
void ImageSqlModel::updateTitle(const int &row, const QString &title) {
|
||||||
|
qDebug() << "Row is " << row;
|
||||||
|
QSqlRecord rowdata = record(row);
|
||||||
|
qDebug() << rowdata;
|
||||||
|
rowdata.setValue("title", title);
|
||||||
|
setRecord(row, rowdata);
|
||||||
|
qDebug() << rowdata;
|
||||||
|
submitAll();
|
||||||
|
emit titleChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl ImageSqlModel::filePath() const {
|
||||||
|
return m_filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageSqlModel::setFilePath(const QUrl &filePath) {
|
||||||
|
if (filePath == m_filePath)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_filePath = filePath;
|
||||||
|
|
||||||
|
select();
|
||||||
|
emit filePathChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is for updating the filepath from outside the delegate
|
||||||
|
void ImageSqlModel::updateFilePath(const int &row, const QUrl &filePath) {
|
||||||
|
qDebug() << "Row is " << row;
|
||||||
|
QSqlRecord rowdata = record(row);
|
||||||
|
qDebug() << rowdata;
|
||||||
|
rowdata.setValue("filePath", filePath);
|
||||||
|
setRecord(row, rowdata);
|
||||||
|
qDebug() << rowdata;
|
||||||
|
submitAll();
|
||||||
|
emit filePathChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl ImageSqlModel::getImage(const int &row) {
|
||||||
|
qDebug() << "Row we are getting is " << row;
|
||||||
|
QUrl image;
|
||||||
|
QSqlRecord rec = record(row);
|
||||||
|
qDebug() << rec.value("filePath").toUrl();
|
||||||
|
// image.append(rec.value("title"));
|
||||||
|
// image.append(rec.value("filePath"));
|
||||||
|
image = rec.value("filePath").toUrl();
|
||||||
|
return image;
|
||||||
|
}
|
49
src/imagesqlmodel.h
Normal file
49
src/imagesqlmodel.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#ifndef IMAGESQLMODEL_H
|
||||||
|
#define IMAGESQLMODEL_H
|
||||||
|
|
||||||
|
#include <QSqlTableModel>
|
||||||
|
#include <qobject.h>
|
||||||
|
#include <qobjectdefs.h>
|
||||||
|
#include <qqml.h>
|
||||||
|
#include <qurl.h>
|
||||||
|
#include <qvariant.h>
|
||||||
|
|
||||||
|
class ImageSqlModel : public QSqlTableModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(int id READ id)
|
||||||
|
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
|
||||||
|
Q_PROPERTY(QUrl filePath READ filePath WRITE setFilePath NOTIFY filePathChanged)
|
||||||
|
QML_ELEMENT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ImageSqlModel(QObject *parent = 0);
|
||||||
|
|
||||||
|
int id() const;
|
||||||
|
QString title() const;
|
||||||
|
QUrl filePath() const;
|
||||||
|
|
||||||
|
void setTitle(const QString &title);
|
||||||
|
void setFilePath(const QUrl &filePath);
|
||||||
|
|
||||||
|
Q_INVOKABLE void updateTitle(const int &row, const QString &title);
|
||||||
|
Q_INVOKABLE void updateFilePath(const int &row, const QUrl &filePath);
|
||||||
|
|
||||||
|
Q_INVOKABLE void newImage(const QUrl &filePath);
|
||||||
|
Q_INVOKABLE void deleteImage(const int &row);
|
||||||
|
Q_INVOKABLE QUrl getImage(const int &row);
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void titleChanged();
|
||||||
|
void filePathChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_id;
|
||||||
|
QString m_title;
|
||||||
|
QUrl m_filePath;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //IMAGESQLMODEL_H
|
|
@ -37,6 +37,7 @@
|
||||||
#include "serviceitemmodel.h"
|
#include "serviceitemmodel.h"
|
||||||
#include "songsqlmodel.h"
|
#include "songsqlmodel.h"
|
||||||
#include "videosqlmodel.h"
|
#include "videosqlmodel.h"
|
||||||
|
#include "imagesqlmodel.h"
|
||||||
|
|
||||||
static void connectToDatabase() {
|
static void connectToDatabase() {
|
||||||
// let's setup our sql database
|
// let's setup our sql database
|
||||||
|
@ -98,6 +99,7 @@ int main(int argc, char *argv[])
|
||||||
//register our models
|
//register our models
|
||||||
qmlRegisterType<SongSqlModel>("org.presenter", 1, 0, "SongSqlModel");
|
qmlRegisterType<SongSqlModel>("org.presenter", 1, 0, "SongSqlModel");
|
||||||
qmlRegisterType<VideoSqlModel>("org.presenter", 1, 0, "VideoSqlModel");
|
qmlRegisterType<VideoSqlModel>("org.presenter", 1, 0, "VideoSqlModel");
|
||||||
|
qmlRegisterType<ImageSqlModel>("org.presenter", 1, 0, "ImageSqlModel");
|
||||||
qmlRegisterType<ServiceItemModel>("org.presenter", 1, 0, "ServiceItemModel");
|
qmlRegisterType<ServiceItemModel>("org.presenter", 1, 0, "ServiceItemModel");
|
||||||
|
|
||||||
connectToDatabase();
|
connectToDatabase();
|
||||||
|
|
|
@ -8,6 +8,9 @@ import "./" as Presenter
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
property string type: "image"
|
||||||
|
property var image
|
||||||
|
|
||||||
GridLayout {
|
GridLayout {
|
||||||
id: mainLayout
|
id: mainLayout
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -83,15 +86,15 @@ Item {
|
||||||
border.color: Kirigami.Theme.activeBackgroundColor
|
border.color: Kirigami.Theme.activeBackgroundColor
|
||||||
border.width: 2
|
border.width: 2
|
||||||
}
|
}
|
||||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
closePolicy: Controls.Popup.CloseOnEscape | Controls.Popup.CloseOnPressOutsideParent
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
Controls.ToolButton {
|
Controls.ToolButton {
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: "Video"
|
text: "Image"
|
||||||
icon.name: "emblem-videos-symbolic"
|
icon.name: "emblem-images-symbolic"
|
||||||
onClicked: videoFileDialog.open() & backgroundType.close()
|
onClicked: imageFileDialog.open() & backgroundType.close()
|
||||||
}
|
}
|
||||||
Controls.ToolButton {
|
Controls.ToolButton {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
@ -121,11 +124,11 @@ Item {
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
Controls.SplitView.fillHeight: true
|
Controls.SplitView.fillHeight: true
|
||||||
Controls.SplitView.preferredWidth: 500
|
Controls.SplitView.preferredWidth: 300
|
||||||
Controls.SplitView.minimumWidth: 500
|
Controls.SplitView.minimumWidth: 100
|
||||||
|
|
||||||
Controls.TextField {
|
Controls.TextField {
|
||||||
id: songTitleField
|
id: imageTitleField
|
||||||
|
|
||||||
Layout.preferredWidth: 300
|
Layout.preferredWidth: 300
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
@ -133,98 +136,46 @@ Item {
|
||||||
Layout.rightMargin: 20
|
Layout.rightMargin: 20
|
||||||
|
|
||||||
placeholderText: "Song Title..."
|
placeholderText: "Song Title..."
|
||||||
text: songTitle
|
text: "idk"
|
||||||
padding: 10
|
padding: 10
|
||||||
onEditingFinished: updateTitle(text);
|
/* 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 {
|
Item {
|
||||||
id: songLyricsField
|
id: empty
|
||||||
|
|
||||||
Layout.preferredHeight: 3000
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Layout.leftMargin: 20
|
|
||||||
|
|
||||||
rightPadding: 20
|
|
||||||
|
|
||||||
Controls.TextArea {
|
|
||||||
id: lyricsEditor
|
|
||||||
width: parent.width
|
|
||||||
placeholderText: "Put lyrics here..."
|
|
||||||
persistentSelection: true
|
|
||||||
text: songLyrics
|
|
||||||
textFormat: TextEdit.MarkdownText
|
|
||||||
padding: 10
|
|
||||||
onEditingFinished: {
|
|
||||||
updateLyrics(text);
|
|
||||||
editorTimer.running = false;
|
|
||||||
}
|
}
|
||||||
onPressed: editorTimer.running = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Controls.TextField {
|
|
||||||
id: songAuthorField
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredWidth: 300
|
|
||||||
Layout.leftMargin: 20
|
|
||||||
Layout.rightMargin: 20
|
|
||||||
|
|
||||||
placeholderText: "Author..."
|
|
||||||
text: songAuthor
|
|
||||||
padding: 10
|
|
||||||
onEditingFinished: updateAuthor(text)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
Controls.SplitView.fillHeight: true
|
Controls.SplitView.fillHeight: true
|
||||||
Controls.SplitView.preferredWidth: 700
|
Controls.SplitView.preferredWidth: 700
|
||||||
Controls.SplitView.minimumWidth: 300
|
Controls.SplitView.minimumWidth: 300
|
||||||
|
spacing: 5
|
||||||
|
|
||||||
Rectangle {
|
Item {
|
||||||
id: slideBar
|
id: topEmpty
|
||||||
color: Kirigami.Theme.highlightColor
|
Layout.fillHeight: true
|
||||||
|
|
||||||
Layout.preferredWidth: 500
|
|
||||||
Layout.preferredHeight: songTitleField.height
|
|
||||||
Layout.rightMargin: 20
|
|
||||||
Layout.leftMargin: 20
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Presenter.SlideEditor {
|
Image {
|
||||||
id: slideEditor
|
id: imagePreview
|
||||||
Layout.preferredWidth: 500
|
Layout.preferredWidth: 600
|
||||||
Layout.fillWidth: true
|
Layout.preferredHeight: Layout.preferredWidth / 16 * 9
|
||||||
Layout.preferredHeight: slideEditor.width / 16 * 9
|
Layout.alignment: Qt.AlignCenter
|
||||||
Layout.bottomMargin: 30
|
fillMode: Image.PreserveAspectFit
|
||||||
Layout.rightMargin: 20
|
source: "file://" + image.toString()
|
||||||
Layout.leftMargin: 20
|
}
|
||||||
|
Item {
|
||||||
|
id: botEmpty
|
||||||
|
Layout.fillHeight: true
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
function changeImage(image) {
|
||||||
Timer {
|
root.image = image;
|
||||||
id: editorTimer
|
print(image.toString());
|
||||||
interval: 1000
|
|
||||||
repeat: true
|
|
||||||
running: false
|
|
||||||
onTriggered: updateLyrics(lyricsEditor.text)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -485,12 +485,40 @@ Item {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.alignment: Qt.AlignTop
|
Layout.alignment: Qt.AlignTop
|
||||||
color: Kirigami.Theme.backgroundColor
|
color: Kirigami.Theme.backgroundColor
|
||||||
|
opacity: 1.0
|
||||||
|
|
||||||
Controls.Label {
|
Controls.Label {
|
||||||
|
id: imageLabel
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "Images"
|
text: "Images"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Controls.Label {
|
||||||
|
id: imageCount
|
||||||
|
anchors {left: imageLabel.right
|
||||||
|
verticalCenter: imageLabel.verticalCenter
|
||||||
|
leftMargin: 15}
|
||||||
|
text: imagesqlmodel.rowCount()
|
||||||
|
font.pixelSize: 15
|
||||||
|
color: Kirigami.Theme.disabledTextColor
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.Icon {
|
||||||
|
id: imageDrawerArrow
|
||||||
|
anchors {right: parent.right
|
||||||
|
verticalCenter: imageCount.verticalCenter
|
||||||
|
rightMargin: 10}
|
||||||
|
source: "arrow-down"
|
||||||
|
rotation: selectedLibrary == "images" ? 0 : 180
|
||||||
|
|
||||||
|
Behavior on rotation {
|
||||||
|
NumberAnimation {
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
duration: 300
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
@ -508,6 +536,9 @@ Item {
|
||||||
Layout.preferredHeight: parent.height - 200
|
Layout.preferredHeight: parent.height - 200
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.alignment: Qt.AlignTop
|
Layout.alignment: Qt.AlignTop
|
||||||
|
model: imagesqlmodel
|
||||||
|
delegate: imageDelegate
|
||||||
|
clip: true
|
||||||
state: "deselected"
|
state: "deselected"
|
||||||
|
|
||||||
states: [
|
states: [
|
||||||
|
@ -534,6 +565,118 @@ Item {
|
||||||
duration: 300
|
duration: 300
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: imageDelegate
|
||||||
|
Item{
|
||||||
|
implicitWidth: ListView.view.width
|
||||||
|
height: selectedLibrary == "images" ? 50 : 0
|
||||||
|
Kirigami.BasicListItem {
|
||||||
|
id: imageListItem
|
||||||
|
|
||||||
|
property bool rightMenu: false
|
||||||
|
|
||||||
|
implicitWidth: imageLibraryList.width
|
||||||
|
height: selectedLibrary == "images" ? 50 : 0
|
||||||
|
clip: true
|
||||||
|
label: title
|
||||||
|
/* subtitle: author */
|
||||||
|
supportsMouseEvents: false
|
||||||
|
backgroundColor: {
|
||||||
|
if (parent.ListView.isCurrentItem) {
|
||||||
|
Kirigami.Theme.highlightColor;
|
||||||
|
} else if (imageDragHandler.containsMouse){
|
||||||
|
Kirigami.Theme.highlightColor;
|
||||||
|
} else {
|
||||||
|
Kirigami.Theme.backgroundColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
textColor: {
|
||||||
|
if (parent.ListView.isCurrentItem || imageDragHandler.containsMouse)
|
||||||
|
activeTextColor;
|
||||||
|
else
|
||||||
|
Kirigami.Theme.textColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on height {
|
||||||
|
NumberAnimation {
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
duration: 300
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Drag.active: imageDragHandler.drag.active
|
||||||
|
Drag.hotSpot.x: width / 2
|
||||||
|
Drag.hotSpot.y: height / 2
|
||||||
|
Drag.keys: [ "library" ]
|
||||||
|
|
||||||
|
states: State {
|
||||||
|
name: "dragged"
|
||||||
|
when: imageListItem.Drag.active
|
||||||
|
PropertyChanges {
|
||||||
|
target: imageListItem
|
||||||
|
x: x
|
||||||
|
y: y
|
||||||
|
width: width
|
||||||
|
height: height
|
||||||
|
}
|
||||||
|
ParentChange {
|
||||||
|
target: imageListItem
|
||||||
|
parent: rootApp.overlay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: imageDragHandler
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
drag {
|
||||||
|
target: imageListItem
|
||||||
|
onActiveChanged: {
|
||||||
|
if (imageDragHandler.drag.active) {
|
||||||
|
dragItemTitle = title;
|
||||||
|
dragItemType = "image";
|
||||||
|
dragItemText = "";
|
||||||
|
dragItemBackgroundType = "image";
|
||||||
|
dragItemBackground = filePath;
|
||||||
|
} else {
|
||||||
|
imageListItem.Drag.drop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filterChildren: true
|
||||||
|
threshold: 10
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
id: imageClickHandler
|
||||||
|
anchors.fill: parent
|
||||||
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
|
onClicked: {
|
||||||
|
if(mouse.button == Qt.RightButton)
|
||||||
|
rightClickImageMenu.popup()
|
||||||
|
else{
|
||||||
|
imageLibraryList.currentIndex = index
|
||||||
|
const image = imagesqlmodel.getImage(imageLibraryList.currentIndex);
|
||||||
|
if (!editMode)
|
||||||
|
editMode = true;
|
||||||
|
editType = "image";
|
||||||
|
editSwitch(image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Controls.Menu {
|
||||||
|
id: rightClickImageMenu
|
||||||
|
x: imageClickHandler.mouseX
|
||||||
|
y: imageClickHandler.mouseY + 10
|
||||||
|
Kirigami.Action {
|
||||||
|
text: "delete"
|
||||||
|
onTriggered: imagesqlmodel.deleteImage(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|
|
@ -66,6 +66,7 @@ Controls.Page {
|
||||||
id: presentation
|
id: presentation
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
}
|
}
|
||||||
|
|
||||||
Presenter.SongEditor {
|
Presenter.SongEditor {
|
||||||
id: songEditor
|
id: songEditor
|
||||||
visible: false
|
visible: false
|
||||||
|
@ -77,6 +78,12 @@ Controls.Page {
|
||||||
visible: false
|
visible: false
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Presenter.ImageEditor {
|
||||||
|
id: imageEditor
|
||||||
|
visible: false
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Presenter.Library {
|
Presenter.Library {
|
||||||
|
@ -102,6 +109,10 @@ Controls.Page {
|
||||||
id: videosqlmodel
|
id: videosqlmodel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImageSqlModel {
|
||||||
|
id: imagesqlmodel
|
||||||
|
}
|
||||||
|
|
||||||
ServiceItemModel {
|
ServiceItemModel {
|
||||||
id: serviceItemModel
|
id: serviceItemModel
|
||||||
}
|
}
|
||||||
|
@ -141,19 +152,24 @@ Controls.Page {
|
||||||
presentation.visible = false;
|
presentation.visible = false;
|
||||||
videoEditor.visible = false;
|
videoEditor.visible = false;
|
||||||
videoEditor.stop();
|
videoEditor.stop();
|
||||||
|
imageEditor.visible = false;
|
||||||
songEditor.visible = true;
|
songEditor.visible = true;
|
||||||
songEditor.changeSong(item);
|
songEditor.changeSong(item);
|
||||||
break;
|
break;
|
||||||
case "video" :
|
case "video" :
|
||||||
presentation.visible = false;
|
presentation.visible = false;
|
||||||
songEditor.visible = false;
|
songEditor.visible = false;
|
||||||
|
imageEditor.visible = false;
|
||||||
videoEditor.visible = true;
|
videoEditor.visible = true;
|
||||||
videoEditor.changeVideo(item);
|
videoEditor.changeVideo(item);
|
||||||
break;
|
break;
|
||||||
case "image" :
|
case "image" :
|
||||||
mainPageArea.pop(Controls.StackView.Immediate);
|
presentation.visible = false;
|
||||||
mainPageArea.push(imageEditorComp, Controls.StackView.Immediate);
|
videoEditor.visible = false;
|
||||||
videoEditor.stop();
|
videoEditor.stop();
|
||||||
|
songEditor.visible = false;
|
||||||
|
imageEditor.visible = true;
|
||||||
|
imageEditor.changeImage(item);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
videoEditor.visible = false;
|
videoEditor.visible = false;
|
||||||
|
|
|
@ -116,15 +116,12 @@ Qt::ItemFlags ServiceItemModel::flags(const QModelIndex &index) const {
|
||||||
|
|
||||||
void ServiceItemModel::addItem(ServiceItem *item) {
|
void ServiceItemModel::addItem(ServiceItem *item) {
|
||||||
const int index = m_items.size();
|
const int index = m_items.size();
|
||||||
qDebug() << index;
|
// qDebug() << index;
|
||||||
// foreach (item, m_items) {
|
// foreach (item, m_items) {
|
||||||
// qDebug() << item;
|
// qDebug() << item;
|
||||||
// }
|
// }
|
||||||
beginInsertRows(QModelIndex(), index, index);
|
beginInsertRows(QModelIndex(), index, index);
|
||||||
m_items.append(item);
|
m_items.append(item);
|
||||||
foreach (item, m_items) {
|
|
||||||
qDebug() << item;
|
|
||||||
}
|
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,14 +39,14 @@ static void createTable()
|
||||||
qFatal("Failed to query database: %s",
|
qFatal("Failed to query database: %s",
|
||||||
qPrintable(query.lastError().text()));
|
qPrintable(query.lastError().text()));
|
||||||
}
|
}
|
||||||
qDebug() << query.lastQuery();
|
// qDebug() << query.lastQuery();
|
||||||
qDebug() << "inserting into songs";
|
// qDebug() << "inserting into songs";
|
||||||
|
|
||||||
query.exec(
|
query.exec(
|
||||||
"INSERT INTO songs (title, lyrics, author, ccli, audio, vorder, "
|
"INSERT INTO songs (title, lyrics, author, ccli, audio, vorder, "
|
||||||
"background, backgroundType, textAlignment) VALUES ('10,000 Reasons', '10,000 reasons "
|
"background, backgroundType, textAlignment) VALUES ('10,000 Reasons', '10,000 reasons "
|
||||||
"for my heart to sing', 'Matt Redman', '13470183', '', '', '', '', 'center')");
|
"for my heart to sing', 'Matt Redman', '13470183', '', '', '', '', 'center')");
|
||||||
qDebug() << query.lastQuery();
|
// qDebug() << query.lastQuery();
|
||||||
query.exec("INSERT INTO songs (title, lyrics, author, ccli, audio, vorder, "
|
query.exec("INSERT INTO songs (title, lyrics, author, ccli, audio, vorder, "
|
||||||
"background, backgroundType, textAlignment) VALUES ('River', 'Im going down to "
|
"background, backgroundType, textAlignment) VALUES ('River', 'Im going down to "
|
||||||
"the river', 'Jordan Feliz', '13470183', '', '', '', '', 'center')");
|
"the river', 'Jordan Feliz', '13470183', '', '', '', '', 'center')");
|
||||||
|
@ -55,15 +55,15 @@ static void createTable()
|
||||||
"background, backgroundType, textAlignment) VALUES ('Marvelous Light', 'Into marvelous "
|
"background, backgroundType, textAlignment) VALUES ('Marvelous Light', 'Into marvelous "
|
||||||
"light Im running', 'Chris Tomlin', '13470183', '', '', '', '', 'center')");
|
"light Im running', 'Chris Tomlin', '13470183', '', '', '', '', 'center')");
|
||||||
|
|
||||||
qDebug() << query.lastQuery();
|
// qDebug() << query.lastQuery();
|
||||||
query.exec("select * from songs");
|
query.exec("select * from songs");
|
||||||
qDebug() << query.lastQuery();
|
// qDebug() << query.lastQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
SongSqlModel::SongSqlModel(QObject *parent)
|
SongSqlModel::SongSqlModel(QObject *parent)
|
||||||
: QSqlTableModel(parent)
|
: QSqlTableModel(parent)
|
||||||
{
|
{
|
||||||
qDebug() << "creating table";
|
// qDebug() << "creating table";
|
||||||
createTable();
|
createTable();
|
||||||
setTable(songsTableName);
|
setTable(songsTableName);
|
||||||
setEditStrategy(QSqlTableModel::OnManualSubmit);
|
setEditStrategy(QSqlTableModel::OnManualSubmit);
|
||||||
|
|
|
@ -46,4 +46,4 @@ private:
|
||||||
QUrl m_filePath;
|
QUrl m_filePath;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //SONGSQLMODEL_H
|
#endif //VIDEOSQLMODEL_H
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue