qml 结合 QSqlTableModel 动态加载数据 MVC「建议收藏」

效果预览:一、准备好对应的 QSqlTableModel#ifndefLOCALMUSICMODEL_H#defineLOCALMUSICMODEL_H#include<QObject>#include<QSqlTableModel>#include<QMediaPlayer>#include"libzplay.h"usingname…

大家好,又见面了,我是你们的朋友全栈君。

效果预览:

qml 结合 QSqlTableModel 动态加载数据 MVC「建议收藏」

一、准备好对应的 QSqlTableModel

#ifndef LOCALMUSICMODEL_H
#define LOCALMUSICMODEL_H

#include <QObject>
#include <QSqlTableModel>
#include <QMediaPlayer>
#include "libzplay.h"
using namespace libZPlay;

struct songInfo
{
    QString Artist;
    QString title;
    QString album;
    qint32 duration = 0;
    QString path;

};

class LocalMusicModel : public QSqlTableModel
{
    Q_OBJECT
    Q_PROPERTY(int m_musicNum READ musicNum WRITE setMusicNum NOTIFY musicNumChanged)



public:
    explicit LocalMusicModel(QObject *parent = nullptr);
    QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
    QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE;

    Q_INVOKABLE void reloadMusicRecord(const QString &path);
    int musicNum(){return m_musicNum;}
    void setMusicNum(int val){
        m_musicNum = val;
        emit musicNumChanged();
    }

signals:
    void musicNumChanged();

private:
    void parseMusicInfo(QString path);
    void clearDb();

private:
    ZPlay *player;
    int m_musicNum = 0;

};

#endif // LOCALMUSICMODEL_H

#include "localmusicmodel.h"

#include <QDateTime>
#include <QSqlRecord>
#include <QDebug>
#include <QSqlError>
#include <QSqlQuery>
#include <QDir>


static const char *localMusicTableName = "LocalMusicInfo";

static void createTable()
{
    if (QSqlDatabase::database().tables().contains(localMusicTableName)) {
        // The table already exists; we don't need to do anything.
        return;
    }

    QSqlQuery query;
    QString sql_ = QStringLiteral("CREATE TABLE IF NOT EXISTS [LocalMusicInfo] (         \
                                  [title] VARCHAR2 , \
                                  [singer] VARCHAR2 , \
                                  [album] VARCHAR2 , \
                                  [duration] INTEGER ,\
                                  [path] VARCHAR2 NOT NULL ,          \
                                  UNIQUE([path]) ON CONFLICT REPLACE \
                                  )");


    if (!query.exec(sql_)) {
        qFatal("Failed to query database: %s", qPrintable(query.lastError().text()));
    }

    //query.exec("INSERT INTO LocalMusicInfo VALUES('title', 'singer', 'album', 123,'c://')");
}


LocalMusicModel::LocalMusicModel(QObject *parent)
    : QSqlTableModel(parent)
{
    createTable();
    setTable(localMusicTableName);
    /*可以看到这个模型很强大,而且完全脱离了SQL语句,就算你不怎么懂数据库,
     * 也可以利用它进行大部分常用的操作。这个模型提供了缓冲区,可以将所有修改先保存到model中,
     * 只有当我们执行提交修改后,才会真正写入数据库。当然这也是因为我们在最开始设置了它的保存策略:
    submitAll();   revertAll();*/
    setEditStrategy(QSqlTableModel::OnManualSubmit);
    select();
    player = CreateZPlay();

    setMusicNum(this->rowCount());
}

