QTableView Model Delegate日期代理

首先继承QTableView 写一个TableView,这样时常带来一些方便

TableView.h

#ifndef TABLEVIEW_H
#define TABLEVIEW_H

#include <QTableView>



class TableView : public QTableView
{
    Q_OBJECT
public:
    TableView(QWidget* parent = nullptr);
    TableView(const QString& left_top_text, QWidget* parent = nullptr);


    QModelIndexList get_selected_idx_list() const;

    QModelIndex get_last_selected_idx() const;


//    int get_left_top_corner_widget_width() const;
//    void set_corner_widget_width(const int& width);




signals:
    // press ENTER add a space row
    void signal_add_a_space_row(const QModelIndex& idx);

    void signal_delete_selected_rows(const QModelIndexList& idx_list);


protected:
    void keyPressEvent(QKeyEvent* event) override;

    bool eventFilter(QObject* object, QEvent* event) override;




};

#endif // TABLEVIEW_H

TableView .cpp

#include "TableView.h"

#include <QKeyEvent>
#include <QHeaderView>
#include <QApplication>
#include <QStylePainter>
#include <QAbstractButton>
#include <QDebug>



TableView::TableView(QWidget* parent)
    : QTableView(parent)
{
    horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    setContextMenuPolicy(Qt::CustomContextMenu);
}



TableView::TableView(const QString& left_top_text, QWidget* parent)
    : QTableView(parent)
{
    horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    setContextMenuPolicy(Qt::CustomContextMenu);

    QAbstractButton* btn = findChild<QAbstractButton*>();
    if( btn )
    {
        btn->setText(left_top_text);
        btn->installEventFilter(this);

        QStyleOptionHeader opt;
        opt.text = btn->text();
        QSize size = btn->style()->sizeFromContents(QStyle::CT_HeaderSection, &opt, QSize(), btn).expandedTo(QApplication::globalStrut());

        if( size.isValid() )
        {
            verticalHeader()->setMinimumWidth(size.width());
        }
    }
}




//int
//TableView::get_left_top_corner_widget_width() const
//{
//    QAbstractButton* btn = findChild<QAbstractButton*>();
//    qDebug() << __FILE__ << __LINE__ << " btn->rect().width() " << btn->rect().width();

//    if( btn )
//    {
//        return btn->rect().width();
//    }

//    return 0;
//}


//void
//TableView::set_corner_widget_width(const int& width)
//{
//    QAbstractButton* btn = findChild<QAbstractButton*>();
//    if( btn )
//    {
//        btn->setMinimumWidth(width);
//    }
//}



QModelIndexList
TableView::get_selected_idx_list() const
{
    return selectionModel()->selectedIndexes();
}



QModelIndex
TableView::get_last_selected_idx() const
{
    const QModelIndexList& idx_list = this->get_selected_idx_list();

    return idx_list.isEmpty() ? QModelIndex() : idx_list.last();
}



void
TableView::keyPressEvent(QKeyEvent* event)
{
    //qDebug() << __FILE__ << __LINE__ << " event = " << event;
    const int& key = event->key();

    if( Qt::Key_Enter == key || Qt::Key_Return == key )
    {
        const QModelIndex& idx = get_last_selected_idx();
        emit signal_add_a_space_row( idx );
    }
    else if( Qt::Key_Delete == key || Qt::Key_Backspace == key )
    {
        const QModelIndexList& idx_list = this->get_selected_idx_list();
        emit signal_delete_selected_rows(idx_list);
    }

    QTableView::keyPressEvent(event);
}



bool
TableView::eventFilter(QObject* object, QEvent* event)
{
    if( event->type() == QEvent::Paint )
    {
        QAbstractButton* btn = qobject_cast<QAbstractButton*>(object);
        if(btn)
        {
            QStyleOptionHeader opt;
            opt.init(btn);
            QStyle::State state = QStyle::State_None;

            if( btn->isEnabled() )
            {
                state |= QStyle::State_Enabled;
            }
            else if( btn->isActiveWindow() )
            {
                state |= QStyle::State_Active;
            }
            else if( btn->isDown() )
            {
                state |= QStyle::State_Sunken;
            }

            opt.state = state;
            opt.rect = btn->rect();
            opt.text = btn->text();
            opt.position = QStyleOptionHeader::OnlyOneSection;
            opt.textAlignment = Qt::AlignCenter;

            QStylePainter painter(btn);
            painter.drawControl(QStyle::CE_Header, opt);

            return true;
        }
    }

    return false;
}

Model主要是组装数据的

GoodsModel.h

#ifndef GOODSMODEL_H
#define GOODSMODEL_H

#include <QAbstractTableModel>


class DBUtil;
class GoodsItem;

/**
 *
 */
class GoodsModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    GoodsModel(QObject* parent = 0);
    ~GoodsModel();




public:
    void clear_all();

    void refresh();


//    const QModelIndex get_idx_from_mat_name(const QString& material_name);

    int get_id_from_idx(const QModelIndex& idx) const;

    void delete_line(const QModelIndex& idx);



