/** * @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 #include #include #include #include #include #include #include #include #include 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 m_sideBarAniOn; QSharedPointer 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(new QPropertyAnimation(this, "pos")); connect(d->m_sideBarAniOn.data(), &QPropertyAnimation::finished, this, &SideBar::onAnimationOnFinished); d->m_sideBarAniOff = QSharedPointer(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