QVariant LocalMusicModel::data(const QModelIndex &index, int role) const
{
    if (role < Qt::UserRole)
            return QSqlTableModel::data(index, role);

    const QSqlRecord sqlRecord = record(index.row());

    //qDebug() << sqlRecord.value(role - Qt::UserRole);

    switch (role) {
    case Qt::UserRole:
        if(sqlRecord.value(0).toString().isEmpty())
        {
            QString path = sqlRecord.value(role - Qt::UserRole + 4).toString();
            path =  path.right(path.lastIndexOf('/'));
            path.chop(4);
            return  path.simplified();
        }
        break;
    case Qt::UserRole+1:
        if(sqlRecord.value(1).toString().isEmpty())
            return tr("未知歌手");
        break;
    case Qt::UserRole+2:
        if(sqlRecord.value(2).toString().isEmpty())
            return tr("未知专辑");
        break;
    case Qt::UserRole+3:
        int time = sqlRecord.value(3).toInt();
        return QString("%1:%2").arg(time/60).arg(time%60,2,10,QChar('0'));
    }
    return sqlRecord.value(role - Qt::UserRole);
}

QHash<int, QByteArray> LocalMusicModel::roleNames() const
{
    QHash<int, QByteArray> names;
    names[Qt::UserRole] = "title";
    names[Qt::UserRole + 1] = "singer";
    names[Qt::UserRole + 2] = "album";
    names[Qt::UserRole + 3] = "duration";
    names[Qt::UserRole + 4] = "path";
    return names;
}

void LocalMusicModel::reloadMusicRecord(const QString &path_)
{
    parseMusicInfo(path_);
}

//获取指定目录下所有歌曲信息
void LocalMusicModel::parseMusicInfo(QString path)
{
    QList<songInfo> songRecords;
    QStringList dirList=path.split(",");
    QString temp;
    foreach (temp, dirList) {
        temp=temp.right(temp.length()-8);
        QDir dir(temp);
        dir.setNameFilters(QStringList() << "*.mp3" << "*.flac" << "*.wav");
        QFileInfoList fileList=dir.entryInfoList();
        QFileInfo fileInfo;

        foreach (fileInfo, fileList) {
            TID3InfoEx id3_info;
            //如果直接使用LoadFileID3Ex函数,会得不到时长信息
            if(player->OpenFile((const char*) fileInfo.absoluteFilePath().toLocal8Bit(),sfAutodetect))
                if(player->LoadID3Ex(&id3_info,1))
                {
                    songInfo tempSongInfo;
                    tempSongInfo.title = QString::fromLocal8Bit(id3_info.Title);    //音乐标题
                    tempSongInfo.Artist = QString::fromLocal8Bit(id3_info.Artist);  //歌手
                    tempSongInfo.path = fileInfo.absoluteFilePath();                //路径
                    tempSongInfo.album = QString::fromLocal8Bit(id3_info.Album);    //专辑
                    // get stream info,获取时长信息
                    TStreamInfo pInfo;
                    player->GetStreamInfo(&pInfo);
                    tempSongInfo.duration =pInfo.Length.sec;
                    songRecords.append(tempSongInfo);
                }
                else
                {
                    qDebug() << QString("No ID3 data:%1\r\n\r\n").arg(QString::fromLocal8Bit(player->GetError()));
                }
            else
            {
                qDebug() << "LoadID3Ex faild";
            }
        }
    }

    clearDb();

    QSqlRecord newRecord = record();
    for(auto songItem : songRecords)
    {
        newRecord.setValue("title", songItem.title);
        newRecord.setValue("singer", songItem.Artist);
        newRecord.setValue("album", songItem.album);
        newRecord.setValue("duration", songItem.duration);
        newRecord.setValue("path", songItem.path);

        if (!insertRecord(rowCount(), newRecord)) {
            qWarning() << "Failed to send message:" << lastError().text();
            return;
        }
    }

    submitAll();//提交数据库
    setMusicNum(songRecords.size());
}

void LocalMusicModel::clearDb()
{
    if (!QSqlDatabase::database().tables().contains(localMusicTableName)) {
        createTable();
    }

    QSqlQuery query;
    QString sql_ = QStringLiteral("delete from [LocalMusicInfo]");

    if (!query.exec(sql_)) {
        qFatal("Failed to query database: %s", qPrintable(query.lastError().text()));
    }
    qDebug() << "clear table ok";
}

