Qt小例子学习51 - 网格分页过滤器

Qt小例子学习51 - 网格分页过滤器

Filtro.h

#ifndef FILTRO_H
#define FILTRO_H
#include <QSortFilterProxyModel>

class Filtro : public QSortFilterProxyModel
{
    Q_OBJECT
    Q_PROPERTY(bool showOnlyUserRic READ showOnlyUserRic WRITE setshowOnlyUserRic
               NOTIFY showOnlyUserRicChanged)
    Q_PROPERTY(QString string READ string WRITE setstring NOTIFY stringChanged)
public:
    Filtro(QObject *parent = 0);
    ~Filtro();
    Q_INVOKABLE void setStringaFiltro(QString string);
public slots:
    void setshowOnlyUserRic(bool showOnlyUserRic);
    bool showOnlyUserRic() const;
    QString string() const;
    void setstring(QString string);
signals:
    void showOnlyUserRicChanged();
    void oggettiFiltChanged();
    void stringChanged();
private:
    bool m_showOnlyUserRic;
    int m_oggettiFilt;
    QString m_string;
protected:
    bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
    // QSortFilterProxyModel interface
    bool lessThan(const QModelIndex &source_left,
                  const QModelIndex &source_right) const;
};

#endif // FILTRO_H

Filtro.cpp

#include "filtro.h"
#include "modello.h"
#include <QDebug>

Filtro::Filtro(QObject *parent)
    : QSortFilterProxyModel(parent), m_showOnlyUserRic(false), m_oggettiFilt(0),
      m_string("")
{
    setFilterRole(modello::RicettaUtente);
    setSortRole(modello::NomeRicetta);
    setDynamicSortFilter(true);
    sort(0);
}

Filtro::~Filtro() {}

void Filtro::setStringaFiltro(QString string)
{
    this->setFilterCaseSensitivity(
        Qt::CaseInsensitive); // lo rendo case insensitive
    this->setFilterFixedString(string);
}
QString Filtro::string() const { return m_string; }
void Filtro::setstring(QString string)
{
    if (m_string == string)
        return;

    m_string = string;
    emit stringChanged();
    invalidateFilter(); // fa rivalutare il filtro e quindi entra di nuovo in
    // filterAcceptsRows()
}
bool Filtro::showOnlyUserRic() const { return m_showOnlyUserRic; }
void Filtro::setshowOnlyUserRic(bool showOnlyUserRic)
{
    if (m_showOnlyUserRic == showOnlyUserRic)
        return;
    m_showOnlyUserRic = showOnlyUserRic;
    emit showOnlyUserRicChanged();
    invalidateFilter(); // fa rivalutare il filtro e quindi entra di nuovo in
    // filterAcceptsRows()
}

