From a4838a41ac3ecca6d66d44fbbc15116fa0b540f4 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 5 Nov 2018 12:00:56 +0100 Subject: [PATCH] Added ElidingLabel to support text eliding for dock area tabs, removed debug output --- src/DockAreaTabBar.cpp | 22 +++- src/DockAreaTitleBar.cpp | 21 +++- src/DockAreaWidget.cpp | 4 - src/DockContainerWidget.cpp | 1 - src/DockWidgetTab.cpp | 12 ++- src/ElidingLabel.cpp | 198 ++++++++++++++++++++++++++++++++++ src/ElidingLabel.h | 97 +++++++++++++++++ src/FloatingDockContainer.cpp | 10 +- src/FloatingDockContainer.h | 2 + src/src.pro | 6 +- 10 files changed, 348 insertions(+), 25 deletions(-) create mode 100644 src/ElidingLabel.cpp create mode 100644 src/ElidingLabel.h diff --git a/src/DockAreaTabBar.cpp b/src/DockAreaTabBar.cpp index 2c0d40c..262eeb4 100644 --- a/src/DockAreaTabBar.cpp +++ b/src/DockAreaTabBar.cpp @@ -1,3 +1,22 @@ +/******************************************************************************* +** Qt Advanced Docking System +** Copyright (C) 2017 Uwe Kindler +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License as published by the Free Software Foundation; either +** version 2.1 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; If not, see . +******************************************************************************/ + + //============================================================================ /// \file DockAreaTabBar.cpp /// \author Uwe Kindler @@ -24,7 +43,6 @@ #include "DockWidget.h" #include "DockWidgetTab.h" -#include namespace ads { @@ -186,8 +204,6 @@ void CDockAreaTabBar::mouseMoveEvent(QMouseEvent* ev) return; } - /*int DragDistanceY = qAbs(d->DragStartMousePos.y() - ev->pos().y()); - int MinDragDistanceY = this->height() / 2;*/ int DragDistance = (d->DragStartMousePos - ev->pos()).manhattanLength(); if (DragDistance >= CDockManager::startDragDistance()) { diff --git a/src/DockAreaTitleBar.cpp b/src/DockAreaTitleBar.cpp index ace6fdd..fc5b70a 100644 --- a/src/DockAreaTitleBar.cpp +++ b/src/DockAreaTitleBar.cpp @@ -1,3 +1,22 @@ +/******************************************************************************* +** Qt Advanced Docking System +** Copyright (C) 2017 Uwe Kindler +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License as published by the Free Software Foundation; either +** version 2.1 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; If not, see . +******************************************************************************/ + + //============================================================================ /// \file DockAreaTitleBar.cpp /// \author Uwe Kindler @@ -29,7 +48,6 @@ #include "DockWidgetTab.h" #include "DockAreaTabBar.h" -#include namespace ads { @@ -226,7 +244,6 @@ void CDockAreaTitleBar::onCloseButtonClicked() //============================================================================ void CDockAreaTitleBar::onUndockButtonClicked() { - std::cout << "CDockAreaTitleBar::onUndockButtonClicked" << std::endl; d->TabBar->makeAreaFloating(mapFromGlobal(QCursor::pos())); } diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index ead90dc..14c40e7 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -54,8 +54,6 @@ #include "DockSplitter.h" #include "DockAreaTitleBar.h" -#include - namespace ads { @@ -392,7 +390,6 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget, void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget) { qDebug() << "CDockAreaWidget::removeDockWidget"; - std::cout << "CDockAreaWidget::removeDockWidget" << std::endl; auto NextOpenDockWidget = nextOpenDockWidget(DockWidget); d->ContentsLayout->removeWidget(DockWidget); @@ -434,7 +431,6 @@ void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget) //============================================================================ void CDockAreaWidget::hideAreaWithNoVisibleContent() { - std::cout << "CDockAreaWidget::hideAreaWithNoVisibleContent()" << std::endl; this->toggleView(false); // Hide empty parent splitter diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 4dd1dfa..004d963 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -49,7 +49,6 @@ #include "DockSplitter.h" #include -#include namespace ads diff --git a/src/DockWidgetTab.cpp b/src/DockWidgetTab.cpp index 74f1f63..0a89f90 100644 --- a/src/DockWidgetTab.cpp +++ b/src/DockWidgetTab.cpp @@ -28,6 +28,7 @@ //============================================================================ // INCLUDES //============================================================================ +#include #include "DockWidgetTab.h" #include @@ -45,8 +46,6 @@ #include "DockOverlay.h" #include "DockManager.h" -#include - namespace ads { /** @@ -60,6 +59,7 @@ enum eDragState DraggingFloatingWidget//!< DraggingFloatingWidget }; +using tTabLabel = CElidingLabel; /** * Private data class of CDockWidgetTab class (pimpl) @@ -69,7 +69,7 @@ struct DockWidgetTabPrivate CDockWidgetTab* _this; CDockWidget* DockWidget; QLabel* IconLabel; - QLabel* TitleLabel; + tTabLabel* TitleLabel; QPoint DragStartMousePosition; bool IsActiveTab = false; CDockAreaWidget* DockArea = nullptr; @@ -137,15 +137,17 @@ void DockWidgetTabPrivate::createLayout() IconLabel = new QLabel(); IconLabel->setAlignment(Qt::AlignVCenter); + IconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); l->addWidget(IconLabel, Qt::AlignVCenter); - TitleLabel = new QLabel(); + TitleLabel = new tTabLabel(); + TitleLabel->setElideMode(Qt::ElideRight); + TitleLabel->setText(DockWidget->windowTitle()); TitleLabel->setObjectName("dockWidgetTabLabel"); l->addWidget(TitleLabel, 1); IconLabel->setVisible(false); TitleLabel->setVisible(true); - TitleLabel->setText(DockWidget->windowTitle()); } //============================================================================ diff --git a/src/ElidingLabel.cpp b/src/ElidingLabel.cpp new file mode 100644 index 0000000..9b6352c --- /dev/null +++ b/src/ElidingLabel.cpp @@ -0,0 +1,198 @@ +/******************************************************************************* +** Qt Advanced Docking System +** Copyright (C) 2017 Uwe Kindler +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License as published by the Free Software Foundation; either +** version 2.1 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; If not, see . +******************************************************************************/ + + +//============================================================================ +/// \file ElidingLabel.cpp +/// \author Uwe Kindler +/// \date 05.11.2018 +/// \brief Implementation of CElidingLabel +//============================================================================ + +//============================================================================ +// INCLUDES +//============================================================================ +#include +#include + + +namespace ads +{ +/** + * Private data of public CClickableLabel + */ +struct ElidingLabelPrivate +{ + CElidingLabel* _this; + Qt::TextElideMode ElideMode = Qt::ElideNone; + QString Text; + + ElidingLabelPrivate(CElidingLabel* _public) : _this(_public) {} + + void elideText(int Width); + + /** + * Convenience function to check if the + */ + bool isModeElideNone() const + { + return Qt::ElideNone == ElideMode; + } +}; + + +//============================================================================ +void ElidingLabelPrivate::elideText(int Width) +{ + if (isModeElideNone()) + { + return; + } + QFontMetrics fm = _this->fontMetrics(); + QString str = fm.elidedText(Text, ElideMode, Width - _this->margin() * 2 - _this->indent()); + if (str == "…") + { + str = Text.at(0); + } + _this->QLabel::setText(str); +} + + +//============================================================================ +CElidingLabel::CElidingLabel(QWidget* parent, Qt::WindowFlags f) + : QLabel(parent, f), + d(new ElidingLabelPrivate(this)) +{ + +} + + +//============================================================================ +CElidingLabel::CElidingLabel(const QString& text, QWidget* parent, Qt::WindowFlags f) + : QLabel(text, parent,f), + d(new ElidingLabelPrivate(this)) +{ + d->Text = text; + setToolTip(text); +} + + +//============================================================================ +CElidingLabel::~CElidingLabel() +{ + delete d; +} + + +//============================================================================ +Qt::TextElideMode CElidingLabel::elideMode() const +{ + return d->ElideMode; +} + + +//============================================================================ +void CElidingLabel::setElideMode(Qt::TextElideMode mode) +{ + d->ElideMode = mode; + d->elideText(size().width()); +} + + +//============================================================================ +void CElidingLabel::mouseReleaseEvent(QMouseEvent* event) +{ + if (event->button() != Qt::LeftButton) + { + return; + } + + emit clicked(); +} + + +//============================================================================ +void CElidingLabel::mouseDoubleClickEvent( QMouseEvent *ev ) +{ + Q_UNUSED(ev) + emit doubleClicked(); +} + + +//============================================================================ +void CElidingLabel::resizeEvent(QResizeEvent *event) +{ + if (!d->isModeElideNone()) + { + d->elideText(event->size().width()); + } + QLabel::resizeEvent(event); +} + + +//============================================================================ +QSize CElidingLabel::minimumSizeHint() const +{ + if (pixmap() != nullptr || d->isModeElideNone()) + { + return QLabel::minimumSizeHint(); + } + const QFontMetrics &fm = fontMetrics(); + QSize size(fm.width("…"), fm.height()); + return size; +} + + +//============================================================================ +QSize CElidingLabel::sizeHint() const +{ + if (pixmap() != nullptr || d->isModeElideNone()) + { + return QLabel::sizeHint(); + } + const QFontMetrics& fm = fontMetrics(); + QSize size(fm.width(d->Text), QLabel::sizeHint().height()); + return size; +} + + +//============================================================================ +void CElidingLabel::setText(const QString &text) +{ + if (d->isModeElideNone()) + { + Super::setText(text); + } + else + { + d->Text = text; + setToolTip( text ); + d->elideText(this->size().width()); + } +} + + +//============================================================================ +QString CElidingLabel::text() const +{ + return d->Text; +} +} // namespace QtLabb + +//--------------------------------------------------------------------------- +// EOF ClickableLabel.cpp diff --git a/src/ElidingLabel.h b/src/ElidingLabel.h new file mode 100644 index 0000000..75595bf --- /dev/null +++ b/src/ElidingLabel.h @@ -0,0 +1,97 @@ +#ifndef ElidingLabelH +#define ElidingLabelH +/******************************************************************************* +** Qt Advanced Docking System +** Copyright (C) 2017 Uwe Kindler +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License as published by the Free Software Foundation; either +** version 2.1 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public +** License along with this library; If not, see . +******************************************************************************/ + + +//============================================================================ +/// \file ElidingLabel.h +/// \author Uwe Kindler +/// \date 05.11.2018 +/// \brief Declaration of CElidingLabel +//============================================================================ + +//============================================================================ +// INCLUDES +//============================================================================ +#include + +namespace ads +{ +struct ElidingLabelPrivate; + +/** + * A QLabel that supports eliding text. + * Because the functions setText() and text() are no virtual functions setting + * and reading the text via a pointer to the base class QLabel does not work + * properly + */ +class CElidingLabel : public QLabel +{ + Q_OBJECT +private: + ElidingLabelPrivate* d; + friend class ElidingLabelPrivate; + +protected: + virtual void mouseReleaseEvent(QMouseEvent* event) override; + virtual void resizeEvent( QResizeEvent *event ) override; + virtual void mouseDoubleClickEvent( QMouseEvent *ev ) override; + +public: + using Super = QLabel; + + CElidingLabel(QWidget* parent = 0, Qt::WindowFlags f = 0); + CElidingLabel(const QString& text, QWidget* parent = 0, Qt::WindowFlags f = 0); + virtual ~CElidingLabel(); + + /** + * Returns the text elide mode. + * The default mode is ElideNone + */ + Qt::TextElideMode elideMode() const; + + /** + * Sets the text elide mode + */ + void setElideMode(Qt::TextElideMode mode); + + +public: // reimplements QLabel ---------------------------------------------- + virtual QSize minimumSizeHint() const override; + virtual QSize sizeHint() const override; + void setText(const QString &text); + QString text() const; + +signals: + /** + * This signal is emitted if the user clicks on the label (i.e. pressed + * down then released while the mouse cursor is inside the label) + */ + void clicked(); + + /** + * This signal is emitted if the user does a double click on the label + */ + void doubleClicked(); +}; //class CElidingLabel + +} // namespace QtLabb + +//--------------------------------------------------------------------------- +#endif // ElidingLabelH diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index 63de9e2..1c6ac56 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -44,7 +44,6 @@ #include "DockWidget.h" #include "DockOverlay.h" -#include namespace ads { @@ -334,8 +333,7 @@ void CFloatingDockContainer::closeEvent(QCloseEvent *event) //============================================================================ void CFloatingDockContainer::hideEvent(QHideEvent *event) { - std::cout << "CFloatingDockContainer hideEvent" << std::endl; - QWidget::hideEvent(event); + Super::hideEvent(event); for (auto DockArea : d->DockContainer->openedDockAreas()) { for (auto DockWidget : DockArea->openedDockWidgets()) @@ -349,8 +347,7 @@ void CFloatingDockContainer::hideEvent(QHideEvent *event) //============================================================================ void CFloatingDockContainer::showEvent(QShowEvent *event) { - std::cout << "CFloatingDockContainer showEvent" << std::endl; - QWidget::showEvent(event); + Super::showEvent(event); /*for (auto DockArea : d->DockContainer->openedDockAreas()) { for (auto DockWidget : DockArea->openedDockWidgets()) @@ -507,8 +504,6 @@ void CFloatingDockContainer::updateWindowTitle() void CFloatingDockContainer::onDockAreaCurrentChanged(int Index) { Q_UNUSED(Index); - std::cout << "CFloatingDockContainer::onDockAreaCurrentChanged " - << Index << std::endl; this->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle()); } @@ -521,7 +516,6 @@ bool CFloatingDockContainer::restoreState(QXmlStreamReader& Stream, bool Testing return false; } - std::cout << "Dockarea count " << d->DockContainer->dockAreaCount() << std::endl; onDockAreasAddedOrRemoved(); return true; } diff --git a/src/FloatingDockContainer.h b/src/FloatingDockContainer.h index f0affc7..49c9f0d 100644 --- a/src/FloatingDockContainer.h +++ b/src/FloatingDockContainer.h @@ -113,6 +113,8 @@ protected: // reimplements QWidget virtual bool eventFilter(QObject *watched, QEvent *event) override; public: + using Super = QWidget; + /** * Create empty flatingb widget - required for restore state */ diff --git a/src/src.pro b/src/src.pro index e29a73d..c8e7eaf 100644 --- a/src/src.pro +++ b/src/src.pro @@ -41,7 +41,8 @@ HEADERS += \ FloatingDockContainer.h \ DockOverlay.h \ DockSplitter.h \ - DockAreaTitleBar.h + DockAreaTitleBar.h \ + ElidingLabel.h @@ -56,4 +57,5 @@ SOURCES += \ FloatingDockContainer.cpp \ DockOverlay.cpp \ DockSplitter.cpp \ - DockAreaTitleBar.cpp + DockAreaTitleBar.cpp \ + ElidingLabel.cpp