重点是

QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE;

QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;

给你需要的数据设置好role,方便qml进行调用。

二、qml调用

main.cpp

qmlRegisterType<LocalMusicModel>("io.qt.CloudMusic", 1, 0, "LocalMusicModel");

qml:

import io.qt.CloudMusic 1.0

LocalMusicModel{
 
 id:localmusic;}
            TableView{
                id: tableview
                anchors.fill: parent
                visible: localmusic.m_musicNum >0
                backgroundVisible: false;
                frameVisible: false;
                //itemDelegate: StandardTabelItemDelegate{} //代理
                //headerDelegate: headerDele;  //表头委托
                //rowDelegate: rowDele;   //行委托
                model: localmusic

                TableViewColumn {
                          role: "title"
                          title: qsTr("标题")
                          width: 300
                      }
                TableViewColumn {
                          role: "singer"
                          title: qsTr("歌手")
                          width: 300
                      }
                TableViewColumn {
                          role: "album"
                          title: qsTr("专辑")
                          width: 300
                      }
                TableViewColumn {
                          role: "duration"
                          title: qsTr("时长")
                          width: 300
                      }
            }

代理待后面继续完善

qml之从零开始编写网易云音乐目录

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/127739.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • 至强系列cpu天梯图_cpu天梯图2018

    至强系列cpu天梯图_cpu天梯图2018Helio,大家好,距离上一次天梯图更新已经过去一个月时间了,伴随着新的月份到来,新的天梯图该进行更新修正了,下面小编带来CPU天梯图2018年11月最新版,希望对大家有所帮助。CPU天梯图2018年11月最新版:CPU天梯图2018年11月最新版十一月电脑CPU天梯图性能排行新增了几款上个月新上市的几款处理器,尤其是Intel九代酷睿处理器的排行情况,通过前面的评测相信大家基本上对九代酷睿处理器…

    2022年9月15日
  • 并发编程面试题(2020最新版)「建议收藏」

    文章目录基础知识并发编程的优缺点为什么要使用并发编程(并发编程的优点)并发编程有什么缺点并发编程三要素是什么?在Java程序中怎么保证多线程的运行安全?并行和并发有什么区别?什么是多线程,多线程的优劣?线程和进程区别什么是线程和进程?进程与线程的区别什么是上下文切换?守护线程和用户线程有什么区别呢?如何在Windows和Linux上查找哪个线程cpu利用率最高?什么是线程死锁形成死锁的…

    2022年4月18日
  • iOS_UIButton 简单操作

    iOS_UIButton 简单操作

    2022年1月20日
  • 4g融合指的是什么_天翼网关3

    4g融合指的是什么_天翼网关3小草科技推出融合通信新产品系列——多网融合多路聚合今天,深圳小草信息科技有限公司发布了系列新产品,以解决当前移动互联网网络不稳定带宽不够、安全性差等问题。智能融合通信将有线与多路无线智能融合成为一路通道,并聚合多个通道形成一个大容量通道,实现大数据在一个聚合通道中的传输。加载自有协议,安全、快速、稳定的传送数据至云端,提供安全稳定的宽带传输通道,确保业务永不中断。1,MNF-410…

    2022年10月3日
  • 数据库返回的整型数据被偷换成了字符串类型[通俗易懂]

    数据库返回的整型数据被偷换成了字符串类型

    2022年2月15日
  • 手把手教你用python写游戏「建议收藏」

    手把手教你用python写游戏「建议收藏」引言最近python语言大火,除了在科学计算领域python有用武之地之外,在游戏、后台等方面,python也大放异彩,本篇博文将按照正规的项目开发流程,手把手教大家写个python小游戏,项目来自《Python编程从入门到实践》(本文将原项目中的部分错误进行修改完善,PS:强烈推荐这本书,真的很赞),来感受下其中的有趣之处。本次开发的游戏叫做alieninvasion。安装pygame…

    2022年5月24日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号