bool Filtro::filterAcceptsRow(int source_row,
                              const QModelIndex &source_parent) const
{
    QRegExp regEx("*" + string() + "*");
    regEx.setPatternSyntax(QRegExp::Wildcard);
    regEx.setCaseSensitivity(Qt::CaseInsensitive);

    if (showOnlyUserRic() == true)
    {
        // se devo visualizzare solo
        QModelIndex ricUtente = sourceModel()->index(
                                    source_row, 0,
                                    source_parent); // vado a leggere singolarmente ogni riga del modello
        QString stringaConfronto =
            sourceModel()->data(ricUtente, modello::NomeRicetta).toString();

        if (sourceModel()->data(ricUtente, modello::RicettaUtente) == true &&
                stringaConfronto.contains(regEx) == true)
        {
            // se è ricetta utente
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        QModelIndex ricUtente = sourceModel()->index(
                                    source_row, 0,
                                    source_parent); // vado a leggere singolarmente ogni riga del modello
        QString stringaConfronto =
            sourceModel()->data(ricUtente, modello::NomeRicetta).toString();
        if (stringaConfronto.contains(regEx))
            return true;
        //        if(sourceModel()->data(ricUtente,modello::NomeRicetta)== string()
        //        )  //confronto il roles ricetta utene x filtrare il
        //        {
        //            return true;
        //        }
        return false;
    }
}

bool Filtro::lessThan(const QModelIndex &source_left,
                      const QModelIndex &source_right) const
{
    bool leftData = sourceModel()
                    ->data(source_left, modello::RicettaUtente)
                    .toBool(); // vado a leggere il valore RicettaUtente e lo
    // trasformo in bool
    bool rightData = sourceModel()
                     ->data(source_right, modello::RicettaUtente)
                     .toBool(); // vado a leggere il valore RicettaUtente e lo
    // trasformo in bool
    if (leftData != rightData)
        return leftData;
    else
        return QSortFilterProxyModel::lessThan(source_left, source_right);
}

main.qml

import QtQuick 2.7
import QtQuick.Window 2.2
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    color: "#465775"

    TextField {
        id:textField
        anchors.top: parent.top ;anchors.topMargin: 10;
        anchors.horizontalCenter: parent.horizontalCenter
        placeholderText: "Cerca Ricetta"
        width:parent.width*0.95
        font.pointSize: 12
        background: Rectangle {
                radius: 5
                width: parent.width
                implicitHeight: 30

        }

        onTextChanged: {
            //myModelFiltrato.setStringaFiltro(text)
            myModelFiltrato.string=text

        }

    }

    GridView {
     id:grid

     property int indiceCorretto: 0

     function updateModel(){
        // alternativa a mettere il datachanged nel metodo add ricetta
        model=0
        model=myModel

     }
     function increseCurrIndex(index){

         //calcolo il giusto current index per dare effetto di gridView con paginazione

         if(Math.floor(index/6)==0)
           grid.indiceCorretto= 0                           // altrimenti ho valore negativo
         else
           grid.indiceCorretto=(Math.floor(index/6))*6

     }

     onCountChanged: {

          // faccio queste operazioni per aggiornare il numero dei p.indicator quando filtro le tile
          myModel.numIndicatori=grid.count
         // per rendere attivo il click sull'ultima mattonella quando
         myModel.totTile=grid.count
     }

     width:parent.width
     height: parent.height* 0.70

     highlightMoveDuration: 500
     highlightFollowsCurrentItem: true

     anchors.horizontalCenter: parent.horizotalCenter
     anchors.verticalCenter: parent.verticalCenter

     cellWidth: parent.width/3
     cellHeight: parent.height/3
     model: myModelFiltrato
     delegate: tile

     onMovementEnded: {

        increseCurrIndex(currentIndex)
        currentIndex=indiceCorretto
     }
     flow: GridView.FlowTopToBottom
     flickDeceleration: 4500
     clip: true

     boundsBehavior: Flickable.StopAtBounds
     flickableDirection: Flickable.VerticalFlick
     snapMode: GridView.SnapToRow
     highlightRangeMode: GridView.StrictlyEnforceRange
     preferredHighlightBegin: 0
     preferredHighlightEnd:  0

    }

    Component {
       id: tile
       Item{
               width: grid.cellWidth
               height: grid.cellHeight
               Rectangle{

                   color: colore//"#EF6F6C"//Qt.rgba(Math.random(),Math.random(),Math.random(),0.90)
                   width:parent.height*0.90
                   height: parent.height*0.90
                   anchors.verticalCenter: parent.verticalCenter
                   anchors.horizontalCenter: parent.horizontalCenter
                   border.width: 2
                   border.color:"#FFFFFF"

                   Text {
                       anchors.verticalCenter: parent.verticalCenter
                       anchors.left:parent.left
                       anchors.right: parent.right
                       horizontalAlignment: Text.AlignHCenter
                       text:nomeRicetta + " "+index.toString()
                       font.pointSize: 17
                       color: "#ffffff"
                       wrapMode: Text.WordWrap
                   }
                   MouseArea {

                       anchors.fill: parent
                       onClicked: {
                          if(index==myModel.totTile-1)
                             myModel.addRicetta("pane","green",2,true)
                       }
                       onPressAndHold: {
                          if (index != myModel.totTile-1){

                                    myModel.removeRows(index,1)
                          }

                       }
                   }
               }
       }
    }
    // page indicator circolare
    PageIndicator {
        id: control
        visible: false
        interactive: false
        count: myModel.numIndicatori
        currentIndex: Math.floor(grid.currentIndex/6)
        anchors.bottom: parent.bottom ; anchors.bottomMargin:25
        anchors.horizontalCenter: parent.horizontalCenter

        delegate: Rectangle {
              implicitWidth: 8
              implicitHeight: 8

              radius: width / 2
              color: "#ffffff"

              opacity: index === control.currentIndex ? 0.95 : pressed ? 0.7 : 0.45

              Behavior on opacity {
                  OpacityAnimator {
                      duration: 100
                  }
              }
              MouseArea {
                anchors.fill: parent
                onClicked: grid.currentIndex = index*6

              }
          }

    }
    // page indicator quadrato
    PageIndicator {
        id: control1
        visible: true
        interactive: false
        count: myModel.numIndicatori
        currentIndex: Math.floor(grid.currentIndex/6)
        anchors.bottom: parent.bottom ; anchors.bottomMargin:25
        anchors.horizontalCenter: parent.horizontalCenter

        delegate: Rectangle {
              implicitWidth: 25
              implicitHeight: 25

              //radius: width / 2
              color: "#ffffff"

              opacity: index === control1.currentIndex ? 0.95 : pressed ? 0.7 : 0.45

              Text{

               anchors.centerIn: parent
               text:(index+1).toString()
               color: "#465775"
              }

              Behavior on opacity {
                  OpacityAnimator {
                      duration: 100
                  }
              }
              MouseArea {
                anchors.fill: parent
                onClicked: grid.currentIndex = index*6

              }
          }

    }

    CheckBox {
           text: qsTr("Mostra solo ricetteUtente")
           checked: myModelFiltrato.showOnlyUserRic
           onClicked: {
               myModelFiltrato.showOnlyUserRic = !myModelFiltrato.showOnlyUserRic

           }
           anchors.left: parent.left; anchors.leftMargin: 15
           anchors.bottom: parent.bottom ; anchors.bottomMargin: 15
    }
}

