1325 lines
40 KiB
C++
Executable File
1325 lines
40 KiB
C++
Executable File
/**
|
|
* @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
|
|
*/
|
|
|
|
#include "lts_data_view.h"
|
|
#include "ui_lts_data_view.h"
|
|
#include "search_model.h"
|
|
#include "abstract_display_widget.h"
|
|
#include "tree_view.h"
|
|
#include "tree_view_delegate.h"
|
|
#include "icon_view_delegate.h"
|
|
#include "data_delegate.h"
|
|
|
|
#include <LtsWidgets/lts_column_filter_proxy_model.h>
|
|
#include <LtsWidgets/lts_message_dialog.h>
|
|
#include <LtsUtilsSettings/settings.h>
|
|
|
|
#include <QtGui/QClipboard>
|
|
#include <QtWidgets/QComboBox>
|
|
#include <QtCore/QFile>
|
|
#include <QtWidgets/QFileDialog>
|
|
#include <QtGui/QKeyEvent>
|
|
#include <QtWidgets/QLineEdit>
|
|
#include <QtWidgets/QPushButton>
|
|
#include <QtWidgets/QStyledItemDelegate>
|
|
#include <QtCore/QTimer>
|
|
#include <QScroller>
|
|
#include <QtCore/QJsonObject>
|
|
#include <QtCore/QJsonArray>
|
|
#include <QtCore/QJsonDocument>
|
|
#include <QtCore/QDebug>
|
|
#include <utility>
|
|
|
|
/// get the list of visual index as they are display
|
|
namespace LtsDataView
|
|
{
|
|
static const QString s_columSettingSuffix = QStringLiteral("_ColSetting");
|
|
static const QString s_colSettingIndexStr = QStringLiteral("index");
|
|
static const QString s_colSettingVisiStr = QStringLiteral("visible");
|
|
static const QString s_ColumnOrganiserSettingStr = QStringLiteral("ColumnOrganiserSetting");
|
|
|
|
|
|
#include <LtsUtilsSettings/settings.h>
|
|
LtsDataView::LtsDataView(QWidget *parent)
|
|
: QWidget(parent)
|
|
, m_ui(new Ui::LtsDataView)
|
|
, m_columnFilterProxy(nullptr)
|
|
, m_searchModel(new SearchModel(this))
|
|
, m_bOwnProxy(false)
|
|
{
|
|
m_ui->setupUi(this);
|
|
|
|
m_ui->tableView->setAlternatingRowColors(true);
|
|
m_ui->tableView->setAllColumnsShowFocus(true);
|
|
|
|
m_ui->tbColumnOrganiser->setVisible(false);
|
|
m_ui->tbColumnOrganiser->setEnabled(false);
|
|
#ifndef LTS_DEBUG
|
|
m_ui->lblRows->setHidden(true);
|
|
// m_ui->tbCsvExport->hide();
|
|
#endif
|
|
|
|
m_ui->searchView->setItemDelegate(new TreeViewDelegate(this));
|
|
m_ui->tableView->setItemDelegate(new DataDelegate(this));
|
|
|
|
connect(m_ui->tbCustom, &QPushButton::clicked,
|
|
this, &LtsDataView::LtsDataView::selectCustomView);
|
|
|
|
connect(m_ui->tbTable, &QPushButton::clicked,
|
|
this, &LtsDataView::LtsDataView::selectTableView);
|
|
|
|
connect(m_ui->tableView, &TreeView::signalCopyToClipBoard,
|
|
this, &LtsDataView::LtsDataView::slotCopyToClipboard, Qt::QueuedConnection); // event should pass before this slot can be entered
|
|
|
|
connect(m_ui->tbCopy, &QPushButton::clicked,
|
|
this, &LtsDataView::LtsDataView::slotCopyToClipboard);
|
|
|
|
connect(m_ui->tbCsvExport, &QPushButton::clicked,
|
|
this, &LtsDataView::LtsDataView::slotCsvExport);
|
|
|
|
connect(m_ui->tbColumnOrganiser, &QPushButton::clicked,
|
|
this, &LtsDataView::LtsDataView::slotColumnOrganiserDialog);
|
|
|
|
#ifdef TABLET_MODE
|
|
const QList<QWidget *> scrollWidgets = findChildren<QWidget *>();
|
|
for (QWidget *widget : scrollWidgets)
|
|
{
|
|
QVariant isConst = widget->property("const");
|
|
if (isConst.isValid() && isConst.toBool())
|
|
continue;
|
|
addTouchScroll(widget);
|
|
}
|
|
#endif
|
|
|
|
selectTableView();
|
|
}
|
|
|
|
|
|
LtsDataView::~LtsDataView()
|
|
{
|
|
delete m_ui;
|
|
}
|
|
|
|
|
|
void LtsDataView::setModel(QAbstractItemModel *model, const std::function<AbstractDisplayWidget*()> &customDisplayWidgetCreator)
|
|
{
|
|
Q_ASSERT(model);
|
|
|
|
if (!customDisplayWidgetCreator) // no custom widgets? pretend to be a pure table view by hiding the ability to swap between views
|
|
{
|
|
m_ui->tbCustom->setEnabled(false); // disable custom view
|
|
m_ui->tbCustom->hide();
|
|
m_ui->tbTable->hide();
|
|
m_ui->line->hide();
|
|
selectTableView();
|
|
}
|
|
else
|
|
{
|
|
IconViewDelegate *delegate = new IconViewDelegate(this);
|
|
delegate->setDisplayWidgetCreator(customDisplayWidgetCreator);
|
|
m_ui->customView->setItemDelegate(delegate); // does not take ownership of delegate ...
|
|
}
|
|
|
|
LtsWidgets::LtsColumnFilterProxyModel *proxy = qobject_cast<LtsWidgets::LtsColumnFilterProxyModel *>(model);
|
|
if (m_bOwnProxy)
|
|
delete m_columnFilterProxy;
|
|
if (proxy)
|
|
{
|
|
m_columnFilterProxy = proxy;
|
|
m_bOwnProxy = false;
|
|
}
|
|
else
|
|
{
|
|
Q_ASSERT_X(!qobject_cast<QSortFilterProxyModel*>(model),
|
|
__FUNCTION__,
|
|
"Don't pass plain QSortFilterProxyModel to LtsDataView::setModel - it will not work as expected. Derive from LtsColumnFilterProxyModel instead");
|
|
m_columnFilterProxy = new LtsWidgets::LtsColumnFilterProxyModel(this);
|
|
m_columnFilterProxy->setSourceModel(model);
|
|
m_bOwnProxy = true;
|
|
}
|
|
m_searchModel->setSourceModel(model);
|
|
|
|
connect(m_searchModel, &SearchModel::stringFilterForColumnChanged,
|
|
m_columnFilterProxy, &LtsWidgets::LtsColumnFilterProxyModel::onSetColumnStringFilter);
|
|
connect(m_searchModel, &SearchModel::dataFilterForColumnChanged,
|
|
m_columnFilterProxy, &LtsWidgets::LtsColumnFilterProxyModel::onSetColumnDataFilter);
|
|
|
|
m_ui->searchView->setModel(m_searchModel);
|
|
m_ui->tableView->setModel(m_columnFilterProxy);
|
|
m_ui->customView->setModel(m_columnFilterProxy);
|
|
m_ui->searchView->show();
|
|
|
|
|
|
// Main Model
|
|
connect(m_columnFilterProxy, &QAbstractItemModel::rowsInserted,
|
|
this, &LtsDataView::slotRowCountChanged);
|
|
connect(m_columnFilterProxy, &QAbstractItemModel::rowsRemoved,
|
|
this, &LtsDataView::slotRowCountChanged);
|
|
connect(m_columnFilterProxy, &QAbstractItemModel::modelReset,
|
|
this, &LtsDataView::slotRowCountChanged);
|
|
connect(m_columnFilterProxy->sourceModel(), &QAbstractItemModel::rowsInserted,
|
|
this, &LtsDataView::slotRowCountChanged);
|
|
connect(m_columnFilterProxy->sourceModel(), &QAbstractItemModel::rowsRemoved,
|
|
this, &LtsDataView::slotRowCountChanged);
|
|
connect(m_columnFilterProxy->sourceModel(), &QAbstractItemModel::modelReset,
|
|
this, &LtsDataView::slotRowCountChanged);
|
|
|
|
// Selection Changed
|
|
// for example needed by OperatorDialog::enaDisa :
|
|
connect(m_ui->customView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
|
this, &LtsDataView::signalSelectionChanged);
|
|
connect(m_ui->tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
|
this, &LtsDataView::signalSelectionChanged);
|
|
// : for example needed by OperatorDialog::enaDisa
|
|
connect(m_ui->customView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
|
this, [this](const QItemSelection &s, const QItemSelection &d) { emit selectionChanged(mapSelectionToSource(s), mapSelectionToSource(d)); });
|
|
connect(m_ui->tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
|
this, [this](const QItemSelection &s, const QItemSelection &d) { emit selectionChanged(mapSelectionToSource(s), mapSelectionToSource(d)); });
|
|
|
|
// Activated
|
|
connect(m_ui->customView, &QAbstractItemView::activated,
|
|
this, [this](const QModelIndex &idx) { emit activated(mapToSource(idx)); });
|
|
connect(m_ui->tableView, &QAbstractItemView::activated,
|
|
this, [this](const QModelIndex &idx) { emit activated(mapToSource(idx)); });
|
|
|
|
|
|
// Entered (requires MouseTracking)
|
|
m_ui->customView->setMouseTracking(true);
|
|
connect(m_ui->customView, &QAbstractItemView::entered,
|
|
this, [this](const QModelIndex &index) { emit signalEntered(mapToSource(index)); });
|
|
m_ui->tableView->setMouseTracking(true);
|
|
connect(m_ui->tableView, &QAbstractItemView::entered,
|
|
this, [this](const QModelIndex &index) { emit signalEntered(mapToSource(index)); });
|
|
|
|
|
|
// Clicked
|
|
connect(m_ui->customView, &QAbstractItemView::clicked,
|
|
this, [this](const QModelIndex &idx) { emit clicked(mapToSource(idx)); });
|
|
connect(m_ui->tableView, &QAbstractItemView::clicked,
|
|
this, [this](const QModelIndex &idx) { emit clicked(mapToSource(idx)); });
|
|
|
|
// Double Clicked
|
|
connect(m_ui->customView, &QAbstractItemView::doubleClicked,
|
|
this, &LtsDataView::signalDoubleClicked);
|
|
connect(m_ui->tableView, &QAbstractItemView::doubleClicked,
|
|
this, &LtsDataView::signalDoubleClicked);
|
|
|
|
connect(m_ui->customView, &QAbstractItemView::doubleClicked,
|
|
this, [this](const QModelIndex &idx) { emit doubleClicked(mapToSource(idx)); });
|
|
connect(m_ui->tableView, &QAbstractItemView::doubleClicked,
|
|
this, [this](const QModelIndex &idx) { emit doubleClicked(mapToSource(idx)); });
|
|
|
|
// Search View
|
|
connect(m_ui->searchView->header(), &QHeaderView::sortIndicatorChanged,
|
|
this, &LtsDataView::slotSetSortIndicator);
|
|
connect(m_searchModel, &SearchModel::signalFilterChanged,
|
|
this, &LtsDataView::slotRowCountChanged);
|
|
connect(m_searchModel, &SearchModel::signalFilterChanged,
|
|
this, [this](){ emit filterChanged(); });
|
|
connect(m_ui->searchView->header(), &QHeaderView::sectionResized,
|
|
this, &LtsDataView::slotSectionResized);
|
|
connect(m_ui->searchView->header(), &QHeaderView::sectionMoved,
|
|
this, &LtsDataView::slotHeaderMoved);
|
|
|
|
connect(m_ui->searchView->header(), &QHeaderView::sectionHandleDoubleClicked,
|
|
this, &LtsDataView::slotResizeColumn, Qt::QueuedConnection); // wait until the header did a resize by header text
|
|
|
|
|
|
// Horizontal Scrollbar
|
|
connect(m_ui->searchView->horizontalScrollBar(), &QScrollBar::rangeChanged,
|
|
this, &LtsDataView::slotSetHorizontalRange, Qt::QueuedConnection); // queued to make sure pageStep is up-to-date
|
|
connect(m_ui->searchView->horizontalScrollBar(), &QScrollBar::sliderMoved,
|
|
this, &LtsDataView::slotSetHorizontalValue);
|
|
connect(m_ui->searchView->horizontalScrollBar(), &QScrollBar::valueChanged,
|
|
this, &LtsDataView::slotSetHorizontalValue);
|
|
|
|
connect(m_ui->horizontalScrollBar, &QScrollBar::sliderMoved,
|
|
m_ui->searchView->horizontalScrollBar(), &QScrollBar::setValue);
|
|
connect(m_ui->horizontalScrollBar, &QScrollBar::sliderMoved,
|
|
m_ui->tableView->horizontalScrollBar(), &QScrollBar::setValue);
|
|
connect(m_ui->horizontalScrollBar, &QScrollBar::valueChanged,
|
|
m_ui->searchView->horizontalScrollBar(), &QScrollBar::setValue); // when wheelEvent'ing on the scrollbar
|
|
connect(m_ui->horizontalScrollBar, &QScrollBar::valueChanged,
|
|
m_ui->tableView->horizontalScrollBar(), &QScrollBar::setValue); // when wheelEvent'ing on the scrollbar
|
|
|
|
connect(m_ui->tableView->horizontalScrollBar(), &QScrollBar::rangeChanged,
|
|
this, &LtsDataView::slotSetHorizontalRange, Qt::QueuedConnection); // queued to make sure pageStep is up-to-date
|
|
connect(m_ui->tableView->horizontalScrollBar(), &QScrollBar::sliderMoved,
|
|
this, &LtsDataView::slotSetHorizontalValue);
|
|
connect(m_ui->tableView->horizontalScrollBar(), &QScrollBar::valueChanged,
|
|
this, &LtsDataView::slotSetHorizontalValue); // when wheelEvent'ing on the scrollbar
|
|
// custom view has no horizontal scroll bar
|
|
|
|
|
|
// Vertical Scrollbar
|
|
connect(m_ui->customView->verticalScrollBar(), &QScrollBar::rangeChanged,
|
|
this, &LtsDataView::slotSetVerticalRange, Qt::QueuedConnection); // queued to make sure pageStep is up-to-date
|
|
connect(m_ui->customView->verticalScrollBar(), &QScrollBar::sliderMoved,
|
|
this, &LtsDataView::slotSetVerticalValue);
|
|
connect(m_ui->customView->verticalScrollBar(), &QScrollBar::valueChanged,
|
|
this, &LtsDataView::slotSetVerticalValue); // custom view uses setValue on wheelEvent, listen to that
|
|
|
|
connect(m_ui->tableView->verticalScrollBar(), &QScrollBar::rangeChanged,
|
|
this, &LtsDataView::slotSetVerticalRange, Qt::QueuedConnection); // queued to make sure pageStep is up-to-date
|
|
connect(m_ui->tableView->verticalScrollBar(), &QScrollBar::sliderMoved,
|
|
this, &LtsDataView::slotSetVerticalValue);
|
|
connect(m_ui->tableView->verticalScrollBar(), &QScrollBar::valueChanged,
|
|
this, &LtsDataView::slotSetVerticalValue); // when wheelEvent'ing on the scrollbar
|
|
|
|
connect(m_ui->verticalScrollBar, &QScrollBar::valueChanged,
|
|
m_ui->tableView->verticalScrollBar(), &QScrollBar::setValue);
|
|
connect(m_ui->verticalScrollBar, &QScrollBar::valueChanged,
|
|
m_ui->customView->verticalScrollBar(), &QScrollBar::setValue);
|
|
// search view has no vertical scroll bar
|
|
|
|
// for context menue: (but contextPolicy has to be set by user...)
|
|
QTreeView *treeView = m_ui->tableView;
|
|
connect(treeView, &QListView::customContextMenuRequested,
|
|
this, &LtsDataView::onCustomContextMenuRequested, Qt::UniqueConnection);
|
|
connect(m_ui->customView, &QListView::customContextMenuRequested,
|
|
this, &LtsDataView::onCustomContextMenuRequested, Qt::UniqueConnection);
|
|
|
|
// check if a column has a combobox search
|
|
for (int c = 0; c < model->columnCount(); ++c)
|
|
{
|
|
const QModelIndex idx = m_searchModel->index(0, c, QModelIndex());
|
|
const QVariant v = model->headerData(c, Qt::Horizontal, LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole);
|
|
if (!v.isNull())
|
|
{
|
|
m_searchModel->setData(idx, false, Qt::DecorationRole);
|
|
m_searchModel->setData(idx, TreeViewDelegate::noFilterString(), Qt::DisplayRole);
|
|
}
|
|
}
|
|
|
|
// set minimim size for this data view to display custom widgets properly
|
|
// TODO: !
|
|
// AbstractDisplayWidget *dummy = customDisplayWidgetCreator();
|
|
// setMinimumSize(dummy->minimumWidth() + 40 + 100, dummy->minimumHeight() + 40 + 100); // FIXME: margin?
|
|
|
|
slotRowCountChanged(); // show row count
|
|
|
|
// hide h-scrollbar if not needed
|
|
if (m_ui->searchView->horizontalScrollBar()->maximum() == 0)
|
|
m_ui->horizontalScrollBar->hide();
|
|
|
|
setSortIndicator(0, Qt::AscendingOrder);
|
|
|
|
resizeHeadersByContent();
|
|
if (m_autoResizeToConent)
|
|
syncSearchHeaderAndTableContentColumnSize();
|
|
|
|
m_DebugModeColIds.clear();
|
|
}
|
|
|
|
QAbstractItemModel *LtsDataView::sourceModel() const
|
|
{
|
|
return m_columnFilterProxy ? m_columnFilterProxy->sourceModel() : nullptr;
|
|
}
|
|
|
|
LtsWidgets::LtsColumnFilterProxyModel *LtsDataView::proxyModel() const
|
|
{
|
|
return m_columnFilterProxy;
|
|
}
|
|
|
|
QItemSelectionModel *LtsDataView::selectionModel() const
|
|
{
|
|
return m_ui->tableView->selectionModel();
|
|
}
|
|
|
|
SearchModel *LtsDataView::searchModel() const
|
|
{
|
|
return m_searchModel;
|
|
}
|
|
|
|
|
|
|
|
QTreeView *LtsDataView::treeView()
|
|
{
|
|
return m_ui->tableView;
|
|
}
|
|
|
|
const QTreeView *LtsDataView::treeView() const
|
|
{
|
|
return m_ui->tableView;
|
|
}
|
|
|
|
QTreeView *LtsDataView::searchView()
|
|
{
|
|
return m_ui->searchView;
|
|
}
|
|
|
|
const QTreeView *LtsDataView::searchView() const
|
|
{
|
|
return m_ui->searchView;
|
|
}
|
|
|
|
QListView *LtsDataView::getCustomView()
|
|
{
|
|
return m_ui->customView;
|
|
}
|
|
|
|
QWidget *LtsDataView::customWidget() const
|
|
{
|
|
QLayout *hbl = m_ui->customWidget->layout();
|
|
if (hbl)
|
|
{
|
|
for (int i = 0; i < hbl->count(); ++i)
|
|
{
|
|
if (hbl->itemAt(i)->widget())
|
|
return hbl->itemAt(i)->widget();
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void LtsDataView::setCustomWidget(QWidget *customWidget)
|
|
{
|
|
QLayout *hbl = m_ui->customWidget->layout();
|
|
if (hbl)
|
|
{
|
|
while (hbl->count() > 0)
|
|
delete hbl->takeAt(0)->widget();
|
|
}
|
|
delete hbl;
|
|
|
|
hbl = new QHBoxLayout(m_ui->customWidget);
|
|
hbl->setContentsMargins(0, 0, 0, 0);
|
|
hbl->addWidget(customWidget);
|
|
m_ui->customWidget->setLayout(hbl);
|
|
update(); // TODO: noetig? macht doch qt automatisch bei layout aenderungen?
|
|
}
|
|
|
|
|
|
|
|
QModelIndexList LtsDataView::selectedRows(int column) const
|
|
{
|
|
if (m_ui->stackedWidget->currentIndex() == TABLE)
|
|
{
|
|
if (m_ui->tableView->selectionModel())
|
|
return mapToSource(m_ui->tableView->selectionModel()->selectedRows(column));
|
|
}
|
|
else
|
|
{
|
|
Q_ASSERT(column == 0);
|
|
if (m_ui->customView->selectionModel())
|
|
return mapToSource(m_ui->customView->selectionModel()->selectedIndexes());
|
|
}
|
|
return {};
|
|
}
|
|
|
|
void LtsDataView::selectRow(const QModelIndex &idxSource)
|
|
{
|
|
QModelIndex idx = m_bOwnProxy ? m_columnFilterProxy->mapFromSource(idxSource) : idxSource;
|
|
QItemSelectionModel *pSelection = m_ui->tableView->selectionModel();
|
|
if (idx.isValid() && pSelection)
|
|
pSelection->select(idx, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
|
}
|
|
|
|
void LtsDataView::clearSelection()
|
|
{
|
|
if (m_ui->tableView)
|
|
m_ui->tableView->clearSelection();
|
|
if (m_ui->customView)
|
|
m_ui->customView->clearSelection();
|
|
}
|
|
|
|
void LtsDataView::setSelectionMode(QAbstractItemView::SelectionMode selectionMode)
|
|
{
|
|
m_ui->tableView->setSelectionMode(selectionMode);
|
|
m_ui->customView->setSelectionMode(selectionMode);
|
|
}
|
|
|
|
QAbstractItemView::SelectionMode LtsDataView::selectionMode() const
|
|
{
|
|
return m_ui->tableView->selectionMode();
|
|
}
|
|
|
|
QModelIndex LtsDataView::currentIndex() const
|
|
{
|
|
return mapToSource(currentView()->currentIndex());
|
|
}
|
|
|
|
void LtsDataView::setCurrentIndex(const QModelIndex &idxSource)
|
|
{
|
|
const QModelIndex &idx = mapFromSource(idxSource);
|
|
QAbstractItemView *view = currentView();
|
|
view->setCurrentIndex(idx);
|
|
view->scrollTo(idx, QTreeView::ScrollHint::PositionAtCenter);
|
|
}
|
|
|
|
void LtsDataView::scrollTo(const QModelIndex &idxSource)
|
|
{
|
|
QModelIndex idx = m_bOwnProxy ? m_columnFilterProxy->mapFromSource(idxSource) : idxSource;
|
|
if (idx.isValid())
|
|
m_ui->tableView->scrollTo(idx, QAbstractItemView::PositionAtCenter);
|
|
}
|
|
|
|
|
|
|
|
void LtsDataView::moveSection(int from, int to)
|
|
{
|
|
m_ui->searchView->header()->moveSection(from, to);
|
|
}
|
|
|
|
void LtsDataView::seamless()
|
|
{
|
|
// TODO: FIXME: quick hack
|
|
m_ui->tbCopy->setEnabled(false);
|
|
m_ui->tbCsvExport->setEnabled(false);
|
|
m_ui->tbCustom->setEnabled(false);
|
|
m_ui->tbTable->setEnabled(false);
|
|
delete m_ui->horizontalLayout; // does not delete its indirect children
|
|
m_ui->horizontalLayout = nullptr;
|
|
}
|
|
|
|
void LtsDataView::setViewHeaderMovable(bool state)
|
|
{
|
|
m_ui->searchView->header()->setSectionsMovable(state);
|
|
}
|
|
|
|
/*!
|
|
* \brief LtsDataView::saveTableSettings
|
|
* \param defaultSetting: if user want to save default setting of column
|
|
*/
|
|
void LtsDataView::saveTableSettings(bool defaultSetting)
|
|
{
|
|
//qWarning()<<"########### [saveTableSettings]...";
|
|
QJsonArray jsArr;
|
|
int colCount = m_ui->tableView->model()->columnCount();
|
|
for(int i=0; i<colCount; ++i)
|
|
{
|
|
int logicalIndex = defaultSetting ? i : m_ui->tableView->header()->logicalIndex(i); // if true save col default order reset visibility
|
|
bool visible = defaultSetting ? true : !m_ui->searchView->isColumnHidden(logicalIndex);
|
|
|
|
if (m_DebugModeColIds.contains(logicalIndex))
|
|
visible = false; //
|
|
|
|
QJsonObject column;
|
|
column[s_colSettingIndexStr] = logicalIndex;
|
|
column[s_colSettingVisiStr] = visible;
|
|
jsArr.append(column);
|
|
}
|
|
|
|
QJsonObject obj;
|
|
obj.insert(m_tableObjIdentifier, jsArr);
|
|
//qWarning()<<">>>[SAVE] Setting jsObj: -> "<<obj;
|
|
const QString identifier = m_tableObjIdentifier + s_columSettingSuffix;
|
|
LtsUtils::OperatorSettings::getInstance()->setValue(columnOrganiserGroup(), identifier, QVariant::fromValue(obj));
|
|
}
|
|
|
|
bool LtsDataView::restoreTableSettings()
|
|
{
|
|
//qCritical()<<"########### [restoreTableSettings]...";
|
|
|
|
LtsUtils::OperatorSettings* opSettings = LtsUtils::OperatorSettings::getInstance();
|
|
QJsonObject dataObj = opSettings->value(columnOrganiserGroup(), getOperatorColIdentifier()).toJsonObject();
|
|
if (dataObj.isEmpty())
|
|
{
|
|
qCritical()<<">>> [restoreTableSettings] Object EMPTY!!";
|
|
return false;
|
|
}
|
|
QJsonArray jsArr = dataObj.value(m_tableObjIdentifier).toArray();
|
|
qWarning()<<">>> [restoreTableSettings] jsData: "<<dataObj;
|
|
|
|
if (jsArr.isEmpty())
|
|
{
|
|
qCritical()<<">>> [restoreTableSettings] json array EMPTY!!";
|
|
return false;
|
|
}
|
|
|
|
int colIndex =0;
|
|
for(const QJsonValue &value: jsArr)
|
|
{
|
|
QJsonObject column = value.toObject();
|
|
int index = column[s_colSettingIndexStr].toInt();
|
|
bool visible = column[s_colSettingVisiStr].toBool();
|
|
|
|
if (m_DebugModeColIds.contains(index))
|
|
visible = false; // hide debug columns
|
|
|
|
//qWarning()<<"[restore]-> index: "<<index<<" visualIdx: "<<m_ui->searchView->header()->visualIndex(index)<<" visi: "<<visible;
|
|
m_ui->searchView->header()->moveSection(m_ui->searchView->header()->visualIndex(index), colIndex++);
|
|
m_ui->searchView->setColumnHidden(index, !visible);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*!
|
|
* \brief LtsDataView::setColumnViewFromSetting
|
|
* This Method will is Call to set Column Table settings from what was saved in json
|
|
*/
|
|
void LtsDataView::setColumnViewFromSetting()
|
|
{
|
|
qWarning()<<"######### setColumnViewFromSetting ... ";
|
|
m_userChangedColumnPos = false; // on internal move section avoid saving column setting
|
|
|
|
bool brestore = restoreTableSettings();
|
|
if (!brestore)
|
|
qCritical()<<" [setColumnViewFromSetting] couldn't restore table settings";
|
|
|
|
m_userChangedColumnPos = true;
|
|
}
|
|
|
|
QString LtsDataView::getOperatorColIdentifier() const
|
|
{
|
|
return m_tableObjIdentifier + s_columSettingSuffix;
|
|
}
|
|
|
|
QString LtsDataView::columnOrganiserGroup() const
|
|
{
|
|
return s_ColumnOrganiserSettingStr;
|
|
}
|
|
|
|
/*!
|
|
* \brief LtsDataView::getColumnOrganiserSetting
|
|
* \return get vector of struct from column jsondata (struct: id, visibility,..)
|
|
*/
|
|
QVector<ColumnOrganiserInfo> LtsDataView::getColumnOrganiserSetting()
|
|
{
|
|
const QString identifier = m_tableObjIdentifier + s_columSettingSuffix;
|
|
LtsUtils::OperatorSettings* opSettings = LtsUtils::OperatorSettings::getInstance();
|
|
QJsonObject dataObj = opSettings->value(columnOrganiserGroup(), identifier).toJsonObject();
|
|
QJsonArray jsArr = dataObj.value(m_tableObjIdentifier).toArray();
|
|
QVector<ColumnOrganiserInfo> vecInfo;
|
|
vecInfo.reserve(jsArr.count());
|
|
for(const QJsonValue &value: jsArr)
|
|
{
|
|
ColumnOrganiserInfo ci;
|
|
QJsonObject column = value.toObject();
|
|
ci.logicalIndex = column[s_colSettingIndexStr].toInt();
|
|
ci.show = column[s_colSettingVisiStr].toBool();
|
|
vecInfo.push_back(ci);
|
|
}
|
|
return vecInfo;
|
|
}
|
|
|
|
|
|
/*!
|
|
* \brief LtsDataView::setColumnsOrganiserEnabled
|
|
* \param tableIdentifier: unique name for table using column Settings
|
|
* \param enable : set button for column Setting Widget visible
|
|
*/
|
|
void LtsDataView::setColumnsOrganiserEnabled(const QString &tableIdentifier, bool enable)
|
|
{
|
|
qWarning()<<"############## [setColumnsOrganiserEnabled]...";
|
|
m_tableObjIdentifier = tableIdentifier;
|
|
m_ui->tbColumnOrganiser->setVisible(enable);
|
|
m_ui->tbColumnOrganiser->setEnabled(enable);
|
|
|
|
if (!restoreTableSettings())
|
|
saveTableSettings();
|
|
|
|
m_userChangedColumnPos = enable;
|
|
}
|
|
|
|
/*!
|
|
* \brief LtsDataView::slotColumnOrganiserDialog
|
|
*/
|
|
void LtsDataView::slotColumnOrganiserDialog()
|
|
{
|
|
qWarning()<<"############# [slotColumnOrganiserDialog]...";
|
|
if (!m_ui->tbColumnOrganiser->isEnabled())
|
|
return;
|
|
|
|
auto vecInfo = getColumnOrganiserSetting();
|
|
|
|
if(vecInfo.isEmpty())
|
|
{
|
|
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Couldn't start Column Organiser Dialog"), tr("Column Organiser"));
|
|
return;
|
|
}
|
|
|
|
const int colCount = m_columnFilterProxy->columnCount();
|
|
/// set Column names for Dialog Widget
|
|
for( auto &ci : vecInfo)
|
|
{
|
|
if (ci.logicalIndex > colCount)
|
|
continue;
|
|
|
|
ci.name = m_columnFilterProxy->headerData(ci.logicalIndex, Qt::Horizontal).toString();
|
|
|
|
// hide columns displayed only in debug mode
|
|
// because column is marked for debug, user will not be able to hide or show this column
|
|
if (m_DebugModeColIds.contains(ci.logicalIndex))
|
|
{
|
|
ci.show = false;
|
|
ci.debugOnly = true;
|
|
}
|
|
}
|
|
|
|
LtsColumnsSettingWidget *dialog = new LtsColumnsSettingWidget(vecInfo, this);
|
|
//LtsColumnOrganiser *dialog = new LtsColumnOrganiser(vecInfo, this);
|
|
|
|
connect(dialog, &LtsColumnsSettingWidget::columnVisibilityChanged, this, &LtsDataView::updateColumnsVisibility);
|
|
connect(dialog, &LtsColumnsSettingWidget::columnsResetted, this, &LtsDataView::slotSetColumnsDefaultOrder);
|
|
|
|
dialog->setModal(true);
|
|
dialog->show();
|
|
}
|
|
|
|
|
|
|
|
|
|
void LtsDataView::setRootIsDecorated(bool isDecorated)
|
|
{
|
|
if (m_ui && m_ui->tableView)
|
|
m_ui->tableView->setRootIsDecorated(isDecorated);
|
|
}
|
|
|
|
bool LtsDataView::rootIsDecorated() const
|
|
{
|
|
if (m_ui && m_ui->tableView)
|
|
return m_ui->tableView->rootIsDecorated();
|
|
return false;
|
|
}
|
|
|
|
void LtsDataView::setAlternatingRowColors(bool enable)
|
|
{
|
|
m_ui->tableView->setAlternatingRowColors(enable);
|
|
}
|
|
|
|
bool LtsDataView::alternatingRowColors() const
|
|
{
|
|
return m_ui->tableView->alternatingRowColors();
|
|
}
|
|
|
|
|
|
|
|
void LtsDataView::setColumnCountVisible(bool bVisible)
|
|
{
|
|
m_ui->lblRows->setVisible(bVisible);
|
|
m_ui->lbRows->setVisible(bVisible);
|
|
}
|
|
|
|
bool LtsDataView::showColumnCount() const
|
|
{
|
|
return m_ui->lblRows->isVisible();
|
|
}
|
|
|
|
void LtsDataView::setToolButtonsVisible(bool bVisible)
|
|
{
|
|
m_ui->tbCsvExport->setVisible(bVisible);
|
|
m_ui->tbCopy->setVisible(bVisible);
|
|
m_ui->tbTable->setVisible(bVisible);
|
|
m_ui->tbCustom->setVisible(bVisible);
|
|
m_ui->line->setVisible(bVisible);
|
|
}
|
|
|
|
bool LtsDataView::toolButtonsVisible() const
|
|
{
|
|
return m_ui->tbCsvExport->isVisible() &&
|
|
m_ui->tbCopy->isVisible() &&
|
|
m_ui->tbTable->isVisible() &&
|
|
m_ui->tbCustom->isVisible();
|
|
}
|
|
|
|
void LtsDataView::setAllColumnsShowFocus(bool enable)
|
|
{
|
|
m_ui->tableView->setAllColumnsShowFocus(enable);
|
|
}
|
|
|
|
bool LtsDataView::allColumnsShowFocus() const
|
|
{
|
|
return m_ui->tableView->allColumnsShowFocus();
|
|
}
|
|
|
|
void LtsDataView::hideColumn(int column, bool debugMode)
|
|
{
|
|
if (debugMode)
|
|
m_DebugModeColIds.insert(column); // used in setting column order and visibility
|
|
|
|
setColumnHidden(column, true);
|
|
}
|
|
|
|
void LtsDataView::showColumn(int column)
|
|
{
|
|
setColumnHidden(column, false);
|
|
}
|
|
|
|
bool LtsDataView::isColumnHidden(int column) const
|
|
{
|
|
return m_ui->searchView->isColumnHidden(column);
|
|
}
|
|
|
|
void LtsDataView::setColumnHidden(int column, bool hide)
|
|
{
|
|
m_ui->searchView->setColumnHidden(column, hide);
|
|
m_ui->tableView->setColumnHidden(column, hide);
|
|
}
|
|
|
|
|
|
|
|
void LtsDataView::setAutoResizeToContent(bool enable)
|
|
{
|
|
m_autoResizeToConent = enable;
|
|
}
|
|
|
|
bool LtsDataView::autoResizeToContent() const
|
|
{
|
|
return m_autoResizeToConent;
|
|
}
|
|
|
|
void LtsDataView::resizeSection(int logicalIndex, int size)
|
|
{
|
|
m_ui->searchView->header()->resizeSection(logicalIndex, size);
|
|
}
|
|
|
|
void LtsDataView::resizeHeadersByContent()
|
|
{
|
|
for (int i = 0; i < m_ui->tableView->header()->count(); i++)
|
|
slotResizeColumn(i);
|
|
}
|
|
|
|
void LtsDataView::resizeColumnsToContent()
|
|
{
|
|
if (!m_columnFilterProxy)
|
|
return;
|
|
// Sync von Header und Table erfolgt mit Aufruf von syncSearchHeaderAndTableContentColumnSize() nachdem das Modell initialisiert wurde.
|
|
const int colCount = m_columnFilterProxy->columnCount();
|
|
for (int col = 0; col < colCount; ++col)
|
|
m_ui->tableView->header()->setSectionResizeMode(col, QHeaderView::ResizeToContents);
|
|
}
|
|
|
|
void LtsDataView::syncSearchHeaderAndTableContentColumnSize()
|
|
{
|
|
m_ui->searchView->header()->resizeSections(QHeaderView::ResizeToContents);
|
|
const int colCount = m_columnFilterProxy->columnCount();
|
|
for (int col = 0; col < colCount; ++col)
|
|
slotResizeColumn(col);
|
|
}
|
|
|
|
void LtsDataView::setRootIndex(const QModelIndex &srcIndex)
|
|
{
|
|
m_ui->searchView->setRootIndex((srcIndex));
|
|
m_ui->tableView->setRootIndex(m_columnFilterProxy->mapFromSource(srcIndex));
|
|
m_ui->customView->setRootIndex(m_columnFilterProxy->mapFromSource(srcIndex));
|
|
}
|
|
|
|
|
|
|
|
void LtsDataView::setSortIndicator(int logicalIndex, Qt::SortOrder order)
|
|
{
|
|
m_ui->searchView->header()->setSortIndicator(logicalIndex, order);
|
|
}
|
|
|
|
void LtsDataView::setSortIndicatorShown(bool show)
|
|
{
|
|
m_ui->searchView->header()->setSortIndicatorShown(show);
|
|
}
|
|
|
|
|
|
|
|
Qt::ContextMenuPolicy LtsDataView::contextMenuPolicyPerView(LtsDataView::Page page) const
|
|
{
|
|
if (!m_ui)
|
|
return Qt::NoContextMenu;
|
|
|
|
switch (page)
|
|
{
|
|
case TABLE:
|
|
if (m_ui->tableView)
|
|
return m_ui->tableView->contextMenuPolicy();
|
|
break;
|
|
|
|
case CUSTOM:
|
|
if (m_ui->customView)
|
|
return m_ui->customView->contextMenuPolicy();
|
|
}
|
|
return Qt::NoContextMenu;
|
|
}
|
|
|
|
void LtsDataView::setContextMenuPolicyPerView(LtsDataView::Page page, Qt::ContextMenuPolicy policy)
|
|
{
|
|
if (!m_ui)
|
|
return;
|
|
|
|
switch (page)
|
|
{
|
|
case TABLE:
|
|
if (m_ui->tableView)
|
|
m_ui->tableView->setContextMenuPolicy(policy);
|
|
break;
|
|
case CUSTOM:
|
|
if (m_ui->customView)
|
|
m_ui->customView->setContextMenuPolicy(policy);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
QModelIndex LtsDataView::mapToSource(const QModelIndex &mi) const
|
|
{
|
|
return m_columnFilterProxy ? m_columnFilterProxy->mapToSource(mi) : mi;
|
|
}
|
|
|
|
QModelIndex LtsDataView::mapFromSource(const QModelIndex &mi) const
|
|
{
|
|
return m_columnFilterProxy ? m_columnFilterProxy->mapFromSource(mi) : mi;
|
|
}
|
|
|
|
QModelIndexList LtsDataView::mapToSource(const QModelIndexList &mil) const
|
|
{
|
|
QModelIndexList sourced;
|
|
if (!m_columnFilterProxy)
|
|
return sourced;
|
|
sourced.reserve(mil.size());
|
|
for (const auto &mi : mil)
|
|
sourced.append(mapToSource(mi));
|
|
|
|
return sourced;
|
|
}
|
|
|
|
QItemSelection LtsDataView::mapSelectionToSource(const QItemSelection &is) const
|
|
{
|
|
return m_columnFilterProxy ? m_columnFilterProxy->mapSelectionToSource(is) : is;
|
|
}
|
|
|
|
|
|
|
|
bool LtsDataView::setInitialSearchContent(int section, const QVariant &filterData)
|
|
{
|
|
if (!m_searchModel || !m_columnFilterProxy)
|
|
{
|
|
Q_ASSERT(false);
|
|
return false;
|
|
}
|
|
const QVariant headerData = m_columnFilterProxy->headerData(section, Qt::Horizontal, LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole);
|
|
const LtsWidgets::ComboboxFilterContent cfc(LtsWidgets::ComboboxFilterContent::fromVariant(headerData));
|
|
if (!cfc.isValid())
|
|
{
|
|
const QModelIndex index = m_searchModel->index(0, section, QModelIndex());
|
|
// assume it's a text search
|
|
m_searchModel->setData(index, filterData, Qt::DisplayRole);
|
|
m_searchModel->setData(index, filterData, Qt::EditRole);
|
|
return false;
|
|
}
|
|
for (const auto &d : cfc.data)
|
|
{
|
|
if (d.data == filterData)
|
|
{
|
|
const QModelIndex index = m_searchModel->index(0, section, QModelIndex());
|
|
m_searchModel->setData(index, d.text, Qt::DisplayRole);
|
|
m_searchModel->setData(index, d.data, LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void LtsDataView::setIconSize(const QSize &size)
|
|
{
|
|
m_ui->tableView->setIconSize(size);
|
|
}
|
|
|
|
|
|
|
|
QByteArray LtsDataView::saveState() const
|
|
{
|
|
return m_ui->searchView->header()->saveState();
|
|
}
|
|
|
|
bool LtsDataView::restoreState(const QByteArray &headerState)
|
|
{
|
|
bool ok = m_ui->searchView->header()->restoreState(headerState);
|
|
if (ok)
|
|
ok = m_ui->tableView->header()->restoreState(headerState);
|
|
return ok;
|
|
}
|
|
|
|
|
|
|
|
QString LtsDataView::createCsv() const
|
|
{
|
|
if (!m_columnFilterProxy)
|
|
return QString();
|
|
|
|
const QAbstractItemView *itemView = currentView();
|
|
const QModelIndexList selection = itemView->selectionModel()->selectedRows();
|
|
|
|
// create csv:
|
|
int cols = m_columnFilterProxy->columnCount();
|
|
QString csv;
|
|
QStringList csvLine;
|
|
|
|
for (auto i = selection.constBegin(); i != selection.constEnd(); ++i)
|
|
{
|
|
int row = (*i).row();
|
|
|
|
csvLine.clear();
|
|
for (int k = 0; k < cols; k++)
|
|
if (m_ui->stackedWidget->currentIndex() != TABLE || !m_ui->tableView->isColumnHidden(k))
|
|
csvLine.append(m_columnFilterProxy->data(m_columnFilterProxy->index(row, k)).toString());
|
|
|
|
csv += csvLine.join(QLatin1Char(';'));
|
|
csv += QStringLiteral("\n"); // FIXME: windows?
|
|
}
|
|
|
|
return csv;
|
|
}
|
|
|
|
void LtsDataView::addTouchScroll(QWidget *widget)
|
|
{
|
|
if (!widget)
|
|
return;
|
|
widget->setAttribute(Qt::WA_AcceptTouchEvents);
|
|
|
|
{
|
|
QScrollArea *sca = qobject_cast<QScrollArea *>(widget);
|
|
if (sca)
|
|
{
|
|
QScroller::grabGesture(sca->viewport(), QScroller::LeftMouseButtonGesture);
|
|
QScroller::grabGesture(sca, QScroller::LeftMouseButtonGesture);
|
|
return;
|
|
}
|
|
}
|
|
|
|
{
|
|
QAbstractItemView *aiv = qobject_cast<QAbstractItemView *>(widget);
|
|
if (aiv)
|
|
{
|
|
QScroller::grabGesture(aiv->viewport(), QScroller::LeftMouseButtonGesture);
|
|
QScroller::grabGesture(aiv, QScroller::LeftMouseButtonGesture);
|
|
aiv->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
|
aiv->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
QAbstractItemView *LtsDataView::currentView() const
|
|
{
|
|
if (m_ui->stackedWidget->currentIndex() == TABLE)
|
|
return m_ui->tableView;
|
|
return m_ui->customView;
|
|
}
|
|
|
|
|
|
|
|
void LtsDataView::keyPressEvent(QKeyEvent *event) // CustomView events land here
|
|
{
|
|
if (QGuiApplication::queryKeyboardModifiers() == Qt::ControlModifier
|
|
&& event->key() == Qt::Key_C)
|
|
slotCopyToClipboard();
|
|
|
|
// Enter: Enter on numpad
|
|
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
|
|
emit signalEnterPressed();
|
|
|
|
QWidget::keyPressEvent(event);
|
|
}
|
|
|
|
|
|
|
|
void LtsDataView::selectTableView()
|
|
{
|
|
selectView(TABLE);
|
|
}
|
|
|
|
void LtsDataView::selectCustomView()
|
|
{
|
|
selectView(CUSTOM);
|
|
}
|
|
|
|
void LtsDataView::selectView(Page page)
|
|
{
|
|
m_ui->tbTable->setChecked(page == TABLE);
|
|
m_ui->tbCustom->setChecked(page == CUSTOM);
|
|
m_ui->stackedWidget->setCurrentIndex(page);
|
|
slotSetVerticalRange();
|
|
slotSetVerticalValue(m_ui->customView->verticalScrollBar()->value());
|
|
}
|
|
|
|
void LtsDataView::slotCopyToClipboard()
|
|
{
|
|
QApplication::clipboard()->setText(createCsv()); // finally copy to clipboard
|
|
}
|
|
|
|
void LtsDataView::collapseAll()
|
|
{
|
|
m_ui->tableView->collapseAll();
|
|
}
|
|
|
|
void LtsDataView::expandAll()
|
|
{
|
|
m_ui->tableView->expandAll();
|
|
}
|
|
|
|
void LtsDataView::expand(const QModelIndex &index)
|
|
{
|
|
m_ui->tableView->expand(index);
|
|
}
|
|
|
|
void LtsDataView::setSortingEnabled(bool enable)
|
|
{
|
|
m_ui->searchView->setSortingEnabled(enable);
|
|
m_ui->tableView->setSortingEnabled(enable);
|
|
}
|
|
|
|
|
|
|
|
void LtsDataView::slotSetSortIndicator(int logicalIndex, Qt::SortOrder order)
|
|
{
|
|
m_ui->tableView->header()->setSortIndicator(logicalIndex, order);
|
|
// TODO: needed since custom view rebuild?:
|
|
m_ui->customView->update();
|
|
emit sortOrderChanged(logicalIndex, order);
|
|
}
|
|
|
|
void LtsDataView::slotRowCountChanged()
|
|
{
|
|
if (m_columnFilterProxy && m_columnFilterProxy->sourceModel())
|
|
m_ui->lbRows->setText(tr("%1 of %2")
|
|
.arg(m_columnFilterProxy->rowCount())
|
|
.arg(m_columnFilterProxy->sourceModel()->rowCount()));
|
|
|
|
// customview: sometimes the gui is not updated if model is cleared:
|
|
// (Example: clear JumpPointModel by selecting a workspace WITHOUT JumpPoints)
|
|
// TODO: needed since custom view rebuild?:
|
|
if (m_ui->customView &&
|
|
m_columnFilterProxy &&
|
|
m_columnFilterProxy->sourceModel() &&
|
|
m_columnFilterProxy->sourceModel()->rowCount() == 0)
|
|
m_ui->customView->update();
|
|
}
|
|
|
|
void LtsDataView::slotSetHorizontalRange(int min, int max)
|
|
{
|
|
m_ui->searchView->horizontalScrollBar()->hide(); // always hide!
|
|
if (!min && !max) // no min, no max = not visible
|
|
m_ui->horizontalScrollBar->hide();
|
|
else
|
|
m_ui->horizontalScrollBar->show();
|
|
|
|
//qWarning() << "hori: min" << min << "max" << max;
|
|
|
|
m_ui->horizontalScrollBar->setRange(min, max);
|
|
m_ui->horizontalScrollBar->setPageStep(m_ui->searchView->horizontalScrollBar()->pageStep());
|
|
}
|
|
|
|
void LtsDataView::updateColumnsVisibility(const QVector<ColumnOrganiserInfo> &data)
|
|
{
|
|
const int colCount = m_columnFilterProxy->columnCount();
|
|
for(const auto &ci : data)
|
|
{
|
|
if(ci.logicalIndex >= colCount || ci.logicalIndex < 0)
|
|
continue;
|
|
|
|
|
|
m_ui->searchView->setColumnHidden(ci.logicalIndex, ci.hide());
|
|
}
|
|
|
|
// save setting
|
|
saveTableSettings();
|
|
}
|
|
|
|
void LtsDataView::slotSetColumnsDefaultOrder()
|
|
{
|
|
saveTableSettings(true);
|
|
m_userChangedColumnPos = false; // save is already done so avoid saving while restoring data
|
|
restoreTableSettings();
|
|
m_userChangedColumnPos = true;
|
|
}
|
|
|
|
void LtsDataView::slotSetHorizontalValue(int val)
|
|
{
|
|
m_ui->horizontalScrollBar->setValue(val);
|
|
}
|
|
|
|
void LtsDataView::slotSetVerticalRange(int , int )
|
|
{
|
|
// when custom view gets new data (dds data topic), table view and custom view send new ranges, only take the range of the active tab in stacked widget
|
|
m_ui->tableView->verticalScrollBar()->hide(); // always hide!
|
|
m_ui->customView->verticalScrollBar()->hide(); // always hide!
|
|
|
|
QScrollBar *whichScrollBar = m_ui->tableView->verticalScrollBar();
|
|
|
|
if (m_ui->stackedWidget->currentIndex() == CUSTOM)
|
|
whichScrollBar = m_ui->customView->verticalScrollBar();
|
|
|
|
int min = whichScrollBar->minimum();
|
|
int max = whichScrollBar->maximum();
|
|
int pagestep = whichScrollBar->pageStep();
|
|
|
|
if (!min && !max) // no min, no max = not visible
|
|
m_ui->verticalScrollBar->hide();
|
|
else
|
|
m_ui->verticalScrollBar->show();
|
|
|
|
// dont know which scrollbar it is
|
|
m_ui->verticalScrollBar->setRange(min, max);
|
|
m_ui->verticalScrollBar->setPageStep(pagestep);
|
|
}
|
|
|
|
void LtsDataView::slotSetVerticalValue(int val)
|
|
{
|
|
QScrollBar *caller = qobject_cast<QScrollBar *>(QObject::sender());
|
|
if (caller && caller->isVisible())
|
|
m_ui->verticalScrollBar->setVisible(caller->isVisible());
|
|
|
|
m_ui->verticalScrollBar->setValue(val);
|
|
}
|
|
|
|
void LtsDataView::slotSectionResized(int index, int oldSize, int newSize)
|
|
{
|
|
if (newSize == 0)
|
|
{
|
|
m_ui->tableView->setColumnHidden(index, true);
|
|
return;
|
|
}
|
|
if (oldSize == 0)
|
|
m_ui->tableView->setColumnHidden(index, false);
|
|
m_ui->tableView->setColumnWidth(index, newSize);
|
|
}
|
|
|
|
void LtsDataView::slotHeaderMoved(int logicalColumn, int oldColumn, int newColumn)
|
|
{
|
|
Q_UNUSED(logicalColumn);
|
|
m_ui->tableView->header()->moveSection(oldColumn, newColumn);
|
|
|
|
if (m_userChangedColumnPos)
|
|
{
|
|
qWarning()<<">>>> [updateColumnsVisibility]";
|
|
saveTableSettings();
|
|
}
|
|
}
|
|
|
|
void LtsDataView::slotCsvExport() // TODO: maybe save to dds (office/filemanagement) instead of hd?
|
|
{
|
|
if (!m_columnFilterProxy)
|
|
return;
|
|
|
|
QFileDialog dialog(this); // save dialog
|
|
//dialog.setFileMode(QFileDialog::ExistingFile); // single file selection
|
|
dialog.setNameFilter(tr("CSV File (*.csv)"));
|
|
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
|
|
|
if (!dialog.exec())
|
|
return;
|
|
const QStringList fileNames = dialog.selectedFiles();
|
|
if (fileNames.isEmpty())
|
|
return;
|
|
|
|
QFile file;
|
|
file.setFileName(fileNames.first());
|
|
|
|
if (!file.open(QFile::ReadWrite))
|
|
{
|
|
LtsWidgets::LtsMessageDialog::showMessage(this, tr("File '%1' is not accessible").arg(fileNames.at(0)), tr("CSV Export"));
|
|
return;
|
|
}
|
|
|
|
QHeaderView* hdr = m_ui->tableView->header();
|
|
QMap<int, int> colsHeader; //<visualIndex, logicalIndex>
|
|
|
|
// create header csv
|
|
const int cols = m_columnFilterProxy->columnCount();
|
|
QStringList colsList;
|
|
colsList.reserve(cols);
|
|
for (int i = 0; i < cols; ++i)
|
|
{
|
|
if (m_ui->stackedWidget->currentIndex() != TABLE || !m_ui->tableView->isColumnHidden(i))
|
|
{
|
|
int visualIndex = hdr->visualIndex(i);
|
|
colsHeader[visualIndex] = i;
|
|
//colsList.append(m_columnFilterProxy->headerData(i, Qt::Horizontal).toString());
|
|
}
|
|
}
|
|
|
|
for (const int logicalIndex : std::as_const(colsHeader))
|
|
colsList.append(m_columnFilterProxy->headerData(logicalIndex, Qt::Horizontal).toString());
|
|
|
|
//qCritical() << "slotCsvExport: header colsList = " << colsList;
|
|
|
|
const QString columnCsv = colsList.join(QLatin1Char(';'));
|
|
file.write(columnCsv.toLocal8Bit()); // write header
|
|
file.write("\n");
|
|
|
|
// write csv body
|
|
//file.write(createCsv().toStdString().c_str());
|
|
|
|
// create body csv (with all rows)
|
|
// TODO: threaded? as this can take a while
|
|
const int rows = m_columnFilterProxy->rowCount();
|
|
QStringList rowsList;
|
|
rowsList.reserve(rows);
|
|
for (int row = 0; row < rows; ++row)
|
|
{
|
|
colsList.clear();
|
|
for (const int logicalIndex : std::as_const(colsHeader))
|
|
colsList.append(m_columnFilterProxy->data(m_columnFilterProxy->index(row, logicalIndex)).toString());
|
|
// for (int col = 0; col < cols; col++)
|
|
// if (m_ui->stackedWidget->currentIndex() != TABLE || !m_ui->tableView->isColumnHidden(col))
|
|
// colsList.append(m_columnFilterProxy->data(m_columnFilterProxy->index(row, col)).toString());
|
|
|
|
//qCritical() << "slotCsvExport: row = "<< row << ", colsList = " << colsList;
|
|
rowsList.append(colsList.join(QLatin1Char(';')));
|
|
}
|
|
|
|
const QString csvBody = rowsList.join(QLatin1Char('\n')); // TODO: windows?
|
|
|
|
file.write(csvBody.toLocal8Bit());
|
|
|
|
file.close();
|
|
|
|
LtsWidgets::LtsMessageDialog::showMessage(this, tr("CSV Export was successful"), tr("CSV Export"));
|
|
}
|
|
|
|
void LtsDataView::slotResizeColumn(int columnIndex)
|
|
{
|
|
m_ui->tableView->resizeColumnToContents(columnIndex);
|
|
|
|
QHeaderView *header = m_ui->searchView->header();
|
|
int minimumWidth = header->sectionSize(columnIndex);
|
|
int contentWidth = m_ui->tableView->columnWidth(columnIndex);
|
|
|
|
if (contentWidth > minimumWidth)
|
|
header->resizeSection(columnIndex, contentWidth);
|
|
else
|
|
m_ui->tableView->header()->resizeSection(columnIndex, minimumWidth);
|
|
}
|
|
|
|
void LtsDataView::onCustomContextMenuRequested(const QPoint &pos)
|
|
{
|
|
if (!m_ui)
|
|
return;
|
|
QModelIndex mi;
|
|
QPoint globalPos;
|
|
if (m_ui->stackedWidget->currentIndex() == CUSTOM)
|
|
{
|
|
if (m_ui->customView)
|
|
{
|
|
mi = m_ui->customView->indexAt(pos);
|
|
globalPos = m_ui->customView->mapToGlobal(pos);
|
|
} else if (m_ui->tableView)
|
|
{
|
|
mi = m_ui->tableView->indexAt(pos);
|
|
globalPos = m_ui->tableView->mapToGlobal(pos);
|
|
}
|
|
} else if (m_ui->stackedWidget->currentIndex() == TABLE)
|
|
{
|
|
if (m_ui->tableView)
|
|
{
|
|
mi = m_ui->tableView->indexAt(pos);
|
|
globalPos = m_ui->tableView->mapToGlobal(pos);
|
|
}
|
|
}
|
|
|
|
emit signalContextMenuRequested(globalPos, mapToSource(mi));
|
|
}
|
|
|
|
//void LtsDataView::setDelegate(std::function<AbstractDisplayWidget*()> delegateFunction)
|
|
//{
|
|
// m_ui->customView->setDelegate(delegateFunction);
|
|
//}
|
|
|
|
} // namespace LtsDataView
|