Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
Executable
+64
@@ -0,0 +1,64 @@
|
||||
#
|
||||
# CMakeLists.txt for Data View
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Mike Wille, SLSE, 2016-06-15
|
||||
#
|
||||
|
||||
SET(ltsDataView_SRCS
|
||||
lts_data_view_export.h
|
||||
lts_data_view.h
|
||||
lts_data_view.cpp
|
||||
abstract_display_widget.h
|
||||
abstract_display_widget.cpp
|
||||
search_model.cpp
|
||||
search_model.h
|
||||
tree_view.cpp
|
||||
tree_view.h
|
||||
check_state_proxy_model.h
|
||||
check_state_proxy_model.cpp
|
||||
tree_view_delegate.cpp
|
||||
tree_view_delegate.h
|
||||
icon_view_delegate.cpp
|
||||
icon_view_delegate.h
|
||||
data_delegate.cpp
|
||||
data_delegate.h
|
||||
lts_columns_setting.cpp
|
||||
lts_columns_setting.h
|
||||
lts_columns_setting.cpp
|
||||
lts_columns_setting.h
|
||||
)
|
||||
|
||||
NGL_WRAP_UI(ltsDataView_SRCS
|
||||
lts_data_view.ui
|
||||
lts_columns_setting.ui
|
||||
lts_columns_setting.ui
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(WS LtsDataView SHARED ${ltsDataView_SRCS})
|
||||
|
||||
NGL_TARGET_LINK_LIBRARIES(LtsDataView
|
||||
PRIVATE
|
||||
LtsWidgets
|
||||
LtsUtilsSettings
|
||||
ngltools
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
Qt5::Widgets
|
||||
)
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(LtsDataView
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
)
|
||||
NGL_INSTALL_TARGET(LtsDataView)
|
||||
|
||||
|
||||
# Test-Executable
|
||||
NGL_ADD_EXECUTABLE(WS NO_TRANSLATION LtsDataViewTest test.h test.cpp)
|
||||
NGL_TARGET_LINK_LIBRARIES(LtsDataViewTest
|
||||
Qt5::Widgets
|
||||
LtsDataView
|
||||
LtsWidgets
|
||||
)
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Abstract Display Widget is an Abstract class to create Custom Display Widgets for the Custom View
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Mike Wille, SLSE, 2016-06-15
|
||||
*/
|
||||
|
||||
#include "abstract_display_widget.h"
|
||||
#include <QModelIndex>
|
||||
|
||||
namespace LtsDataView
|
||||
{
|
||||
AbstractDisplayWidget::AbstractDisplayWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
setAutoFillBackground(true);
|
||||
}
|
||||
|
||||
QVariant AbstractDisplayWidget::rowData(const QModelIndex &idx, int column, int role) const
|
||||
{
|
||||
const QModelIndex rowIdx(idx.column() == column ? idx : idx.model()->index(idx.row(), column));
|
||||
return idx.model()->data(rowIdx, role);
|
||||
}
|
||||
|
||||
|
||||
} // namespace LtsDataView
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Abstract Display Widget is an Abstract class to create Custom Display Widgets for the Custom View
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Mike Wille, SLSE, 2016-06-15
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "lts_data_view_export.h"
|
||||
|
||||
#include <QWidget>
|
||||
class QModelIndex;
|
||||
|
||||
namespace LtsDataView
|
||||
{
|
||||
class LTSDATAVIEW_EXPORT AbstractDisplayWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AbstractDisplayWidget(QWidget *parent = nullptr);
|
||||
virtual bool init(const QModelIndex &idx) = 0;
|
||||
|
||||
protected:
|
||||
QVariant rowData(const QModelIndex &idx, int column, int role = Qt::DisplayRole) const;
|
||||
};
|
||||
} // namespace LtsDataView
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Implementation of CheckStateProxyModel
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl/Christian Froebel, NLE, 2019-05-10
|
||||
*/
|
||||
|
||||
#include "check_state_proxy_model.h"
|
||||
|
||||
namespace LtsDataView
|
||||
{
|
||||
Qt::ItemFlags CheckStateProxyModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return sourceModel()->flags(index); // delegate to source model for further processing if necessary
|
||||
|
||||
// Sets only the checkbox nodes on user checkable,
|
||||
// checkbox leaves must be handled in source model.
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
Qt::ItemFlags fl = sourceModel()->flags(sourceIndex);
|
||||
if (index.column() == 0)
|
||||
return fl | Qt::ItemIsUserCheckable;
|
||||
return fl;
|
||||
}
|
||||
|
||||
|
||||
QVariant CheckStateProxyModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
|
||||
// delegate everything except CheckStateRole to source model
|
||||
if (role != Qt::CheckStateRole)
|
||||
return sourceModel()->data(sourceIndex, role);
|
||||
|
||||
// delegate a leaf too with CheckStateRole to source model
|
||||
if (isLeaf(index))
|
||||
return sourceModel()->data(sourceIndex, role);
|
||||
|
||||
// delegate to source model for further processing of further columns if necessary
|
||||
if (index.column() != 0)
|
||||
return sourceModel()->data(sourceIndex, role);
|
||||
|
||||
// sets the node checkboxes and decoration depending on the entries in the tree structure
|
||||
int checkedCount = 0;
|
||||
int childCount = rowCount(index);
|
||||
for (int childRow = 0; childRow < childCount; ++childRow)
|
||||
{
|
||||
QModelIndex childIndex = this->index(childRow, 0, index);
|
||||
Qt::CheckState checkState = data(childIndex, Qt::CheckStateRole).value<Qt::CheckState>();
|
||||
if (checkState == Qt::PartiallyChecked)
|
||||
return Qt::PartiallyChecked;
|
||||
if (checkState == Qt::Checked)
|
||||
++checkedCount;
|
||||
}
|
||||
if (checkedCount == childCount)
|
||||
return Qt::Checked;
|
||||
else if (checkedCount == 0)
|
||||
return Qt::Unchecked;
|
||||
else
|
||||
return Qt::PartiallyChecked;
|
||||
}
|
||||
|
||||
|
||||
bool CheckStateProxyModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return false;
|
||||
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
|
||||
// delegate to source model for further processing of further columns if necessary
|
||||
if (index.column() != 0)
|
||||
return sourceModel()->setData(sourceIndex, value, role);
|
||||
|
||||
// delegate everything except CheckStateRole to source mode
|
||||
if (role != Qt::CheckStateRole)
|
||||
return sourceModel()->setData(sourceIndex, value, role);
|
||||
|
||||
if (isLeaf(index))
|
||||
{
|
||||
// delegate a leaf to source model
|
||||
sourceModel()->setData(sourceIndex, value, role);
|
||||
|
||||
// update parents recursively here
|
||||
QModelIndex idx = index.parent();
|
||||
do
|
||||
{
|
||||
emit dataChanged(idx, idx, {Qt::CheckStateRole});
|
||||
idx = idx.parent();
|
||||
}
|
||||
while (idx.isValid());
|
||||
return true;
|
||||
}
|
||||
|
||||
// update underlying children recursively (Additional nodes with leaves may also exist)
|
||||
int childCount = rowCount(index);
|
||||
for (int childRow = 0; childRow < childCount; ++childRow)
|
||||
{
|
||||
QModelIndex childIndex = this->index(childRow, 0, index);
|
||||
setData(childIndex, value, Qt::CheckStateRole);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CheckStateProxyModel::isLeaf(const QModelIndex &index) const
|
||||
{
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
return sourceModel()->flags(sourceIndex).testFlag(Qt::ItemIsUserCheckable);
|
||||
}
|
||||
|
||||
|
||||
} // namespace InfrastructureManagement
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The model is used to handle CheckState Boxes in an LtsDataView (QTreeModel).
|
||||
* Only the nodes of a TreeView are handled in this model. Leaves are forwarded to the transferred model and must be edited there.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl/Christian Froebel, NLE, 2019-05-10
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QIdentityProxyModel>
|
||||
|
||||
#include "lts_data_view_export.h"
|
||||
|
||||
namespace LtsDataView
|
||||
{
|
||||
|
||||
class LTSDATAVIEW_EXPORT CheckStateProxyModel : public QIdentityProxyModel
|
||||
{
|
||||
public:
|
||||
using QIdentityProxyModel::QIdentityProxyModel;
|
||||
|
||||
/**
|
||||
* Handles the 'ItemIsUserCheckable' flags
|
||||
* @param[in] sourceModel index
|
||||
*
|
||||
*/
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
/**
|
||||
* Handles the representation of data
|
||||
* @param[in] sourceModel index
|
||||
* @param[in] role role to which the data relates
|
||||
*
|
||||
*/
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
/**
|
||||
* Handles the storage of data
|
||||
* @param[in] index index
|
||||
* @param[in] value value to be set
|
||||
* @param[in] role role to which the data relates
|
||||
*
|
||||
*/
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Returns true if the item with the given index is an leaf
|
||||
* @param[in] index item index whose information is requested
|
||||
* will be internally mapped to source model data
|
||||
*/
|
||||
bool isLeaf(const QModelIndex &index) const;
|
||||
|
||||
}; // class CheckStateProxyModel
|
||||
} // namespace LtsDataView
|
||||
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Renders complex types from model data to text for views
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Mike Wille, NLE, 2020-09-09
|
||||
*/
|
||||
|
||||
#include "data_delegate.h"
|
||||
|
||||
#include <ngltools/ngltools_dtg.h>
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
|
||||
namespace LtsDataView
|
||||
{
|
||||
DataDelegate::DataDelegate(QObject *parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
{}
|
||||
|
||||
|
||||
QString DataDelegate::displayText(const QVariant &value, const QLocale &locale) const
|
||||
{
|
||||
if (value.type() == QVariant::Type::DateTime)
|
||||
return DTG::toString(value.toDateTime());
|
||||
return QStyledItemDelegate::displayText(value, locale);
|
||||
}
|
||||
} // namespace LtsDataView
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Renders complex types from model data to text for views
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Mike Wille, NLE, 2020-09-09
|
||||
*/
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
|
||||
namespace LtsDataView
|
||||
{
|
||||
class DataDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DataDelegate(QObject *parent);
|
||||
QString displayText(const QVariant &value, const QLocale &locale) const override;
|
||||
};
|
||||
} // namespace LtsDataView
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
#include "icon_view_delegate.h"
|
||||
|
||||
#include <QGraphicsDropShadowEffect>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsPixmapItem>
|
||||
#include <QPainter>
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
namespace LtsDataView
|
||||
{
|
||||
static constexpr int s_shadowRadius = 22;
|
||||
|
||||
void IconViewDelegate::setDisplayWidgetCreator(const std::function<AbstractDisplayWidget*()> &customDisplayWidgetCreator)
|
||||
{
|
||||
m_customDisplayWidgetCreator = customDisplayWidgetCreator;
|
||||
|
||||
QScopedPointer<AbstractDisplayWidget> dw(m_customDisplayWidgetCreator());
|
||||
if (!dw)
|
||||
{
|
||||
qWarning() << "IconViewDelegate::setDisplayWidgetCreator: delegate is not a base of AbstractDisplayWidget!";
|
||||
Q_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
m_displayWidgetSize = dw->size() + QSize(s_shadowRadius * 2, s_shadowRadius * 2);
|
||||
}
|
||||
|
||||
|
||||
QSize IconViewDelegate::sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const
|
||||
{
|
||||
return m_displayWidgetSize;
|
||||
}
|
||||
|
||||
void IconViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
QScopedPointer<AbstractDisplayWidget> dw(m_customDisplayWidgetCreator());
|
||||
|
||||
if (!dw)
|
||||
{
|
||||
qWarning() << "IconViewDelegate::paint: delegate is not a base of AbstractDisplayWidget!";
|
||||
Q_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dw->init(index))
|
||||
{
|
||||
qWarning() << "IconViewDelegate::paint: delegate could not create ui";
|
||||
return;
|
||||
}
|
||||
|
||||
const auto dpr = dw->devicePixelRatioF();
|
||||
QPixmap p(dw->size() * dpr);
|
||||
p.setDevicePixelRatio(dpr);
|
||||
QPainter myPainter(&p);
|
||||
dw->render(&myPainter);
|
||||
myPainter.end();
|
||||
|
||||
// drop shadow
|
||||
QGraphicsDropShadowEffect *shadowEffect = new QGraphicsDropShadowEffect();
|
||||
shadowEffect->setBlurRadius(s_shadowRadius);
|
||||
shadowEffect->setOffset(0, 0); // center (shadow on all sides)
|
||||
|
||||
if (option.state & QStyle::State_Selected)
|
||||
shadowEffect->setColor(dw->palette().light().color());
|
||||
else
|
||||
shadowEffect->setColor(dw->palette().shadow().color());
|
||||
|
||||
// draw pixmap & shadow
|
||||
QGraphicsPixmapItem *item = new QGraphicsPixmapItem(p);
|
||||
item->setGraphicsEffect(shadowEffect);
|
||||
|
||||
// TODO: avoid creating a QGraphicsScene by using QGraphicsItem::paint()
|
||||
QGraphicsScene scene;
|
||||
scene.addItem(item);
|
||||
scene.render(painter, option.rect, QRectF(-s_shadowRadius, -s_shadowRadius, option.rect.width(), option.rect.height()));
|
||||
}
|
||||
} // namespace LtsDataView
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "abstract_display_widget.h"
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
namespace LtsDataView
|
||||
{
|
||||
class IconViewDelegate final : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using QStyledItemDelegate::QStyledItemDelegate;
|
||||
void setDisplayWidgetCreator(const std::function<AbstractDisplayWidget*()> &customDisplayWidgetCreator);
|
||||
|
||||
QSize sizeHint(const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const;
|
||||
void paint(QPainter *painter,
|
||||
const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const;
|
||||
|
||||
private:
|
||||
std::function<AbstractDisplayWidget*()> m_customDisplayWidgetCreator;
|
||||
QSize m_displayWidgetSize;
|
||||
};
|
||||
} // namespace LtsDataView
|
||||
+231
@@ -0,0 +1,231 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* LtsColumnsSettingWidget Organise table columns
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Steve Kemayou, ESZS, 2025-03-19
|
||||
*/
|
||||
|
||||
|
||||
#include "lts_columns_setting.h"
|
||||
#include "ui_lts_columns_setting.h"
|
||||
|
||||
#include<QDebug>
|
||||
namespace LtsDataView
|
||||
{
|
||||
LtsColumnsSettingWidget::LtsColumnsSettingWidget(const QVector<ColumnOrganiserInfo> &columnInfoVec, QWidget *parent)
|
||||
: LtsWidgets::LtsFramelessDialog(parent)
|
||||
, m_ui(new Ui::LtsColumnsSetting)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_model = new ColumnOrganiserModel(this);
|
||||
m_model->setModelData(columnInfoVec);
|
||||
m_ui->tableView->setModel(m_model);
|
||||
|
||||
for(const auto &ci : columnInfoVec)
|
||||
{
|
||||
if (ci.debugOnly){
|
||||
qDebug()<<">>>[LtsColumnsSettingWidgets] column to hide: id: "<<ci.logicalIndex;
|
||||
m_ui->tableView->hideRow(ci.logicalIndex);
|
||||
}
|
||||
}
|
||||
connect(m_ui->applyBtn, &QPushButton::clicked, this, &LtsColumnsSettingWidget::onApplyClicked);
|
||||
connect(m_ui->cancelBtn, &QPushButton::clicked, this, &LtsColumnsSettingWidget::onAbortClicked);
|
||||
connect(m_ui->resetBtn, &QPushButton::clicked, this, &LtsColumnsSettingWidget::onResetClicked);
|
||||
}
|
||||
|
||||
LtsColumnsSettingWidget::~LtsColumnsSettingWidget()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void LtsColumnsSettingWidget::onResetClicked()
|
||||
{
|
||||
emit columnsResetted();
|
||||
accept();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief LtsColumnsSettingWidget::onApplyClicked
|
||||
* send columns settings
|
||||
*/
|
||||
void LtsColumnsSettingWidget::onApplyClicked()
|
||||
{
|
||||
QVector<LtsDataView::ColumnOrganiserInfo> colInfoVec;
|
||||
const int rowCount = m_ui->tableView->model()->rowCount();
|
||||
colInfoVec.reserve(rowCount);
|
||||
for(int row = 0; row < rowCount; ++row)
|
||||
{
|
||||
const ColumnOrganiserInfo ci = m_ui->tableView->model()->data(m_model->index(row,0),Qt::UserRole).value<ColumnOrganiserInfo>();
|
||||
colInfoVec.push_back(ci);
|
||||
}
|
||||
emit columnVisibilityChanged(colInfoVec);
|
||||
accept();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief LtsColumnsSettingWidget::onAbortClicked
|
||||
*/
|
||||
void LtsColumnsSettingWidget::onAbortClicked()
|
||||
{
|
||||
reject();
|
||||
}
|
||||
|
||||
/// TABLE MODEL FOR COLUMN SETTINGS
|
||||
|
||||
/*!
|
||||
* \brief ColumnOrganiserModel::ColumnOrganiserModel
|
||||
* \param parent
|
||||
*/
|
||||
ColumnOrganiserModel::ColumnOrganiserModel(QObject *parent)
|
||||
:QAbstractTableModel(parent)
|
||||
{
|
||||
beginResetModel();
|
||||
m_vecData.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief ColumnOrganiserModel::setModelData
|
||||
* \param infos
|
||||
*/
|
||||
void ColumnOrganiserModel::setModelData(const QVector<ColumnOrganiserInfo> &infos)
|
||||
{
|
||||
for(const auto &data : infos)
|
||||
insertRow(data);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief ColumnOrganiserModel::insertRow
|
||||
* \param info
|
||||
*/
|
||||
void ColumnOrganiserModel::insertRow(const ColumnOrganiserInfo &info)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), m_vecData.size(), m_vecData.size());
|
||||
m_vecData.append(info);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief ColumnOrganiserModel::columnCount
|
||||
* \param parent
|
||||
* \return
|
||||
*/
|
||||
int ColumnOrganiserModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return 1; // list of Column header as rows with on column
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief ColumnOrganiserModel::rowCount
|
||||
* \param parent
|
||||
* \return
|
||||
*/
|
||||
int ColumnOrganiserModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return m_vecData.count();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief ColumnOrganiserModel::data
|
||||
* \param index
|
||||
* \param role
|
||||
* \return
|
||||
*/
|
||||
QVariant ColumnOrganiserModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if ((role != Qt::DisplayRole &&
|
||||
role != Qt::DecorationRole &&
|
||||
role != Qt::EditRole &&
|
||||
role != Qt::CheckStateRole &&
|
||||
role != Qt::UserRole) || !index.isValid() || index.row() >= m_vecData.size())
|
||||
return QVariant();
|
||||
|
||||
const ColumnOrganiserInfo ci = m_vecData.at(index.row());
|
||||
|
||||
if (role == Qt::CheckStateRole)
|
||||
{
|
||||
return ci.show;
|
||||
}
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
return ci.name;
|
||||
|
||||
if (role == Qt::UserRole)
|
||||
return QVariant::fromValue(ci);
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief ColumnOrganiserModel::setData
|
||||
* \param index
|
||||
* \param value
|
||||
* \param role
|
||||
* \return
|
||||
*/
|
||||
bool ColumnOrganiserModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
Q_UNUSED(value)
|
||||
if (role != Qt::EditRole && role != Qt::CheckStateRole)
|
||||
return false;
|
||||
|
||||
ColumnOrganiserInfo &ci = m_vecData[index.row()];
|
||||
|
||||
if (role == Qt::CheckStateRole)
|
||||
{
|
||||
ci.show = !ci.show;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (index.column())
|
||||
{
|
||||
case 0:
|
||||
return false;
|
||||
}
|
||||
|
||||
emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief ColumnOrganiserModel::flags
|
||||
* \param index
|
||||
* \return
|
||||
*/
|
||||
Qt::ItemFlags ColumnOrganiserModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
auto f = QAbstractTableModel::flags(index);
|
||||
if (!index.isValid())
|
||||
return f;
|
||||
|
||||
if (index.column() == 0)
|
||||
{
|
||||
f.setFlag(Qt::ItemIsUserCheckable);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief ColumnOrganiserModel::headerData
|
||||
* \param section
|
||||
* \param orientation
|
||||
* \param role
|
||||
* \return
|
||||
*/
|
||||
QVariant ColumnOrganiserModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal
|
||||
&& role == Qt::DisplayRole)
|
||||
{
|
||||
if (section == 0)
|
||||
return tr("Column Visibility");
|
||||
}
|
||||
return QAbstractTableModel::headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+84
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* LtsColumnsSetting Organise table columns
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Steve Kemayou, ESZS, 2025-03-19
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsDataView/lts_data_view_export.h>
|
||||
|
||||
#include "LtsWidgets/lts_frameless_dialog.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QDialog>
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
namespace Ui {
|
||||
class LtsColumnsSetting;
|
||||
}
|
||||
namespace LtsDataView
|
||||
{
|
||||
struct ColumnOrganiserInfo
|
||||
{
|
||||
int logicalIndex; // logicalIndex
|
||||
QString name;
|
||||
bool show;
|
||||
bool debugOnly = false; // column is only displayed in debug mode
|
||||
bool hide() const {return !show;}
|
||||
};
|
||||
|
||||
class ColumnOrganiserModel;
|
||||
|
||||
class LTSDATAVIEW_EXPORT LtsColumnsSettingWidget : public LtsWidgets::LtsFramelessDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LtsColumnsSettingWidget(const QVector<ColumnOrganiserInfo> &columnInfoVec, QWidget *parent = nullptr);
|
||||
~LtsColumnsSettingWidget();
|
||||
|
||||
signals:
|
||||
void columnVisibilityChanged(const QVector<ColumnOrganiserInfo> &data);
|
||||
void columnsResetted();
|
||||
|
||||
private slots:
|
||||
void onResetClicked();
|
||||
void onApplyClicked();
|
||||
void onAbortClicked();
|
||||
|
||||
|
||||
private:
|
||||
Ui::LtsColumnsSetting *m_ui;
|
||||
|
||||
ColumnOrganiserModel *m_model;
|
||||
};
|
||||
|
||||
class ColumnOrganiserModel final : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ColumnOrganiserModel(QObject *parent = nullptr);
|
||||
~ ColumnOrganiserModel(){}
|
||||
|
||||
void setModelData(const QVector<ColumnOrganiserInfo> &infos);
|
||||
protected:
|
||||
void insertRow(const ColumnOrganiserInfo &info);
|
||||
int columnCount(const QModelIndex &parent = QModelIndex())const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex() ) const override;
|
||||
QVariant data (const QModelIndex &index, int role = Qt::DisplayRole)const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override final;
|
||||
|
||||
private:
|
||||
|
||||
QVector<ColumnOrganiserInfo> m_vecData;
|
||||
};
|
||||
|
||||
} // namespace LtsDataView
|
||||
|
||||
Q_DECLARE_METATYPE(LtsDataView::ColumnOrganiserInfo)
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LtsColumnsSetting</class>
|
||||
<widget class="QWidget" name="LtsColumnsSetting">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="4">
|
||||
<widget class="QTableView" name="tableView">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>121</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="resetBtn">
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="applyBtn">
|
||||
<property name="text">
|
||||
<string>Apply</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QPushButton" name="cancelBtn">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Executable
+1323
File diff suppressed because it is too large.
Load diff
Executable
+225
@@ -0,0 +1,225 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* LtsDataView is the exported View, which contains and manages a Custom View and a Table View
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Mike Wille, SLSE, 2016-06-15
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <LtsDataView/lts_data_view_export.h>
|
||||
#include <LtsDataView/lts_columns_setting.h>
|
||||
|
||||
#include <QWidget>
|
||||
#include <QAbstractItemView>
|
||||
#include <QLineEdit>
|
||||
#include <functional>
|
||||
|
||||
|
||||
class QListView;
|
||||
class QTreeView;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class LtsDataView;
|
||||
}
|
||||
namespace LtsWidgets
|
||||
{
|
||||
class LtsColumnFilterProxyModel;
|
||||
struct ColumnOrganiserInfo;
|
||||
}
|
||||
|
||||
// TODO: doxy doku
|
||||
|
||||
namespace LtsDataView
|
||||
{
|
||||
class AbstractDisplayWidget;
|
||||
class SearchModel;
|
||||
|
||||
|
||||
class SearchLineEdit final : public QLineEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SearchLineEdit(QWidget *parent)
|
||||
: QLineEdit(parent)
|
||||
{
|
||||
setProperty("isSearchLineEdit", true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class LTSDATAVIEW_EXPORT LtsDataView : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool rootIsDecorated READ rootIsDecorated WRITE setRootIsDecorated)
|
||||
Q_PROPERTY(bool showColumnCount READ showColumnCount WRITE setColumnCountVisible)
|
||||
Q_PROPERTY(bool toolButtonsVisible READ toolButtonsVisible WRITE setToolButtonsVisible)
|
||||
Q_PROPERTY(bool alternatingRowColors READ alternatingRowColors WRITE setAlternatingRowColors)
|
||||
Q_PROPERTY(bool allColumnsShowFocus READ allColumnsShowFocus WRITE setAllColumnsShowFocus)
|
||||
Q_PROPERTY(bool autoResizeToContent READ autoResizeToContent WRITE setAutoResizeToContent)
|
||||
Q_PROPERTY(QAbstractItemView::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode)
|
||||
|
||||
public:
|
||||
enum Page
|
||||
{
|
||||
TABLE = 0,
|
||||
CUSTOM = 1,
|
||||
};
|
||||
|
||||
explicit LtsDataView(QWidget *parent = nullptr);
|
||||
~LtsDataView();
|
||||
|
||||
/** once you set the model without a ADW, the view cannot switch back to double-view mode!
|
||||
*
|
||||
*/
|
||||
void setModel(QAbstractItemModel *model, const std::function<AbstractDisplayWidget*()> &customDisplayWidgetCreator = nullptr);
|
||||
QAbstractItemModel *sourceModel() const;
|
||||
LtsWidgets::LtsColumnFilterProxyModel *proxyModel() const;
|
||||
QItemSelectionModel *selectionModel() const;
|
||||
SearchModel *searchModel() const;
|
||||
|
||||
QTreeView *treeView();
|
||||
const QTreeView *treeView() const;
|
||||
QTreeView *searchView();
|
||||
const QTreeView *searchView() const;
|
||||
QListView *getCustomView();
|
||||
QWidget *customWidget() const;
|
||||
void setCustomWidget(QWidget *customWidget); // not visible in seamless mode
|
||||
|
||||
QModelIndexList selectedRows(int column = 0) const; // TODO: returns indexes instead of rows if in custom view ... change naming?
|
||||
void selectRow(const QModelIndex &idxSource);
|
||||
void clearSelection();
|
||||
void setSelectionMode(QAbstractItemView::SelectionMode selectionMode);
|
||||
QAbstractItemView::SelectionMode selectionMode() const;
|
||||
QModelIndex currentIndex() const;
|
||||
void setCurrentIndex(const QModelIndex &idx); // also makes sure that the current index is visible (QAIV::scrollTo())
|
||||
void scrollTo(const QModelIndex &idxSource);
|
||||
|
||||
void moveSection(int from, int to);
|
||||
void seamless();
|
||||
|
||||
void setViewHeaderMovable(bool state);
|
||||
void moveSections(const QMap<int, int> &list); /// logicalIndex (key) visualIndex(value)
|
||||
|
||||
void saveTableSettings(bool defaultSetting = false);/// if defaultSetting true, the default order of the table will be restore and save
|
||||
bool restoreTableSettings();
|
||||
QString getOperatorColIdentifier() const;
|
||||
QVector<ColumnOrganiserInfo> getColumnOrganiserSetting();
|
||||
QString columnOrganiserGroup() const;
|
||||
void setColumnViewFromSetting();
|
||||
void setColumnsOrganiserEnabled(const QString &tableIdentifier, bool enable = false);
|
||||
|
||||
void setRootIsDecorated(bool isDecorated);
|
||||
bool rootIsDecorated() const;
|
||||
void setAlternatingRowColors(bool enable);
|
||||
bool alternatingRowColors() const;
|
||||
|
||||
void setColumnCountVisible(bool bVisible);
|
||||
bool showColumnCount() const;
|
||||
void setToolButtonsVisible(bool bVisible);
|
||||
bool toolButtonsVisible() const;
|
||||
void setAllColumnsShowFocus(bool enable);
|
||||
bool allColumnsShowFocus() const;
|
||||
void hideColumn(int column, bool debugMode = false);
|
||||
void showColumn(int column);
|
||||
bool isColumnHidden(int column) const;
|
||||
void setColumnHidden(int column, bool hide);
|
||||
|
||||
void setAutoResizeToContent(bool enable);
|
||||
bool autoResizeToContent() const;
|
||||
void resizeSection(int logicalIndex, int size);
|
||||
void resizeHeadersByContent();
|
||||
void resizeColumnsToContent();
|
||||
void syncSearchHeaderAndTableContentColumnSize();
|
||||
void setRootIndex(const QModelIndex &srcIndex);
|
||||
|
||||
/**
|
||||
* @brief See QHeaderview::setSortIndicator
|
||||
*/
|
||||
void setSortIndicator(int logicalIndex, Qt::SortOrder order);
|
||||
void setSortIndicatorShown(bool show = true);
|
||||
|
||||
Qt::ContextMenuPolicy contextMenuPolicyPerView(Page page) const;
|
||||
void setContextMenuPolicyPerView(Page page, Qt::ContextMenuPolicy policy);
|
||||
|
||||
QModelIndex mapFromSource(const QModelIndex &mi) const;
|
||||
QModelIndex mapToSource(const QModelIndex &mi) const;
|
||||
QModelIndexList mapToSource(const QModelIndexList &mil) const;
|
||||
QItemSelection mapSelectionToSource(const QItemSelection &is) const;
|
||||
|
||||
bool setInitialSearchContent(int section, const QVariant &filterData);
|
||||
void setIconSize(const QSize &size);
|
||||
|
||||
QByteArray saveState() const;
|
||||
bool restoreState(const QByteArray &headerState);
|
||||
|
||||
private:
|
||||
Ui::LtsDataView *m_ui;
|
||||
LtsWidgets::LtsColumnFilterProxyModel *m_columnFilterProxy;
|
||||
SearchModel *m_searchModel;
|
||||
bool m_bOwnProxy;
|
||||
bool m_autoResizeToConent{true};
|
||||
QString m_tableObjIdentifier; // identifier for column Organiser
|
||||
bool m_userChangedColumnPos = false;
|
||||
QSet<int> m_DebugModeColIds; /// column which are only visible in debug mode
|
||||
|
||||
QString createCsv() const;
|
||||
void addTouchScroll(QWidget *widget);
|
||||
QAbstractItemView *currentView() const;
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
|
||||
public slots:
|
||||
void selectTableView();
|
||||
void selectCustomView();
|
||||
void selectView(Page page);
|
||||
void slotCopyToClipboard();
|
||||
void collapseAll();
|
||||
void expandAll();
|
||||
void expand(const QModelIndex &index);
|
||||
void setSortingEnabled(bool enable);
|
||||
void slotSetHorizontalRange(int, int);
|
||||
void updateColumnsVisibility(const QVector<ColumnOrganiserInfo> &data);
|
||||
void slotSetColumnsDefaultOrder();
|
||||
private slots:
|
||||
void slotSetSortIndicator(int logicalIndex, Qt::SortOrder order);
|
||||
void slotRowCountChanged();
|
||||
void slotSetHorizontalValue(int);
|
||||
void slotSetVerticalRange(int x = 0, int y = 0);
|
||||
void slotSetVerticalValue(int);
|
||||
void slotSectionResized(int, int, int);
|
||||
void slotHeaderMoved(int, int, int);
|
||||
void slotCsvExport();
|
||||
void slotResizeColumn(int columnIndex);
|
||||
void onCustomContextMenuRequested(const QPoint &pos);
|
||||
void slotColumnOrganiserDialog();
|
||||
|
||||
|
||||
signals:
|
||||
void signalEnterPressed();
|
||||
void signalEntered(const QModelIndex &index);
|
||||
|
||||
// These are only emitted from the TableView
|
||||
void clicked(const QModelIndex &index);
|
||||
void doubleClicked(const QModelIndex &index);
|
||||
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
|
||||
void activated(const QModelIndex &index);
|
||||
|
||||
// These are emitted from both
|
||||
void signalSelectionChanged();
|
||||
void signalDoubleClicked();
|
||||
// signalContextMenuRequested requires setContextMenuPolicyPerView to be set
|
||||
void signalContextMenuRequested(const QPoint &globalPos, const QModelIndex &indexSrc);
|
||||
|
||||
// custom signals (@Filip)
|
||||
void filterChanged();
|
||||
void sortOrderChanged(const int &column, const Qt::SortOrder &order);
|
||||
|
||||
};
|
||||
} // namespace LtsDataView
|
||||
Executable
+367
@@ -0,0 +1,367 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LtsDataView</class>
|
||||
<widget class="QWidget" name="LtsDataView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>556</width>
|
||||
<height>350</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="lblRows">
|
||||
<property name="text">
|
||||
<string>Rows:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbRows">
|
||||
<property name="text">
|
||||
<string notr="true">0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="customWidget" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="tbColumnOrganiser">
|
||||
<property name="whatsThis">
|
||||
<string>Save selected line(s) as csv to a selected file with headers</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Column Setting</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="tbCsvExport">
|
||||
<property name="whatsThis">
|
||||
<string>Save selected line(s) as csv to a selected file with headers</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>CSV Export</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="tbCopy">
|
||||
<property name="whatsThis">
|
||||
<string>Copy selected line(s) as csv to clipboard without headers</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Copy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="tbTable">
|
||||
<property name="text">
|
||||
<string>Table</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="tbCustom">
|
||||
<property name="text">
|
||||
<string>Custom</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QVBoxLayout" name="oneTableLayout" stretch="1,0">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="LtsDataView::TreeView" name="searchView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="autoScroll">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="autoScrollMargin">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::CurrentChanged|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectItems</enum>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="itemsExpandable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="headerShowSortIndicator" stdset="0">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>255</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="TableView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="LtsDataView::TreeView" name="tableView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="headerVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="CustomView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QListView" name="customView">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragDrop</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="movement">
|
||||
<enum>QListView::Free</enum>
|
||||
</property>
|
||||
<property name="flow">
|
||||
<enum>QListView::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="viewMode">
|
||||
<enum>QListView::IconMode</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QScrollBar" name="verticalScrollBar">
|
||||
<property name="maximum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QScrollBar" name="horizontalScrollBar">
|
||||
<property name="maximum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QWidget" name="nullWidget" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LtsDataView::TreeView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header location="global">tree_view.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>tableView</tabstop>
|
||||
<tabstop>searchView</tabstop>
|
||||
<tabstop>tbCsvExport</tabstop>
|
||||
<tabstop>tbCopy</tabstop>
|
||||
<tabstop>tbTable</tabstop>
|
||||
<tabstop>tbCustom</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Export definitions
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifndef LTSDATAVIEW_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define LTSDATAVIEW_EXPORT
|
||||
# else
|
||||
# if defined(MAKE_LTSDATAVIEW_LIB)
|
||||
# define LTSDATAVIEW_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define LTSDATAVIEW_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
Executable
+156
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Search Model for TableViews (has the ability to give the user a row for searching data)
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Mike Wille, SLSE, 2016-03-14
|
||||
*/
|
||||
|
||||
#include "search_model.h"
|
||||
|
||||
#include <QFont>
|
||||
#include <QGuiApplication>
|
||||
#include <QIcon>
|
||||
#include <QPalette>
|
||||
#include <LtsWidgets/lts_column_filter_proxy_model.h>
|
||||
|
||||
namespace LtsDataView
|
||||
{
|
||||
SearchModel::SearchModel(QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
, m_searchIcon(QIcon(QStringLiteral("icon:show.svg")))
|
||||
{
|
||||
}
|
||||
|
||||
int SearchModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid()) return 0;
|
||||
if (!m_sourceModel) return 0;
|
||||
// no parent here - the given model index has nothing to do with the source model
|
||||
return m_sourceModel->columnCount(QModelIndex());
|
||||
}
|
||||
|
||||
|
||||
int SearchModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid()) return 0;
|
||||
if (!m_sourceModel) return 0;
|
||||
return 1; // the search row
|
||||
}
|
||||
|
||||
|
||||
QVariant SearchModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole: // Text
|
||||
return m_displayData.value(index.column());
|
||||
case Qt::EditRole: // Editor Text
|
||||
return m_columnFilters.value(index.column());
|
||||
case Qt::TextColorRole: // Text-Color
|
||||
if (!m_columnFilters.contains(index.column()))
|
||||
return QGuiApplication::palette().color(QPalette::Disabled, QPalette::ButtonText);
|
||||
break;
|
||||
case Qt::DecorationRole:
|
||||
return m_hideDecorationColumns.contains(index.column()) ? QVariant() : m_searchIcon;
|
||||
case Qt::BackgroundRole:
|
||||
return QGuiApplication::palette().color(QPalette::Disabled, QPalette::AlternateBase);
|
||||
case LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole:
|
||||
return m_comboBoxData.value(index.column());
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
QVariant SearchModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::FontRole)
|
||||
{
|
||||
QFont boldFont;
|
||||
boldFont.setBold(true);
|
||||
return boldFont;
|
||||
}
|
||||
|
||||
return m_sourceModel ? m_sourceModel->headerData(section, orientation, role) : QVariant();
|
||||
}
|
||||
|
||||
|
||||
bool SearchModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (!m_sourceModel || !index.isValid())
|
||||
return false;
|
||||
|
||||
if (role == Qt::EditRole) // add / replace column filter when edited and in search row (row 0)
|
||||
{
|
||||
if (value.isNull())
|
||||
m_columnFilters.remove(index.column());
|
||||
else
|
||||
m_columnFilters[index.column()] = value;
|
||||
emit stringFilterForColumnChanged(value.toString(), index.column());
|
||||
emit signalFilterChanged(); // must be called at last
|
||||
emit dataChanged(index, index, {role});
|
||||
return true; // done! (report a change, so that text keeps showing on search row)
|
||||
}
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (value.isNull())
|
||||
m_displayData.remove(index.column());
|
||||
else
|
||||
m_displayData[index.column()] = value;
|
||||
emit dataChanged(index, index, {role});
|
||||
return true;
|
||||
}
|
||||
if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
|
||||
{
|
||||
if (value.isNull())
|
||||
m_comboBoxData.remove(index.column());
|
||||
else
|
||||
m_comboBoxData[index.column()] = value;
|
||||
emit dataFilterForColumnChanged(value, index.column());
|
||||
emit signalFilterChanged(); // must be called at last
|
||||
emit dataChanged(index, index, {role});
|
||||
return true;
|
||||
}
|
||||
if (role == Qt::DecorationRole)
|
||||
{
|
||||
if (value.isNull())
|
||||
m_hideDecorationColumns.remove(index.column());
|
||||
else
|
||||
m_hideDecorationColumns.insert(index.column());
|
||||
emit dataChanged(index, index, {role});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void SearchModel::setSourceModel(QAbstractItemModel* sourceModel)
|
||||
{
|
||||
m_sourceModel = sourceModel;
|
||||
m_columnFilters.clear();
|
||||
|
||||
emit dataChanged(QModelIndex(), QModelIndex()); // update view
|
||||
}
|
||||
|
||||
|
||||
Qt::ItemFlags SearchModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
|
||||
}
|
||||
|
||||
|
||||
QModelIndex SearchModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return QModelIndex();
|
||||
return createIndex(row, column);
|
||||
}
|
||||
} // namespace LtsDataView
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Search Model for TableViews (has the ability to give the user a row for searching data)
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Mike Wille, SLSE, 2016-03-14
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsDataView/lts_data_view_export.h>
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QSet>
|
||||
#include <QString>
|
||||
#include <QPointer>
|
||||
|
||||
|
||||
namespace LtsDataView
|
||||
{
|
||||
class LTSDATAVIEW_EXPORT SearchModel final : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SearchModel(QObject *parent = nullptr);
|
||||
|
||||
void setSourceModel(QAbstractItemModel* sourceModel);
|
||||
QAbstractItemModel *sourceModel() const { return m_sourceModel; }
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override final;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override final;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override final;
|
||||
int rowCount(const QModelIndex &parent) const override final;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override final;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override final;
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent) const override final;
|
||||
QModelIndex parent(const QModelIndex &child) const override final { (void)child; return QModelIndex(); }
|
||||
|
||||
signals:
|
||||
void stringFilterForColumnChanged(const QString &newFilterString, int column);
|
||||
void dataFilterForColumnChanged(const QVariant &newFilterData, int column);
|
||||
void signalFilterChanged();
|
||||
|
||||
private:
|
||||
QVariant m_searchIcon;
|
||||
QPointer<QAbstractItemModel> m_sourceModel;
|
||||
QHash<int, QVariant> m_columnFilters;
|
||||
QHash<int, QVariant> m_displayData;
|
||||
QHash<int, QVariant> m_comboBoxData;
|
||||
QSet<int> m_hideDecorationColumns;
|
||||
};
|
||||
} // namespace LtsDataView
|
||||
Executable
+103
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Test for LtsDataView and their AbstractDisplayWidgets
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Mike Wille, SLSE, 2016-03-14
|
||||
*/
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#include <lts_data_view.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QLabel>
|
||||
#include <QStandardItem>
|
||||
#include <QStandardItemModel>
|
||||
#include <QElapsedTimer>
|
||||
#include <QScrollArea>
|
||||
#include <QScroller>
|
||||
|
||||
|
||||
Disp::Disp()
|
||||
: LtsDataView::AbstractDisplayWidget(nullptr)
|
||||
, m_label(new QLabel(this))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool Disp::init(const QModelIndex &idx)
|
||||
{
|
||||
if (!idx.isValid())
|
||||
return false;
|
||||
|
||||
m_label->setText(rowData(idx, 0).toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QApplication app(argc,argv);
|
||||
|
||||
int rows = 20;
|
||||
int cols = 7;
|
||||
|
||||
QElapsedTimer et;
|
||||
et.start();
|
||||
qWarning() << "creating" << rows << "items";
|
||||
qWarning() << "wait..";
|
||||
|
||||
LtsDataView::LtsDataView *view = new LtsDataView::LtsDataView();
|
||||
|
||||
QStandardItemModel model;
|
||||
|
||||
for (int r = 0; r < rows; r++)
|
||||
{
|
||||
for (int c = 0; c < cols; c++)
|
||||
{
|
||||
QStandardItem *item = new QStandardItem(QStringLiteral("Item %1/%2").arg(r).arg(c));
|
||||
model.setItem(r,c,item);
|
||||
}
|
||||
}
|
||||
|
||||
view->setModel(&model, [](){ return new Disp(); });
|
||||
view->show();
|
||||
|
||||
#ifdef TABLET_MODE
|
||||
auto widget = view;
|
||||
if (widget)
|
||||
{
|
||||
widget->setAttribute(Qt::WA_AcceptTouchEvents);
|
||||
|
||||
{
|
||||
QScrollArea *sca = qobject_cast<QScrollArea *>(widget);
|
||||
if (sca)
|
||||
{
|
||||
qWarning() << widget << "is scroll area";
|
||||
QScroller::grabGesture(sca->viewport(), QScroller::LeftMouseButtonGesture);
|
||||
QScroller::grabGesture(sca, QScroller::LeftMouseButtonGesture);
|
||||
}
|
||||
else
|
||||
{
|
||||
QAbstractItemView *aiv = qobject_cast<QAbstractItemView *>(widget);
|
||||
if (aiv)
|
||||
{
|
||||
qWarning() << widget << "is abst. item view";
|
||||
QScroller::grabGesture(aiv->viewport(), QScroller::LeftMouseButtonGesture);
|
||||
QScroller::grabGesture(aiv, QScroller::LeftMouseButtonGesture);
|
||||
aiv->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
aiv->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
qWarning() << "took" << et.elapsed() << "ms";
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Search Model for TableViews (has the ability to give the user a row for searching data)
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Mike Wille, SLSE, 2016-03-14
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "abstract_display_widget.h"
|
||||
|
||||
|
||||
class QLabel;
|
||||
|
||||
|
||||
class Disp : public LtsDataView::AbstractDisplayWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Disp();
|
||||
bool init(const QModelIndex &idx) override;
|
||||
|
||||
private:
|
||||
QLabel *m_label;
|
||||
};
|
||||
Executable
+82
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* A QTreeView with some events catched
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Mike Wille, SLSE, 2016-10-07
|
||||
*/
|
||||
|
||||
#include "tree_view.h"
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QKeyEvent>
|
||||
|
||||
namespace LtsDataView
|
||||
{
|
||||
|
||||
// needed until QTBUG-78726 is fixed
|
||||
void TreeView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
|
||||
const QVector<int> &roles)
|
||||
{
|
||||
QTreeView::dataChanged(topLeft, bottomRight, roles);
|
||||
if (!m_toolTipPos.isNull() && (roles.isEmpty() || roles.contains(Qt::ToolTipRole)))
|
||||
{
|
||||
if (viewport()->mapToGlobal(m_toolTipPos) != QCursor::pos())
|
||||
{
|
||||
m_toolTipPos = QPoint();
|
||||
return;
|
||||
}
|
||||
const QModelIndex index = indexAt(m_toolTipPos);
|
||||
if (index.row() >= topLeft.row() && index.row() <= bottomRight.row() &&
|
||||
index.column() >= topLeft.column() && index.column() <= bottomRight.column())
|
||||
{
|
||||
|
||||
QHelpEvent he(QEvent::ToolTip, m_toolTipPos, viewport()->mapToGlobal(m_toolTipPos));
|
||||
QTreeView::viewportEvent(&he);
|
||||
m_toolTipPos = QPoint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TreeView::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (QGuiApplication::keyboardModifiers() == Qt::ControlModifier
|
||||
&& event->key() == Qt::Key_C)
|
||||
emit signalCopyToClipBoard(); // queue !
|
||||
|
||||
QTreeView::keyPressEvent(event);
|
||||
}
|
||||
|
||||
bool TreeView::edit(const QModelIndex &index, EditTrigger trigger, QEvent *event)
|
||||
{
|
||||
|
||||
if (trigger == QAbstractItemView::NoEditTriggers)
|
||||
{
|
||||
const QMouseEvent *me = dynamic_cast<QMouseEvent*>(event);
|
||||
if (me && me->buttons().testFlag(Qt::LeftButton))
|
||||
trigger = QAbstractItemView::AllEditTriggers;
|
||||
}
|
||||
return QTreeView::edit(index, trigger, event);
|
||||
}
|
||||
|
||||
// needed until QTBUG-78726 is fixed
|
||||
bool TreeView::viewportEvent(QEvent *event)
|
||||
{
|
||||
bool ret = QTreeView::viewportEvent(event);
|
||||
if (event->type() == QEvent::ToolTip)
|
||||
{
|
||||
if (!ret)
|
||||
{
|
||||
QHelpEvent *he = static_cast<QHelpEvent*>(event);
|
||||
m_toolTipPos = he->pos();
|
||||
}
|
||||
else
|
||||
m_toolTipPos = QPoint();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
} // namespace LtsDataView
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* A QTreeView with some events catched
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Mike Wille, SLSE, 2016-10-07
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QTreeView>
|
||||
|
||||
|
||||
namespace LtsDataView
|
||||
{
|
||||
class TreeView final : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using QTreeView::QTreeView;
|
||||
|
||||
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
|
||||
const QVector<int> &roles) override;
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
bool edit(const QModelIndex &index, EditTrigger trigger, QEvent *event) override;
|
||||
bool viewportEvent(QEvent *event) override;
|
||||
|
||||
signals:
|
||||
void signalCopyToClipBoard();
|
||||
private:
|
||||
QPoint m_toolTipPos;
|
||||
};
|
||||
} // namespace LtsDataView
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
#include "lts_data_view.h"
|
||||
#include "tree_view_delegate.h"
|
||||
#include "search_model.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QComboBox>
|
||||
#include <QTimer>
|
||||
//#include <QDebug>
|
||||
|
||||
namespace LtsDataView
|
||||
{
|
||||
TreeViewDelegate::ComboBoxData TreeViewDelegate::comboBoxData(const QModelIndex &index)
|
||||
{
|
||||
const SearchModel *sm = qobject_cast<const SearchModel *>(index.model());
|
||||
if (!sm)
|
||||
return {};
|
||||
const QAbstractItemModel *aim = sm->sourceModel();
|
||||
if (!aim)
|
||||
return {};
|
||||
const QVariant val = aim->headerData(index.column(), Qt::Horizontal, LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole);
|
||||
return LtsWidgets::ComboboxFilterContent::fromVariant(val);
|
||||
}
|
||||
|
||||
|
||||
void TreeViewDelegate::paint(QPainter *painter,
|
||||
const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
const ComboBoxData cbd = comboBoxData(index);
|
||||
if (!cbd.isValid())
|
||||
return QStyledItemDelegate::paint(painter, option, index);
|
||||
|
||||
const QWidget *const widget = option.widget;
|
||||
QStyle* const style = widget ? widget->style() : QApplication::style();
|
||||
QStyleOptionComboBox cbOption;
|
||||
cbOption.rect = option.rect;
|
||||
cbOption.direction = option.direction;
|
||||
const auto currentData = index.data(LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole);
|
||||
for (const auto &content : cbd.data)
|
||||
{
|
||||
if (content.data == currentData)
|
||||
{
|
||||
cbOption.currentIcon = content.icon;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cbOption.currentText = index.data(Qt::DisplayRole).toString();
|
||||
cbOption.fontMetrics = option.fontMetrics;
|
||||
const int iconWidth = style->pixelMetric(QStyle::PM_SmallIconSize, nullptr, widget);
|
||||
cbOption.iconSize = QSize(iconWidth, iconWidth);
|
||||
cbOption.palette = option.palette;
|
||||
cbOption.state = option.state;
|
||||
cbOption.styleObject = option.styleObject;
|
||||
style->drawComplexControl(QStyle::CC_ComboBox, &cbOption, painter, widget);
|
||||
style->drawControl(QStyle::CE_ComboBoxLabel, &cbOption, painter, widget);
|
||||
}
|
||||
|
||||
|
||||
QWidget *TreeViewDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(option);
|
||||
|
||||
const ComboBoxData cbd = comboBoxData(index);
|
||||
if (cbd.isValid())
|
||||
{
|
||||
QComboBox *cbx = new QComboBox(parent);
|
||||
for (const auto &content : cbd.data)
|
||||
cbx->addItem(content.icon, content.text, content.data);
|
||||
if (cbd.sortItems)
|
||||
cbx->model()->sort(0);
|
||||
cbx->insertItem(0, noFilterString());
|
||||
connect(cbx, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, &TreeViewDelegate::slotFinished);
|
||||
QTimer::singleShot(0, cbx, &QComboBox::showPopup);
|
||||
return cbx;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef TABLET_MODE
|
||||
//qWarning() << "TABLET MODE !!!!!!!!";
|
||||
// no line edit as it crashes
|
||||
return nullptr;
|
||||
#else
|
||||
//qWarning() << "****NO**** TABLET MODE !!!!!!!!!!!!!!!!";
|
||||
SearchLineEdit *edit = new SearchLineEdit(parent);
|
||||
edit->setFrame(false);
|
||||
connect(edit, &SearchLineEdit::editingFinished,
|
||||
this, &TreeViewDelegate::slotFinished);
|
||||
return edit;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TreeViewDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
const ComboBoxData cbd = comboBoxData(index);
|
||||
if (cbd.isValid())
|
||||
{
|
||||
QComboBox *cbx = qobject_cast<QComboBox *>(editor);
|
||||
if (cbx)
|
||||
{
|
||||
// save the current data since it may change within setData() due to dataChanged() signals
|
||||
const QString curTxt = cbx->currentText();
|
||||
const QVariant curData = cbx->currentData();
|
||||
model->setData(index, curData, LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole);
|
||||
model->setData(index, curTxt, Qt::DisplayRole);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SearchLineEdit *edit = qobject_cast<SearchLineEdit *>(editor);
|
||||
if (edit)
|
||||
{
|
||||
model->setData(index, edit->text(), Qt::DisplayRole);
|
||||
model->setData(index, edit->text(), Qt::EditRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TreeViewDelegate::slotFinished()
|
||||
{
|
||||
QWidget *w = qobject_cast<QWidget *>(sender());
|
||||
if (!w)
|
||||
return;
|
||||
|
||||
emit commitData(w);
|
||||
emit closeEditor(w);
|
||||
}
|
||||
|
||||
void TreeViewDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
|
||||
{
|
||||
const ComboBoxData cbd = comboBoxData(index);
|
||||
if (cbd.isValid())
|
||||
{
|
||||
QComboBox *cbx = qobject_cast<QComboBox *>(editor);
|
||||
if (cbx)
|
||||
{
|
||||
const auto currentData = index.data(LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole);
|
||||
cbx->setCurrentIndex(cbx->findData(currentData));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SearchLineEdit *edit = qobject_cast<SearchLineEdit *>(editor);
|
||||
if (edit)
|
||||
edit->setText(index.data().toString());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace LtsDataView
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_column_filter_proxy_model.h>
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QStyle>
|
||||
|
||||
|
||||
namespace LtsDataView
|
||||
{
|
||||
class TreeViewDelegate final : public QStyledItemDelegate // needed to tell the QLineEdit to be as compact as possible while editing
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using ComboBoxData = LtsWidgets::ComboboxFilterContent;
|
||||
using QStyledItemDelegate::QStyledItemDelegate;
|
||||
|
||||
void paint(QPainter *painter,
|
||||
const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const override;
|
||||
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||
const QModelIndex &index) const override;
|
||||
|
||||
static QString noFilterString() { return tr("<No filter>"); }
|
||||
private:
|
||||
static ComboBoxData comboBoxData(const QModelIndex &index);
|
||||
|
||||
private slots:
|
||||
void slotFinished();
|
||||
};
|
||||
} // namespace LtsDataView
|
||||
Reference in new issue
Block a user