modello.h

#ifndef MODELLO_H
#define MODELLO_H

#include <QAbstractItemModel>
#include <QObject>
#include <QSortFilterProxyModel>

class Tile
{
public:
    Tile(const QString &nomeRicetta, const QString &colore, const int &durata,
         const bool &ricettaUtente);
    QString nomeRicetta() const;
    QString colore() const;
    int durata() const;
    bool ricettaUtente() const;

private:
    QString m_nomeRicetta;
    QString m_colore;
    int m_durata;
    bool m_ricettaUtente;
};

class modello : public QAbstractListModel
{
    Q_OBJECT
public:
    explicit modello(QObject *parent = 0);
    ~modello();
    Q_PROPERTY(qint16 numIndicatori READ numIndicatori WRITE setnumIndicatori
               NOTIFY numIndicatoriChanged)
    Q_PROPERTY(qint16 totTile READ totTile WRITE setTotTile NOTIFY
               totTileChanged) // property x fare in modo che solo l'ultima
    // tile sia cliccabile
    enum TileRoles
    {

        NomeRicetta = Qt::UserRole + 1,
        Colore,
        Durata,
        RicettaUtente
    };

    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    QVariant data(const QModelIndex &index, int role) const;
    QHash<int, QByteArray> roleNames() const;
    Q_INVOKABLE bool
    removeRows(int row, int count,
               const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE;
    Q_INVOKABLE void addRicetta(QString nomeRic, QString color, int durata,
                                bool ricettaUtente);

    qint16 numIndicatori() const;
    qint16 totTile() const;

public slots:
    void setnumIndicatori(qint16 numIndicatori);
    void setTotTile(qint16 totTile);

signals:
    void numIndicatoriChanged();
    void totTileChanged();

private:
    QList<Tile> m_ricette;
    qint16 m_numIndicatori;
    qint16 m_totTile;
};

#endif // MODELLO_H

modello.cpp

#include "modello.h"

Tile::Tile(const QString &nomeRicetta, const QString &colore, const int &durata,
           const bool &ricettaUtente)
    : m_nomeRicetta(nomeRicetta), m_colore(colore), m_durata(durata),
      m_ricettaUtente(ricettaUtente) {}

QString Tile::nomeRicetta() const { return m_nomeRicetta; }

QString Tile::colore() const { return m_colore; }

int Tile::durata() const { return m_durata; }

bool Tile::ricettaUtente() const { return m_ricettaUtente; }

modello::modello(QObject *parent)
    : QAbstractListModel(parent), m_numIndicatori(1), m_totTile(1)
{
    addRicetta("Aggiungi Ricetta", "grey", 1, true);
}

modello::~modello() {}

int modello::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return m_ricette.count();
}

