mirror of
https://invent.kde.org/network/falkon.git
synced 2024-12-20 18:56:34 +01:00
TabTreeView: Draw real tabbar close button and make it stylable
This commit is contained in:
parent
6985a8567a
commit
ad387fe712
@ -21,9 +21,11 @@
|
|||||||
|
|
||||||
#include "tabmodel.h"
|
#include "tabmodel.h"
|
||||||
#include "tabicon.h"
|
#include "tabicon.h"
|
||||||
#include "iconprovider.h"
|
|
||||||
|
|
||||||
|
#include <QTabBar>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
TabTreeDelegate::TabTreeDelegate(TabTreeView *view)
|
TabTreeDelegate::TabTreeDelegate(TabTreeView *view)
|
||||||
: QStyledItemDelegate()
|
: QStyledItemDelegate()
|
||||||
@ -36,6 +38,19 @@ TabTreeDelegate::TabTreeDelegate(TabTreeView *view)
|
|||||||
connect(m_loadingAnimator, &LoadingAnimator::updateIndex, this, [this](const QModelIndex &index) {
|
connect(m_loadingAnimator, &LoadingAnimator::updateIndex, this, [this](const QModelIndex &index) {
|
||||||
m_view->update(index);
|
m_view->update(index);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Needed to make it stylable the same way as real tabbar close button
|
||||||
|
QTabBar *tabBar = new QTabBar(m_view);
|
||||||
|
tabBar->setObjectName(QSL("treeview_tabbar"));
|
||||||
|
tabBar->lower();
|
||||||
|
|
||||||
|
m_closeButton = new QPushButton(tabBar);
|
||||||
|
m_closeButton->setObjectName(QSL("treeview_close_button"));
|
||||||
|
m_closeButton->lower();
|
||||||
|
|
||||||
|
int width = m_closeButton->style()->pixelMetric(QStyle::PM_TabCloseIndicatorWidth, nullptr, m_closeButton);
|
||||||
|
int height = m_closeButton->style()->pixelMetric(QStyle::PM_TabCloseIndicatorHeight, nullptr, m_closeButton);
|
||||||
|
m_closeButton->resize(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int indexDepth(QModelIndex index)
|
static int indexDepth(QModelIndex index)
|
||||||
@ -70,7 +85,9 @@ QRect TabTreeDelegate::closeButtonRect(const QModelIndex &index) const
|
|||||||
{
|
{
|
||||||
const QRect rect = m_view->visualRect(index);
|
const QRect rect = m_view->visualRect(index);
|
||||||
const int center = rect.height() / 2 + rect.top();
|
const int center = rect.height() / 2 + rect.top();
|
||||||
return QRect(rect.right() - m_padding - 16, center - 16 / 2, 16, 16);
|
QSize size = m_closeButton->size();
|
||||||
|
size.setHeight(qMin(rect.height() - m_padding, size.height()));
|
||||||
|
return QRect(QPoint(rect.right() - m_padding - size.width(), center - size.height() / 2), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabTreeDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
void TabTreeDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||||
@ -91,7 +108,7 @@ void TabTreeDelegate::paint(QPainter *painter, const QStyleOptionViewItem &optio
|
|||||||
const int center = height / 2 + opt.rect.top();
|
const int center = height / 2 + opt.rect.top();
|
||||||
|
|
||||||
int leftPosition = opt.rect.left() + m_indentation + m_indentation * depth + m_padding;
|
int leftPosition = opt.rect.left() + m_indentation + m_indentation * depth + m_padding;
|
||||||
int rightPosition = opt.rect.right() - m_padding * 2 - 16; // always reserve close button size
|
int rightPosition = opt.rect.right() - m_padding * 2 - m_closeButton->size().width();
|
||||||
|
|
||||||
const QIcon::Mode iconMode = opt.state & QStyle::State_Selected ? QIcon::Selected : QIcon::Normal;
|
const QIcon::Mode iconMode = opt.state & QStyle::State_Selected ? QIcon::Selected : QIcon::Normal;
|
||||||
const QPalette::ColorRole colorRole = opt.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text;
|
const QPalette::ColorRole colorRole = opt.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text;
|
||||||
@ -136,10 +153,20 @@ void TabTreeDelegate::paint(QPainter *painter, const QStyleOptionViewItem &optio
|
|||||||
|
|
||||||
// Draw close button
|
// Draw close button
|
||||||
if (opt.state.testFlag(QStyle::State_MouseOver) || opt.state.testFlag(QStyle::State_Selected)) {
|
if (opt.state.testFlag(QStyle::State_MouseOver) || opt.state.testFlag(QStyle::State_Selected)) {
|
||||||
QSize closeSize(16, 16);
|
QStyleOptionButton o;
|
||||||
|
o.init(m_closeButton);
|
||||||
|
|
||||||
|
const bool hovered = closeButtonRect(index).contains(m_view->viewport()->mapFromGlobal(QCursor::pos()));
|
||||||
|
const bool pressed = hovered && QApplication::mouseButtons() == Qt::LeftButton;
|
||||||
|
|
||||||
|
QSize closeSize = QSize(o.rect.size().width(), qMin(height - m_padding, o.rect.size().height()));
|
||||||
QPoint pos(opt.rect.right() - m_padding - closeSize.width(), center - closeSize.height() / 2);
|
QPoint pos(opt.rect.right() - m_padding - closeSize.width(), center - closeSize.height() / 2);
|
||||||
QRect closeRect(pos, closeSize);
|
o.rect = QRect(pos, closeSize);
|
||||||
painter->drawPixmap(closeRect, IconProvider::standardIcon(QStyle::SP_DialogCloseButton).pixmap(closeSize, iconMode));
|
o.state |= QStyle::State_AutoRaise | QStyle::State_Enabled | QStyle::State_Selected;
|
||||||
|
o.state.setFlag(QStyle::State_Raised, hovered && !pressed);
|
||||||
|
o.state.setFlag(QStyle::State_Sunken, pressed);
|
||||||
|
o.state.setFlag(QStyle::State_MouseOver, hovered);
|
||||||
|
style->drawPrimitive(QStyle::PE_IndicatorTabClose, &o, painter, m_closeButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw audio icon
|
// Draw audio icon
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
#include <QStyledItemDelegate>
|
#include <QStyledItemDelegate>
|
||||||
|
|
||||||
|
class QPushButton;
|
||||||
|
|
||||||
class TabTreeView;
|
class TabTreeView;
|
||||||
class LoadingAnimator;
|
class LoadingAnimator;
|
||||||
|
|
||||||
@ -37,6 +39,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
TabTreeView *m_view;
|
TabTreeView *m_view;
|
||||||
LoadingAnimator *m_loadingAnimator;
|
LoadingAnimator *m_loadingAnimator;
|
||||||
|
QPushButton *m_closeButton;
|
||||||
int m_padding;
|
int m_padding;
|
||||||
int m_indentation;
|
int m_indentation;
|
||||||
};
|
};
|
||||||
|
@ -46,6 +46,9 @@ TabTreeView::TabTreeView(QWidget *parent)
|
|||||||
|
|
||||||
// Move scrollbar to the left
|
// Move scrollbar to the left
|
||||||
setLayoutDirection(isRightToLeft() ? Qt::LeftToRight : Qt::RightToLeft);
|
setLayoutDirection(isRightToLeft() ? Qt::LeftToRight : Qt::RightToLeft);
|
||||||
|
|
||||||
|
// Enable hover to force redrawing close button
|
||||||
|
viewport()->setAttribute(Qt::WA_Hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TabTreeView::areTabsInOrder() const
|
bool TabTreeView::areTabsInOrder() const
|
||||||
@ -109,6 +112,7 @@ bool TabTreeView::viewportEvent(QEvent *event)
|
|||||||
case QEvent::MouseButtonPress: {
|
case QEvent::MouseButtonPress: {
|
||||||
QMouseEvent *me = static_cast<QMouseEvent*>(event);
|
QMouseEvent *me = static_cast<QMouseEvent*>(event);
|
||||||
const QModelIndex index = indexAt(me->pos());
|
const QModelIndex index = indexAt(me->pos());
|
||||||
|
update(index);
|
||||||
WebTab *tab = index.data(TabModel::WebTabRole).value<WebTab*>();
|
WebTab *tab = index.data(TabModel::WebTabRole).value<WebTab*>();
|
||||||
if (me->buttons() == Qt::MiddleButton && tab) {
|
if (me->buttons() == Qt::MiddleButton && tab) {
|
||||||
tab->closeTab();
|
tab->closeTab();
|
||||||
@ -131,6 +135,19 @@ bool TabTreeView::viewportEvent(QEvent *event)
|
|||||||
tab->makeCurrentTab();
|
tab->makeCurrentTab();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (m_pressedButton == CloseButton) {
|
||||||
|
me->accept();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case QEvent::MouseMove: {
|
||||||
|
QMouseEvent *me = static_cast<QMouseEvent*>(event);
|
||||||
|
if (m_pressedButton == CloseButton) {
|
||||||
|
me->accept();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,6 +157,7 @@ bool TabTreeView::viewportEvent(QEvent *event)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const QModelIndex index = indexAt(me->pos());
|
const QModelIndex index = indexAt(me->pos());
|
||||||
|
update(index);
|
||||||
if (m_pressedIndex != index) {
|
if (m_pressedIndex != index) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -158,6 +176,20 @@ bool TabTreeView::viewportEvent(QEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (m_pressedButton == CloseButton) {
|
||||||
|
me->accept();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case QEvent::HoverEnter:
|
||||||
|
case QEvent::HoverLeave:
|
||||||
|
case QEvent::HoverMove: {
|
||||||
|
QHoverEvent *he = static_cast<QHoverEvent*>(event);
|
||||||
|
update(m_hoveredIndex);
|
||||||
|
m_hoveredIndex = indexAt(he->pos());
|
||||||
|
update(m_hoveredIndex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ private:
|
|||||||
|
|
||||||
TabTreeDelegate *m_delegate;
|
TabTreeDelegate *m_delegate;
|
||||||
DelegateButton m_pressedButton = NoButton;
|
DelegateButton m_pressedButton = NoButton;
|
||||||
QModelIndex m_pressedIndex;
|
QPersistentModelIndex m_pressedIndex;
|
||||||
|
QPersistentModelIndex m_hoveredIndex;
|
||||||
bool m_tabsInOrder = false;
|
bool m_tabsInOrder = false;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user