mirror of
https://github.com/feather-wallet/feather.git
synced 2025-01-08 20:09:43 +00:00
224 lines
No EOL
7.3 KiB
C++
224 lines
No EOL
7.3 KiB
C++
// SPDX-License-Identifier: BSD-3-Clause
|
|
// SPDX-FileCopyrightText: 2020-2024 The Monero Project
|
|
|
|
#include "HistoryView.h"
|
|
|
|
#include "TransactionHistoryProxyModel.h"
|
|
#include "utils/Utils.h"
|
|
#include "utils/config.h"
|
|
|
|
#include <QHeaderView>
|
|
#include <QMenu>
|
|
|
|
HistoryView::HistoryView(QWidget *parent)
|
|
: QTreeView(parent)
|
|
, m_model(nullptr)
|
|
, m_headerMenu(new QMenu(this))
|
|
{
|
|
setUniformRowHeights(true);
|
|
setRootIsDecorated(false);
|
|
setAlternatingRowColors(true);
|
|
setDragEnabled(true);
|
|
setSortingEnabled(true);
|
|
|
|
header()->setStretchLastSection(false);
|
|
header()->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
|
|
connect(header(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(showHeaderMenu(QPoint)));
|
|
}
|
|
|
|
void HistoryView::setHistoryModel(TransactionHistoryProxyModel *model) {
|
|
m_model = model;
|
|
m_model->setSortCaseSensitivity(Qt::CaseInsensitive);
|
|
m_model->setSortRole(Qt::UserRole);
|
|
m_model->setDynamicSortFilter(true);
|
|
m_model->setSortLocaleAware(true);
|
|
|
|
QTreeView::setModel(m_model);
|
|
resetViewToDefaults();
|
|
|
|
m_headerMenu->clear();
|
|
|
|
// Actions to toggle column visibility, each carrying the corresponding
|
|
// column index as data
|
|
m_columnActions = new QActionGroup(this);
|
|
m_columnActions->setExclusive(false);
|
|
for (int visualIndex = 1; visualIndex < header()->count(); ++visualIndex) {
|
|
int logicalIndex = header()->logicalIndex(visualIndex);
|
|
QString caption = m_model->headerData(logicalIndex, Qt::Horizontal, Qt::DisplayRole).toString();
|
|
if (caption.isEmpty()) {
|
|
caption = m_model->headerData(logicalIndex, Qt::Horizontal, Qt::ToolTipRole).toString();
|
|
}
|
|
|
|
auto action = m_headerMenu->addAction(caption);
|
|
action->setCheckable(true);
|
|
action->setData(logicalIndex);
|
|
m_columnActions->addAction(action);
|
|
}
|
|
connect(m_columnActions, &QActionGroup::triggered, this, &HistoryView::toggleColumnVisibility);
|
|
|
|
m_headerMenu->addSeparator();
|
|
auto action = m_headerMenu->addAction("Show full txid", this, &HistoryView::showFullTxid);
|
|
action->setCheckable(true);
|
|
action->setChecked(conf()->get(Config::historyShowFullTxid).toBool());
|
|
m_headerMenu->addSeparator();
|
|
m_headerMenu->addAction(tr("Fit to window"), this, &HistoryView::fitColumnsToWindow);
|
|
m_headerMenu->addAction(tr("Fit to contents"), this, &HistoryView::fitColumnsToContents);
|
|
m_headerMenu->addSeparator();
|
|
m_headerMenu->addAction(tr("Reset to defaults"), this, &HistoryView::resetViewToDefaults);
|
|
|
|
fitColumnsToWindow();
|
|
}
|
|
|
|
TransactionHistoryModel* HistoryView::sourceModel()
|
|
{
|
|
return dynamic_cast<TransactionHistoryModel *>(m_model->sourceModel());
|
|
}
|
|
|
|
TransactionRow* HistoryView::currentEntry()
|
|
{
|
|
QModelIndexList list = selectionModel()->selectedRows();
|
|
if (list.size() == 1) {
|
|
return this->sourceModel()->entryFromIndex(m_model->mapToSource(list.first()));
|
|
} else {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
void HistoryView::setSearchMode(bool mode) {
|
|
if (!m_inSearchMode) {
|
|
m_showTxidColumn = !header()->isSectionHidden(TransactionHistoryModel::TxID);
|
|
}
|
|
|
|
m_inSearchMode = mode;
|
|
|
|
if (mode) {
|
|
header()->showSection(TransactionHistoryModel::TxID);
|
|
}
|
|
else if (!m_showTxidColumn) {
|
|
header()->hideSection(TransactionHistoryModel::TxID);
|
|
}
|
|
}
|
|
|
|
QByteArray HistoryView::viewState() const
|
|
{
|
|
return header()->saveState();
|
|
}
|
|
|
|
bool HistoryView::setViewState(const QByteArray& state)
|
|
{
|
|
// Reset to unsorted first (https://bugreports.qt.io/browse/QTBUG-86694)
|
|
header()->setSortIndicator(-1, Qt::AscendingOrder);
|
|
bool status = header()->restoreState(state);
|
|
m_columnsNeedRelayout = state.isEmpty();
|
|
|
|
m_showTxidColumn = !header()->isSectionHidden(TransactionHistoryModel::TxID);
|
|
return status;
|
|
}
|
|
|
|
void HistoryView::showHeaderMenu(const QPoint& position)
|
|
{
|
|
const QList<QAction*> actions = m_columnActions->actions();
|
|
for (auto& action : actions) {
|
|
Q_ASSERT(static_cast<QMetaType::Type>(action->data().type()) == QMetaType::Int);
|
|
if (static_cast<QMetaType::Type>(action->data().type()) != QMetaType::Int) {
|
|
continue;
|
|
}
|
|
int columnIndex = action->data().toInt();
|
|
action->setChecked(!isColumnHidden(columnIndex));
|
|
}
|
|
|
|
m_headerMenu->popup(mapToGlobal(position));
|
|
}
|
|
|
|
void HistoryView::toggleColumnVisibility(QAction* action)
|
|
{
|
|
// Verify action carries a column index as data. Since QVariant.toInt()
|
|
// below will accept anything that's interpretable as int, perform a type
|
|
// check here to make sure data actually IS int
|
|
Q_ASSERT(static_cast<QMetaType::Type>(action->data().type()) == QMetaType::Int);
|
|
if (static_cast<QMetaType::Type>(action->data().type()) != QMetaType::Int) {
|
|
return;
|
|
}
|
|
|
|
// Toggle column visibility. Visible columns will only be hidden if at
|
|
// least one visible column remains, as the table header will disappear
|
|
// entirely when all columns are hidden
|
|
int columnIndex = action->data().toInt();
|
|
if (action->isChecked()) {
|
|
header()->showSection(columnIndex);
|
|
if (header()->sectionSize(columnIndex) == 0) {
|
|
header()->resizeSection(columnIndex, header()->defaultSectionSize());
|
|
}
|
|
return;
|
|
}
|
|
if ((header()->count() - header()->hiddenSectionCount()) > 1) {
|
|
header()->hideSection(columnIndex);
|
|
return;
|
|
}
|
|
action->setChecked(true);
|
|
}
|
|
|
|
void HistoryView::showFullTxid(bool enabled) {
|
|
conf()->set(Config::historyShowFullTxid, enabled);
|
|
this->reset();
|
|
|
|
|
|
if (!enabled) {
|
|
this->resizeColumnToContents(TransactionHistoryModel::TxID);
|
|
}
|
|
}
|
|
|
|
void HistoryView::fitColumnsToWindow()
|
|
{
|
|
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
|
header()->setSectionResizeMode(TransactionHistoryModel::Description, QHeaderView::Stretch);
|
|
header()->setStretchLastSection(false);
|
|
QCoreApplication::processEvents();
|
|
}
|
|
|
|
void HistoryView::fitColumnsToContents()
|
|
{
|
|
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
|
QCoreApplication::processEvents();
|
|
header()->setSectionResizeMode(QHeaderView::Interactive);
|
|
}
|
|
|
|
void HistoryView::resetViewToDefaults()
|
|
{
|
|
if (m_inSearchMode) {
|
|
header()->showSection(TransactionHistoryModel::TxID);
|
|
} else {
|
|
header()->hideSection(TransactionHistoryModel::TxID);
|
|
}
|
|
header()->showSection(TransactionHistoryModel::Date);
|
|
header()->showSection(TransactionHistoryModel::Description);
|
|
header()->showSection(TransactionHistoryModel::Amount);
|
|
header()->showSection(TransactionHistoryModel::FiatAmount);
|
|
|
|
// Reset column order to logical indices
|
|
for (int i = 0; i < header()->count(); ++i) {
|
|
header()->moveSection(header()->visualIndex(i), i);
|
|
}
|
|
|
|
m_model->sort(TransactionHistoryModel::Date, Qt::DescendingOrder);
|
|
sortByColumn(TransactionHistoryModel::Date, Qt::DescendingOrder);
|
|
|
|
// The following call only relayouts reliably if the widget has been shown
|
|
// already, so only do it if the widget is visible and let showEvent() handle
|
|
// the initial default layout.
|
|
if (isVisible()) {
|
|
fitColumnsToWindow();
|
|
}
|
|
}
|
|
|
|
void HistoryView::keyPressEvent(QKeyEvent *event) {
|
|
TransactionRow* tx = this->currentEntry();
|
|
|
|
if (event->matches(QKeySequence::Copy) && tx) {
|
|
Utils::copyToClipboard(tx->hash());
|
|
}
|
|
else {
|
|
QTreeView::keyPressEvent(event);
|
|
}
|
|
} |