mirror of
https://invent.kde.org/network/falkon.git
synced 2024-12-20 02:36: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 "tabicon.h"
|
||||
#include "iconprovider.h"
|
||||
|
||||
#include <QTabBar>
|
||||
#include <QPainter>
|
||||
#include <QPushButton>
|
||||
#include <QApplication>
|
||||
|
||||
TabTreeDelegate::TabTreeDelegate(TabTreeView *view)
|
||||
: QStyledItemDelegate()
|
||||
@ -36,6 +38,19 @@ TabTreeDelegate::TabTreeDelegate(TabTreeView *view)
|
||||
connect(m_loadingAnimator, &LoadingAnimator::updateIndex, this, [this](const QModelIndex &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)
|
||||
@ -70,7 +85,9 @@ QRect TabTreeDelegate::closeButtonRect(const QModelIndex &index) const
|
||||
{
|
||||
const QRect rect = m_view->visualRect(index);
|
||||
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
|
||||
@ -91,7 +108,7 @@ void TabTreeDelegate::paint(QPainter *painter, const QStyleOptionViewItem &optio
|
||||
const int center = height / 2 + opt.rect.top();
|
||||
|
||||
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 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
|
||||
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);
|
||||
QRect closeRect(pos, closeSize);
|
||||
painter->drawPixmap(closeRect, IconProvider::standardIcon(QStyle::SP_DialogCloseButton).pixmap(closeSize, iconMode));
|
||||
o.rect = QRect(pos, closeSize);
|
||||
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
|
||||
|
@ -19,6 +19,8 @@
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
class QPushButton;
|
||||
|
||||
class TabTreeView;
|
||||
class LoadingAnimator;
|
||||
|
||||
@ -37,6 +39,7 @@ public:
|
||||
private:
|
||||
TabTreeView *m_view;
|
||||
LoadingAnimator *m_loadingAnimator;
|
||||
QPushButton *m_closeButton;
|
||||
int m_padding;
|
||||
int m_indentation;
|
||||
};
|
||||
|
@ -46,6 +46,9 @@ TabTreeView::TabTreeView(QWidget *parent)
|
||||
|
||||
// Move scrollbar to the left
|
||||
setLayoutDirection(isRightToLeft() ? Qt::LeftToRight : Qt::RightToLeft);
|
||||
|
||||
// Enable hover to force redrawing close button
|
||||
viewport()->setAttribute(Qt::WA_Hover);
|
||||
}
|
||||
|
||||
bool TabTreeView::areTabsInOrder() const
|
||||
@ -109,6 +112,7 @@ bool TabTreeView::viewportEvent(QEvent *event)
|
||||
case QEvent::MouseButtonPress: {
|
||||
QMouseEvent *me = static_cast<QMouseEvent*>(event);
|
||||
const QModelIndex index = indexAt(me->pos());
|
||||
update(index);
|
||||
WebTab *tab = index.data(TabModel::WebTabRole).value<WebTab*>();
|
||||
if (me->buttons() == Qt::MiddleButton && tab) {
|
||||
tab->closeTab();
|
||||
@ -131,6 +135,19 @@ bool TabTreeView::viewportEvent(QEvent *event)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -140,6 +157,7 @@ bool TabTreeView::viewportEvent(QEvent *event)
|
||||
break;
|
||||
}
|
||||
const QModelIndex index = indexAt(me->pos());
|
||||
update(index);
|
||||
if (m_pressedIndex != index) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,7 @@ private:
|
||||
|
||||
TabTreeDelegate *m_delegate;
|
||||
DelegateButton m_pressedButton = NoButton;
|
||||
QModelIndex m_pressedIndex;
|
||||
QPersistentModelIndex m_pressedIndex;
|
||||
QPersistentModelIndex m_hoveredIndex;
|
||||
bool m_tabsInOrder = false;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user