public:
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;

    QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const;

    int rowCount(const QModelIndex& parent = QModelIndex()) const;
    int columnCount(const QModelIndex& parent = QModelIndex()) const;
    //bool hasChildren(const QModelIndex &parent = QModelIndex()) const;//

    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;

    Qt::ItemFlags flags(const QModelIndex& index) const;

    // when click revalue need
    bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);


private:
    void init_data();



private:
    DBUtil* d_db_util;


private:
    QStringList d_head_names;

    QVector<GoodsItem*> d_items;



};

#endif // GOODSMODEL_H

GoodsModel.cpp

#include "GoodsModel.h"
#include "GoodsItem.h"
#include "database/DBUtil.h"
#include "database/table/GoodsTable.h"


#include <QDebug>



GoodsModel::GoodsModel(QObject* parent)
    : QAbstractTableModel(parent),
      d_db_util(0)
{
    d_head_names << QStringLiteral("商品名称")
                 << QStringLiteral("编号")
                 << QStringLiteral("入库日期")
                 << QStringLiteral("标价")
                 << QStringLiteral("成本")
                 << QStringLiteral("售价")
                 << QStringLiteral("出售日期");

    d_db_util = new DBUtil();
    init_data();
}



GoodsModel::~GoodsModel()
{
    clear_all();

    if( !d_head_names.isEmpty() )
    {
        d_head_names.clear();
    }

    if( d_db_util )
    {
        d_db_util->close();

        delete d_db_util;
        d_db_util = 0;
    }
}



void
GoodsModel::clear_all()
{
    if( d_items.isEmpty() )
    {
        return;
    }

    beginResetModel();

    for( QVector<GoodsItem*>::Iterator pos = d_items.begin();
         pos != d_items.end(); pos++)
    {
        delete *pos;
        *pos = 0;
    }

    d_items.clear();

    endResetModel();
}



void
GoodsModel::init_data()
{
    GoodsTable table;
    const QString& sql_str = table.get_select_goods_sql_str();
    const QVector<QMap<QString, QString> >& result_data = d_db_util->select_data(sql_str);
    if( result_data.empty() )
    {
        return;
    }
    //qDebug() << __FILE__ << __LINE__ << " result_data = " << result_data;

    clear_all();

    beginResetModel();

    GoodsItem* item;
    QMap<QString, QString> column_data;

    for(int i = 0; i < result_data.size(); i++)
    {
        column_data = result_data.at(i);

        item = new GoodsItem();
        item->d_id = column_data["id"].toInt();
        item->d_name = column_data["name"];
        item->d_number = column_data["number"];
        item->d_indate = column_data["indate"];
        item->d_marked_price = column_data["marked_price"];
        item->d_cost = column_data["cost"];

        item->d_selling_price = column_data["selling_price"];
        item->d_sell_date = column_data["sell_date"];

        //qDebug() << __FILE__ << __LINE__ << " d_name = " << item->d_name;
        d_items.push_back(item);
    }

    endResetModel();
}



void
GoodsModel::refresh()
{
    init_data();
}



//const QModelIndex
//GoodsModel::get_idx_from_mat_name(const QString& material_name)
//{
//    int row = -1;

//    for( int i = 0; i < d_items.size(); i++)
//    {
//        if( d_items.at(i)->d_material_name == material_name )
//        {
//            row = i;
//            break;
//        }
//    }

//    if( row == -1 )
//    {
//        return QModelIndex();
//    }

//    return index(row);
//}



int
GoodsModel::get_id_from_idx(const QModelIndex& idx) const
{
    if( !idx.isValid() )
    {
        return -1;
    }

    GoodsItem* item = (GoodsItem*)idx.internalPointer();

    return item->d_id;
}



void
GoodsModel::delete_line(const QModelIndex& idx)
{
    if( !idx.isValid() )
    {
        return;
    }

    beginResetModel();

    const int& pos = idx.row();
    const int& id = d_items.at(pos)->d_id;

    GoodsTable table;
    const QString& sql_str = table.get_delete_sql_str_from_goods_id(id);
    d_db_util->delete_data(sql_str);

    d_items.remove(pos);

    endResetModel();
}



QVariant
GoodsModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    //qDebug() << __FILE__ << __LINE__ << " headerData ";
    if( Qt::DisplayRole == role &&
        Qt::Horizontal == orientation &&
        section < d_head_names.size() )
    {
        return d_head_names.at(section);
    }

    return QAbstractTableModel::headerData(section, orientation, role);
}



QModelIndex
GoodsModel::index(int row, int column, const QModelIndex& parent) const
{
    if( parent.isValid() )
    {
        return QModelIndex();
    }

    if( row < d_items.size() )
    {
        return createIndex(row, column, d_items.at(row));
    }

    return QModelIndex();
}



int
GoodsModel::rowCount(const QModelIndex& parent) const
{
    Q_UNUSED(parent);
    return d_items.size();
}



int
GoodsModel::columnCount(const QModelIndex& parent) const
{
    Q_UNUSED(parent);
    return d_head_names.size();
}



