33#include <QStyleOption>
34#include <QApplication>
42#define MIMETYPE QSL("application/falkon.tabbar.tab")
56 if (!m_metrics.isEmpty()) {
82 QHash<int, int> m_metrics;
90 , m_tabWidget(tabWidget)
91 , m_hideTabBarWithOneTab(false)
92 , m_showCloseOnInactive(0)
95 , m_forceHidden(false)
97 setObjectName(
QSL(
"tabbar"));
98 setElideMode(Qt::ElideRight);
99 setFocusPolicy(Qt::NoFocus);
100 setTabsClosable(
false);
101 setMouseTracking(
true);
102 setDocumentMode(
true);
103 setAcceptDrops(
true);
110 setUsesScrollButtons(
true);
111 setCloseButtonsToolTip(BrowserWindow::tr(
"Close Tab"));
114 tabMetrics()->init();
116 if (
mApp->isPrivate()) {
117 auto* privateBrowsing =
new QLabel(
this);
118 privateBrowsing->setObjectName(
QSL(
"private-browsing-icon"));
120 privateBrowsing->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
121 privateBrowsing->setFixedWidth(30);
122 addCornerWidget(privateBrowsing, Qt::TopLeftCorner);
130 m_hideTabBarWithOneTab = settings.
value(
QSL(
"hideTabsWithOneTab"),
false).toBool();
131 bool activateLastTab = settings.
value(
QSL(
"ActivateLastTabWhenClosingActual"),
false).toBool();
132 m_showCloseOnInactive = settings.
value(
QSL(
"showCloseOnInactiveTabs"), 0).toInt(
nullptr);
149 ComboTabBar::setVisible(
false);
155 visible = !(
count() <= 1 && m_hideTabBarWithOneTab);
158 ComboTabBar::setVisible(visible);
163 m_forceHidden = hidden;
167void TabBar::overflowChanged(
bool overflowed)
171 if (overflowed && m_showCloseOnInactive != 1) {
177QSize TabBar::tabSizeHint(
int index,
bool fast)
const
179 if (!m_window->isVisible()) {
182 return QSize(-1, -1);
192 size.setWidth(index >=
pinnedTabsCount() ? minTabWidth : pinnedTabWidth);
196 auto* webTab = qobject_cast<WebTab*>(m_tabWidget->
widget(index));
197 auto* tabBar =
const_cast <TabBar*
>(
this);
200 size.setWidth(pinnedTabWidth);
205 if (availableWidth < 0) {
206 return QSize(-1, -1);
213 m_normalTabWidth = maxTabWidth;
214 size.setWidth(m_normalTabWidth);
220 int realTabWidth = maxWidthForTab;
221 bool adjustingActiveTab =
false;
223 if (realTabWidth < minActiveTabWidth) {
225 realTabWidth = minActiveTabWidth;
226 adjustingActiveTab =
true;
233 tabBar->setTabsClosable(
false);
236 if (m_showCloseOnInactive == 1) {
238 tabBar->setTabsClosable(
true);
243 m_normalTabWidth = maxWidthForTab;
247 if (adjustingActiveTab) {
248 m_activeTabWidth = (availableWidth - minActiveTabWidth
252 m_activeTabWidth = (availableWidth - maxWidthForTab *
normalTabsCount) + maxWidthForTab;
254 size.setWidth(m_activeTabWidth);
257 size.setWidth(m_normalTabWidth);
264 tabBar->setTabsClosable(
true);
268 tabBar->updatePinnedTabCloseButton(
i);
273 if (index ==
count() - 1) {
277 if (lastMainActiveTab && m_activeTabWidth > m_normalTabWidth) {
278 xForAddTabButton += m_activeTabWidth - m_normalTabWidth;
281 if (QApplication::layoutDirection() == Qt::RightToLeft) {
282 xForAddTabButton = width() - xForAddTabButton;
285 Q_EMIT tabBar->moveAddTabButton(xForAddTabButton);
295 return tabMetrics()->pinnedWidth() > 0 ? tabMetrics()->pinnedWidth() : 32;
298 return tabMetrics()->activeMinWidth();
301 return tabMetrics()->normalMinWidth();
304 return tabMetrics()->overflowedWidth();
307 return tabMetrics()->normalMaxWidth();
319WebTab* TabBar::webTab(
int index)
const
324 return qobject_cast<WebTab*>(m_tabWidget->
widget(index));
327void TabBar::showCloseButton(
int index)
329 if (!validIndex(index)) {
333 auto* webTab = qobject_cast<WebTab*>(m_tabWidget->
widget(index));
336 if (button || (webTab && webTab->
isPinned())) {
343void TabBar::contextMenuEvent(QContextMenuEvent* event)
354 const QPoint pos =
event->globalPos();
355 QPoint p(pos.x(), pos.y() + 1);
359void TabBar::hideCloseButton(
int index)
371 button->deleteLater();
374void TabBar::updatePinnedTabCloseButton(
int index)
376 if (!validIndex(index)) {
380 auto* webTab = qobject_cast<WebTab*>(m_tabWidget->
widget(index));
383 bool pinned = webTab && webTab->
isPinned();
395 showCloseButton(index);
400void TabBar::closeTabFromButton()
402 QWidget* button = qobject_cast<QWidget*>(sender());
413 if (tabToClose != -1) {
418void TabBar::currentTabChanged(
int index)
420 if (!validIndex(index)) {
425 if (m_dragStartPosition.isNull() && !m_isRestoring) {
426 showCloseButton(index);
428 hideCloseButton(m_lastTab->tabIndex());
430 QTimer::singleShot(100,
this, [
this]() {
ensureVisible(); });
433 m_lastTab = webTab(index);
446 tabText.replace(QLatin1Char(
'&'), QLatin1String(
"&&"));
448 if (
WebTab* tab = webTab(index)) {
449 if (tab->isPinned()) {
458void TabBar::tabInserted(
int index)
463 if (tabMetrics()->pinnedWidth() == -1) {
464 QTimer::singleShot(0,
this, [
this]() {
465 if (tabMetrics()->pinnedWidth() != -1) {
469 if (w && w->parentWidget()) {
470 const QRect wg = w->parentWidget()->geometry();
471 const QRect wr = QStyle::visualRect(layoutDirection(), wg, w->geometry());
472 tabMetrics()->setPinnedWidth(
iconButtonSize().width() + wr.x() * 2);
481void TabBar::tabRemoved(
int index)
491 if (QApplication::layoutDirection() == Qt::RightToLeft)
492 xForAddTabButton = width() - xForAddTabButton;
497void TabBar::mouseDoubleClickEvent(QMouseEvent* event)
508 ComboTabBar::mouseDoubleClickEvent(
event);
511void TabBar::mousePressEvent(QMouseEvent* event)
513 ComboTabBar::mousePressEvent(
event);
520 m_dragStartPosition =
event->position().toPoint();
522 m_dragStartPosition = QPoint();
526void TabBar::mouseMoveEvent(QMouseEvent* event)
528 ComboTabBar::mouseMoveEvent(
event);
534 if (
count() == 1 &&
mApp->windowCount() == 1) {
538 if (!m_dragStartPosition.isNull()) {
540 const int eventY =
event->position().toPoint().y();
542 offset = qAbs(eventY);
543 }
else if (eventY > height()) {
544 offset = eventY - height();
546 if (offset > QApplication::startDragDistance() * 3) {
547 const QPoint global = mapToGlobal(m_dragStartPosition);
548 QWidget *w = QApplication::widgetAt(global);
550 QMouseEvent mouse(QEvent::MouseButtonRelease,
event->position(), w->mapFromGlobal(global), Qt::LeftButton, Qt::LeftButton,
event->modifiers());
551 QApplication::sendEvent(w, &mouse);
553 auto *drag =
new QDrag(
this);
554 auto *mime =
new QMimeData;
555 mime->setData(
MIMETYPE, QByteArray());
556 drag->setMimeData(mime);
558 if (drag->exec() == Qt::IgnoreAction) {
566void TabBar::mouseReleaseEvent(QMouseEvent* event)
568 ComboTabBar::mouseReleaseEvent(
event);
570 m_dragStartPosition = QPoint();
576 if (!rect().contains(
event->position().toPoint())) {
577 ComboTabBar::mouseReleaseEvent(
event);
581 if (
event->button() == Qt::MiddleButton) {
611static TabDropAction tabDropAction(
const QPoint &pos,
const QRect &tabRect,
bool allowSelect)
613 if (!tabRect.contains(pos)) {
617 const QPoint c = tabRect.center();
618 const QSize csize = QSize(tabRect.width() * 0.7, tabRect.height() * 0.7);
619 const QRect center(c.x() - csize.width() / 2, c.y() - csize.height() / 2, csize.width(), csize.height());
621 if (allowSelect && center.contains(pos)) {
623 }
else if (pos.x() < c.x()) {
630void TabBar::dragEnterEvent(QDragEnterEvent* event)
632 const QMimeData* mime =
event->mimeData();
634 if (mime->hasText() || mime->hasUrls() || (mime->hasFormat(
MIMETYPE) &&
event->source())) {
635 event->acceptProposedAction();
639 ComboTabBar::dragEnterEvent(
event);
642void TabBar::dragMoveEvent(QDragMoveEvent *event)
644 const int index =
tabAt(
event->position().toPoint());
645 const QMimeData* mime =
event->mimeData();
648 ComboTabBar::dragMoveEvent(
event);
652 switch (tabDropAction(
event->position().toPoint(),
tabRect(index), !mime->hasFormat(
MIMETYPE))) {
665void TabBar::dragLeaveEvent(QDragLeaveEvent *event)
669 ComboTabBar::dragLeaveEvent(
event);
672void TabBar::dropEvent(QDropEvent* event)
676 const QMimeData* mime =
event->mimeData();
678 if (!mime->hasText() && !mime->hasUrls() && !mime->hasFormat(
MIMETYPE)) {
679 ComboTabBar::dropEvent(
event);
683 event->acceptProposedAction();
685 auto *sourceTabBar = qobject_cast<TabBar*>(
event->source());
687 int index =
tabAt(
event->position().toPoint());
689 if (mime->hasUrls()) {
690 const auto urls = mime->urls();
691 for (
const QUrl &url : urls) {
694 }
else if (mime->hasText()) {
696 }
else if (mime->hasFormat(
MIMETYPE) && sourceTabBar) {
697 WebTab *tab = sourceTabBar->webTab();
699 sourceTabBar->m_tabWidget->detachTab(tab);
708 if (mime->hasUrls()) {
709 req = mime->urls().at(0);
710 }
else if (mime->hasText()) {
711 req =
mApp->searchEnginesManager()->searchResult(mime->text());
718 const int newIndex = action ==
PrependTab ? index : index + 1;
721 }
else if (mime->hasFormat(
MIMETYPE) && sourceTabBar) {
722 WebTab *tab = sourceTabBar->webTab();
724 if (sourceTabBar ==
this) {
727 sourceTabBar->m_tabWidget->detachTab(tab);
739 m_isRestoring = restoring;
744 return m_isRestoring;
int tabAt(const QPoint &pos) const
QTabBar::ButtonPosition iconButtonPosition() const
bool isDragInProgress() const
int normalTabsCount() const
QString tabText(int index) const
void clearDropIndicator()
int mainTabBarCurrentIndex() const
void showDropIndicator(int index, DropIndicatorPosition position)
QPixmap tabPixmap(int index) const
QWidget * tabButton(int index, QTabBar::ButtonPosition position) const
QRect tabRect(int index) const
QSize iconButtonSize() const
void ensureVisible(int index=-1, int xmargin=-1)
QTabBar::ButtonPosition closeButtonPosition() const
int pinnedTabsCount() const
void setTabButton(int index, QTabBar::ButtonPosition position, QWidget *widget)
void currentChanged(int index)
void setSelectionBehaviorOnRemove(QTabBar::SelectionBehavior behavior)
int pinTabBarWidth() const
int cornerWidth(Qt::Corner corner) const
void overFlowChanged(bool overFlow)
void setTabToolTip(int index, const QString &tip)
virtual QSize tabSizeHint(int index, bool fast=false) const
bool event(QEvent *event) override
void setTabText(int index, const QString &text)
void wheelEvent(QWheelEvent *event) override
int mainTabBarWidth() const
void setTabsClosable(bool closable)
bool emptyArea(const QPoint &pos) const
bool tabsClosable() const
void insertCloseButton(int index)
static QIcon privateBrowsingIcon()
void beginGroup(const QString &prefix)
QVariant value(const QString &key, const QVariant &defaultValue=QVariant())
void wheelEvent(QWheelEvent *event) override
void setTabText(int index, const QString &text)
void setVisible(bool visible) override
void setForceHidden(bool hidden)
void moveAddTabButton(int posX)
void setIsRestoring(bool restoring)
TabWidget * tabWidget() const
void setNormalMinWidth(int value)
void setActiveMinWidth(int value)
void setNormalMaxWidth(int value)
void setOverflowedWidth(int value)
int activeMinWidth() const
void setPinnedWidth(int value)
int overflowedWidth() const
int normalMaxWidth() const
int normalMinWidth() const
void setPinned(bool state)
void load(const LoadRequest &request)
int value(const QColor &c)