417 lines
10 KiB
C++
Executable File
417 lines
10 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* SideBar
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
* Created by Norbert Thoden, SLSE, 2015-01-19
|
|
*/
|
|
|
|
|
|
// Own
|
|
#include "side_bar.h"
|
|
#include "side_bar_model.h"
|
|
|
|
// Qt
|
|
#include <QVBoxLayout>
|
|
#include <QLabel>
|
|
#include <QPushButton>
|
|
#include <QTreeView>
|
|
#include <QKeyEvent>
|
|
#include <QSharedPointer>
|
|
#include <QPropertyAnimation>
|
|
#include <QPainter>
|
|
#include <QIcon>
|
|
#include <QTimer>
|
|
|
|
namespace SituationMap
|
|
{
|
|
|
|
class SideBar::Private
|
|
{
|
|
public:
|
|
Private() = default;
|
|
~Private() = default;
|
|
|
|
|
|
SideBarModel *m_model = nullptr;
|
|
QTreeView *m_view = nullptr;
|
|
bool m_suppressClick = false;
|
|
QTimer *m_suppressTimer = nullptr;
|
|
|
|
QSharedPointer<QPropertyAnimation> m_sideBarAniOn;
|
|
QSharedPointer<QPropertyAnimation> m_sideBarAniOff;
|
|
|
|
|
|
}; // class SideBar::Private
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
QImage SideBar::createImage(const QColor &fgColor,
|
|
const QColor &bgColor,
|
|
int size)
|
|
{
|
|
QImage burgerMenueImage(size, size, QImage::Format_ARGB32);
|
|
if (bgColor.isValid())
|
|
burgerMenueImage.fill(bgColor);
|
|
else
|
|
burgerMenueImage.fill(Qt::transparent);
|
|
|
|
QPainter p(&burgerMenueImage);
|
|
|
|
{
|
|
QPen pen(Qt::white);
|
|
pen.setWidth(size * 0.15);
|
|
pen.setCapStyle(Qt::PenCapStyle::RoundCap);
|
|
p.setPen(pen);
|
|
|
|
double yFactor = 0.1;
|
|
p.drawLine(QPointF(size * yFactor, size * 0.25), QPointF(size - size * yFactor, size * 0.25));
|
|
p.drawLine(QPointF(size * yFactor, size * 0.50), QPointF(size - size * yFactor, size * 0.50));
|
|
p.drawLine(QPointF(size * yFactor, size * 0.75), QPointF(size - size * yFactor, size * 0.75));
|
|
}
|
|
|
|
{
|
|
QPen pen(fgColor);
|
|
pen.setWidth(size * 0.1);
|
|
pen.setCapStyle(Qt::PenCapStyle::RoundCap);
|
|
p.setPen(pen);
|
|
|
|
double yFactor = 0.1;
|
|
p.drawLine(QPointF(size * yFactor, size * 0.25), QPointF(size - size * yFactor, size * 0.25));
|
|
p.drawLine(QPointF(size * yFactor, size * 0.50), QPointF(size - size * yFactor, size * 0.50));
|
|
p.drawLine(QPointF(size * yFactor, size * 0.75), QPointF(size - size * yFactor, size * 0.75));
|
|
}
|
|
|
|
return burgerMenueImage;
|
|
}
|
|
|
|
QIcon SideBar::createIcon(const QColor &fgColor,
|
|
const QColor &bgColor,
|
|
int size)
|
|
{
|
|
return QIcon(QPixmap::fromImage(SideBar::createImage(fgColor, bgColor, size)));
|
|
}
|
|
|
|
|
|
SideBar::SideBar(QWidget *parent)
|
|
: BaseClass(parent)
|
|
, d(new Private)
|
|
, m_logger(getLogger("SideBar"))
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
|
|
// Prepare animations:
|
|
d->m_sideBarAniOn = QSharedPointer<QPropertyAnimation>(new QPropertyAnimation(this, "pos"));
|
|
connect(d->m_sideBarAniOn.data(), &QPropertyAnimation::finished, this, &SideBar::onAnimationOnFinished);
|
|
|
|
d->m_sideBarAniOff = QSharedPointer<QPropertyAnimation>(new QPropertyAnimation(this, "pos"));
|
|
connect(d->m_sideBarAniOff.data(), &QPropertyAnimation::finished, this, &SideBar::onAnimationOffFinished);
|
|
|
|
QVBoxLayout *layout = new QVBoxLayout();
|
|
layout->setObjectName(QLatin1String("SideBarLayout"));
|
|
this->setLayout(layout);
|
|
|
|
// 1st row
|
|
QHBoxLayout *layoutTopRow = new QHBoxLayout();
|
|
layoutTopRow->setObjectName(QLatin1String("SideBarTopRowLayout"));
|
|
layout->addLayout(layoutTopRow);
|
|
layoutTopRow->addStretch(2);
|
|
|
|
QPushButton *close = new QPushButton();
|
|
close->setObjectName(QLatin1String("SideBarCloseButton"));
|
|
close->setMinimumSize(QSize(0, 0));
|
|
close->setStyleSheet(QLatin1String("QPushButton {background-color: white; border: 1px solid transparent;}"));
|
|
close->setIcon(QIcon(QLatin1String("icon:dialog-close.svg")));
|
|
// close->setIcon(QIcon(QLatin1String("qrc:///icons/svg/dialog-close.svg")));
|
|
close->setIconSize(QSize(20, 20));
|
|
// close->setStyleSheet(QLatin1String("QPushButton { image: url(\"icon:dialog-close.svg\"); }"));
|
|
|
|
|
|
|
|
// lambda :-)
|
|
connect(close, &QPushButton::clicked, this, [this]()
|
|
{
|
|
emit closeRequest();
|
|
this->hideAnimated();
|
|
});
|
|
|
|
|
|
layoutTopRow->addWidget(close);
|
|
|
|
// 2nd Row
|
|
d->m_view = new QTreeView(this);
|
|
if (d->m_view)
|
|
{
|
|
d->m_view->setObjectName(QLatin1String("SideBarTreeView"));
|
|
d->m_view->setMinimumSize(QSize(0, 0));
|
|
d->m_view->setAlternatingRowColors(true);
|
|
connect(d->m_view, &QTreeView::clicked, this, &SideBar::onClicked);
|
|
|
|
layout->addWidget(d->m_view);
|
|
|
|
initModel();
|
|
d->m_view->setModel(d->m_model);
|
|
}
|
|
|
|
initAppearanceToSideBar(true);
|
|
//initAppearanceToSideBar(false);
|
|
|
|
|
|
d->m_suppressTimer = new QTimer(this);
|
|
d->m_suppressTimer->setSingleShot(true);
|
|
d->m_suppressTimer->setInterval(20);
|
|
connect(d->m_suppressTimer, &QTimer::timeout, this, [this]() {
|
|
d->m_suppressClick = false;
|
|
});
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
}
|
|
|
|
|
|
SideBar::~SideBar()
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
delete d;
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
}
|
|
|
|
|
|
bool SideBar::initAppearanceToSideBar(bool toSideBar)
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START, toSideBar = " << toSideBar;
|
|
|
|
if (toSideBar)
|
|
{
|
|
setWindowFlag(Qt::FramelessWindowHint);
|
|
if (d->m_view)
|
|
d->m_view->setHeaderHidden(true); // only TreeView
|
|
|
|
this->layout()->setSpacing(0);
|
|
this->layout()->setContentsMargins(0, 0, 0, 0);
|
|
|
|
// d->m_view->setStyleSheet(QLatin1String("QLabel {border: none;}"));
|
|
|
|
}
|
|
else
|
|
{
|
|
if (d->m_view)
|
|
d->m_view->setHeaderHidden(false);
|
|
|
|
this->layout()->setSpacing(2);
|
|
this->layout()->setContentsMargins(-1, -1, -1, -1); // -1 -> invalid (!?)
|
|
|
|
}
|
|
|
|
setAutoFillBackground(true);
|
|
// // this->setStyleSheet(QLatin1String("QWidget {background-color: white;}"));
|
|
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
return true;
|
|
}
|
|
|
|
void SideBar::setAnimationDuration(int msecs)
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
d->m_sideBarAniOn->setDuration(msecs);
|
|
d->m_sideBarAniOff->setDuration(msecs);
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
}
|
|
|
|
void SideBar::setInvisiblePosition(const QPoint &invisiblePos)
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " invisiblePos=" << invisiblePos;
|
|
|
|
// x--->
|
|
d->m_sideBarAniOn->setStartValue(invisiblePos);
|
|
|
|
// x<---
|
|
d->m_sideBarAniOff->setEndValue(invisiblePos);
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " invisiblePos=" << invisiblePos;
|
|
}
|
|
|
|
void SideBar::setVisiblePosition(const QPoint &visiblePos)
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " visiblePos=" << visiblePos;
|
|
|
|
// --->x
|
|
d->m_sideBarAniOn->setEndValue(visiblePos);
|
|
|
|
// <---x
|
|
d->m_sideBarAniOff->setStartValue(visiblePos);
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " visiblePos=" << visiblePos;
|
|
}
|
|
|
|
void SideBar::showAnimated()
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
this->show();
|
|
this->raise();
|
|
|
|
onAnimationStarted();
|
|
d->m_sideBarAniOn->start();
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
}
|
|
|
|
bool SideBar::isCurrentlyShowing()
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
return d->m_sideBarAniOn->state() == QAbstractAnimation::Running;
|
|
}
|
|
|
|
void SideBar::hideAnimated()
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
|
|
// use current position (maybe showAnimation is interrupted)
|
|
d->m_sideBarAniOff->setStartValue(this->pos());
|
|
|
|
onAnimationStarted();
|
|
d->m_sideBarAniOff->start();
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
}
|
|
|
|
bool SideBar::isCurrentlyHiding()
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
return d->m_sideBarAniOff->state() == QAbstractAnimation::Running;
|
|
}
|
|
|
|
|
|
bool SideBar::initModel()
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
|
|
delete d->m_model;
|
|
d->m_model = new SideBarModel(this);
|
|
d->m_model->setObjectName(QLatin1String("SideBarModel"));
|
|
|
|
connect(d->m_model, &SideBarModel::itemChanged, this, &SideBar::onItemChanged);
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
return true;
|
|
}
|
|
|
|
bool SideBar::addCheckableItem(SideBarItem *item)
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
|
|
item->setCheckable(true);
|
|
item->setEditable(false);
|
|
|
|
d->m_model->addItem(item);
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
return true;
|
|
}
|
|
|
|
|
|
bool SideBar::addWidget(QWidget *widget)
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
|
|
this->layout()->addWidget(widget);
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
return true;
|
|
}
|
|
|
|
void SideBar::onItemChanged(QStandardItem *item)
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
|
|
QString itemText(QLatin1String("-"));
|
|
if (item)
|
|
itemText = item->text();
|
|
INFO_LOG(m_logger) << LOGFUNCTION << " itemChanged, itemText='" << itemText << "'";
|
|
|
|
// hide if empty:
|
|
if (d->m_view)
|
|
d->m_view->setEnabled(d->m_model->rowCount() > 0);
|
|
|
|
emit dataChanged();
|
|
|
|
// If user clicks checkbox, 'clicked' is also emitted afterwards...
|
|
// In this case, avoid evaluating that signal for a small amount on time
|
|
d->m_suppressClick = true;
|
|
d->m_suppressTimer->start();
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
}
|
|
|
|
void SideBar::onAnimationOnFinished()
|
|
{
|
|
onAnimationFinished();
|
|
}
|
|
|
|
void SideBar::onAnimationOffFinished()
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
|
|
this->hide();
|
|
onAnimationFinished();
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
}
|
|
|
|
void SideBar::onClicked(const QModelIndex &index)
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
|
|
if (!d->m_model)
|
|
return;
|
|
|
|
if (d->m_suppressClick)
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << " m_suppressClick";
|
|
return;
|
|
}
|
|
|
|
QStandardItem *item = d->m_model->itemFromIndex(index);
|
|
if (!item)
|
|
return;
|
|
if (!item->isCheckable())
|
|
return;
|
|
if (!item->isEnabled())
|
|
return;
|
|
|
|
if (item->checkState() == Qt::CheckState::Checked)
|
|
item->setCheckState(Qt::CheckState::Unchecked);
|
|
else
|
|
item->setCheckState(Qt::CheckState::Checked);
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
}
|
|
|
|
void SideBar::onAnimationStarted()
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
|
|
int h = this->parentWidget()->height();
|
|
this->setFixedHeight(h); // SetFixedSize/setFixedHeight to have smooth animations, especially in case of some JumpPoints
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
}
|
|
|
|
void SideBar::onAnimationFinished()
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
|
|
this->setFixedHeight(QWIDGETSIZE_MAX);
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
}
|
|
|
|
|
|
} // namespace SituationMap
|