QVariant
GoodsModel::data(const QModelIndex& index, int role) const
{
    if( !index.isValid() )
    {
        return QVariant();
    }

    GoodsItem* item = (GoodsItem*)index.internalPointer();
    if( Qt::DisplayRole == role )
    {
        return item->get_value_from_idx(index.column());
    }

    return QVariant();
}



Qt::ItemFlags
GoodsModel::flags(const QModelIndex& index) const
{
    Q_UNUSED(index);
    Qt::ItemFlags flag = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
    return flag;
}



bool
GoodsModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
    if( !index.isValid() )
    {
        return false;
    }

    if( role != Qt::DisplayRole && role != Qt::EditRole )
    {
        return false;
    }

    GoodsItem* item = (GoodsItem*)index.internalPointer();
    if( !item )
    {
        return false;
    }

    if( value.toString().isEmpty() )
    {
        return false;
    }

    const int& column = index.column();
    if( column == 3 || column == 4 || column == 5 )
    {
        bool ok = true;
        value.toDouble(&ok);
        if( !ok )
        {
            // 说明价格不是数字
            return false;
        }
    }

    item->set_value_from_model_edit(index.column(), value);

    GoodsTable table;
    const QString& sql = table.get_update_sql_str(*item);
    //qDebug() << __FILE__ << __LINE__ << " sql = " << sql;

    DBUtil db_util;
    db_util.update_data(sql);

    return true;
}

Item单个数据元素

GoodsItem.h

#ifndef GOODSITEM_H
#define GOODSITEM_H

#include <QString>
#include <QVariant>



class GoodsItem
{
public:
    GoodsItem();


    QVariant get_value_from_idx(const int& idx);

    void set_value_from_model_edit(const int& idx, const QVariant& value);




public:
    int d_id;

    // 名称
    QString d_name;
    // 编号
    QString d_number;
    // 入库日期
    QString d_indate;
    // 标价
    QString d_marked_price;
    // 成本
    QString d_cost;

    //---------------
    // 售价
    QString d_selling_price;
    // 出售日期
    QString d_sell_date;


};

#endif // GOODSITEM_H

GoodsItem.cpp

#include "GoodsItem.h"

#include <QDebug>



GoodsItem::GoodsItem()
{

}



QVariant
GoodsItem::get_value_from_idx(const int& idx)
{
    switch (idx) {
    case 0:
        return d_name;
    case 1:
        return d_number;
    case 2:
        return d_indate;
    case 3:
        return d_marked_price;
    case 4:
        return d_cost;
    case 5:
        return d_selling_price;
    case 6:
        return d_sell_date;
    default:
        qDebug() << __FILE__ << __LINE__ << " warning: idx = " + idx;
        break;
    }

    return QVariant();
}



void
GoodsItem::set_value_from_model_edit(const int& idx, const QVariant& value)
{
    QString val = value.toString();

    switch (idx) {
    case 0:
        d_name = val;
        break;
    case 1:
        d_number = val;
        break;
    case 2:
        d_indate = val;
        break;
    case 3:
        d_marked_price = val;
        break;
    case 4:
        d_cost = val;
        break;
    case 5:
        d_selling_price = val;
        break;
    case 6:
        d_sell_date = val;
        break;
    default:
        qDebug() << __FILE__ << __LINE__ << " warning: idx = " + idx;
        break;
    }
}

Delegate鼠标点击单元格时,变成编辑状态,比如变成QCheckBox、QSpinBox、QDateTimeEdit、QDateEdit

这里写了一个日期代理

DateDelegate.h

#ifndef DATEDELEGATE_H
#define DATEDELEGATE_H

#include <QItemDelegate>


class DateDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    DateDelegate(QObject* parent = nullptr);



    QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const;
    void setEditorData(QWidget* editor, const QModelIndex& index) const;
    void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const;
    void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const  QModelIndex& index) const;


};

#endif // DATEDELEGATE_H

DateDelegate.cpp

#include "DateDelegate.h"

#include <QDateEdit>
#include <QDebug>


DateDelegate::DateDelegate(QObject* parent)
    : QItemDelegate(parent)
{
}



QWidget*
DateDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem &/*option*/, const QModelIndex& index) const
{
    QString str =index.model()->data(index).toString();

    QDateEdit* editor = new QDateEdit(parent);
    editor->setDisplayFormat("yyyy/M/d");
    editor->setCalendarPopup(true);
    editor->setDate(QDate::fromString(str, "yyyy/M/d"));

    return editor;
}



void
DateDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
    QString str = index.model()->data(index).toString();

    QDateEdit* date = static_cast<QDateEdit*>(editor);
    date->setDate(QDate::fromString(str, "yyyy/M/d"));
}



void
DateDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
    QDateEdit* date = static_cast<QDateEdit*>(editor);
    QString str = date->date().toString("yyyy/M/d");
    //qDebug() <<__FILE__<<__LINE__<< " str = " << str;

    model->setData(index, str);
}



void
DateDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& /*index*/) const
{
    editor->setGeometry(option.rect);
}

model里面有一些数据库操作,自行替换O(∩_∩)O哈哈~

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值