QVariant modello::data(const QModelIndex &index, int role) const
{
    if (index.row() < 0 || index.row() >= m_ricette.count())
        return QVariant();

    const Tile &tiletemp = m_ricette[index.row()];
    switch (role)
    {
    case NomeRicetta:
        return tiletemp.nomeRicetta();
        break;
    case Colore:
        return tiletemp.colore();
        break;
    case Durata:
        return tiletemp.durata();
        break;
    case RicettaUtente:
        return tiletemp.ricettaUtente();
        break;
    default:
        return QVariant();
        break;
    }
}

QHash<int, QByteArray> modello::roleNames() const
{

    QHash<int, QByteArray> roles;
    roles[NomeRicetta] = "nomeRicetta";
    roles[Colore] = "colore";
    roles[Durata] = "durata";
    roles[RicettaUtente] = "ricettaUtente";
    return roles;
}

bool modello::removeRows(int row, int count, const QModelIndex &parent)
{

    Q_UNUSED(parent);

    beginRemoveRows(parent, row, row + count - 1); // row row perchè ne elimino 1
    m_ricette.removeAt(row);
    endRemoveRows();

    QModelIndex top = createIndex(0, 0);
    QModelIndex bottom = createIndex(rowCount() - 1, 0);
    emit dataChanged(top, bottom);
    setnumIndicatori(rowCount()); // passo il totale degli elementi
    setTotTile(rowCount()); // aggiorno la property con il totale mi serve il suo
    // emit x il qml
    return true;
}

void modello::addRicetta(QString nomeRic, QString color, int durata,
                         bool ricettaUtente)
{
    Tile tileTmp(nomeRic, color, durata, ricettaUtente);

    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    if (rowCount() == 0)
        m_ricette << tileTmp;
    else
        m_ricette.insert(rowCount() - 1, tileTmp);
    endInsertRows();

    // mi serve per aggiornare in automatico il qml
    QModelIndex top = createIndex(0, 0);
    QModelIndex bottom = createIndex(rowCount() - 1, 0);
    emit dataChanged(top, bottom);
    setnumIndicatori(rowCount()); // passo il totale degli elementi
    setTotTile(rowCount()); // aggiorno la property con il totale mi serve il suo
    // emit x il qml
}

qint16 modello::numIndicatori() const { return m_numIndicatori; }

qint16 modello::totTile() const { return m_totTile; }

void modello::setnumIndicatori(qint16 numIndicatori)
{
    // divido x 6 perchè ho scelto di visualizzare 6 elemti alla volta
    if (numIndicatori % 6 == 0)
        m_numIndicatori = (numIndicatori / 6);
    else
        m_numIndicatori = (numIndicatori / 6) + 1;
    emit numIndicatoriChanged();
}

void modello::setTotTile(qint16 totTile)
{

    if (m_totTile == totTile)
        return;

    m_totTile = totTile;
    emit totTileChanged();
}

main.cpp

#include "filtro.h"
#include "modello.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QTimer>
int main(int argc, char *argv[])
{
#if defined(Q_OS_WIN)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;

    modello mioModello;
    // riempio il modello
    for (int i = 0; i < 10; i++)
    {
        mioModello.addRicetta("Pane", "red", 5, false);
        mioModello.addRicetta("Branzino", "orange", 3, true);
    }

    QTimer timer;
    QObject::connect(&timer, &QTimer::timeout, [&mioModello]()
    {
        mioModello.addRicetta("AAAA", "orange", 5, true);
    });
    timer.start(1000);

    Filtro filtroSuModello;
    filtroSuModello.setSourceModel(&mioModello);
    filtroSuModello.setFilterRole(mioModello.NomeRicetta);

    engine.rootContext()->setContextProperty("myModelFiltrato", &filtroSuModello);
    engine.rootContext()->setContextProperty("myModel", &mioModello);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;
    return app.exec();
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值