File indexing completed on 2024-04-28 05:50:53
0001 /* 0002 SPDX-FileCopyrightText: 2018 Tomaz Canabrava <tcanabrava@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "DetachableTabBar.h" 0008 #include "KonsoleSettings.h" 0009 #include "widgets/ViewContainer.h" 0010 0011 #include <QApplication> 0012 #include <QMimeData> 0013 #include <QMouseEvent> 0014 0015 #include <KAcceleratorManager> 0016 0017 #include <QColor> 0018 #include <QPainter> 0019 0020 namespace Konsole 0021 { 0022 DetachableTabBar::DetachableTabBar(QWidget *parent) 0023 : QTabBar(parent) 0024 , dragType(DragType::NONE) 0025 , _originalCursor(cursor()) 0026 , tabId(-1) 0027 { 0028 setAcceptDrops(true); 0029 setElideMode(Qt::TextElideMode::ElideLeft); 0030 KAcceleratorManager::setNoAccel(this); 0031 } 0032 0033 void DetachableTabBar::setColor(int idx, const QColor &color) 0034 { 0035 setTabData(idx, color); 0036 } 0037 0038 void DetachableTabBar::removeColor(int idx) 0039 { 0040 setTabData(idx, QVariant()); 0041 } 0042 0043 void DetachableTabBar::middleMouseButtonClickAt(const QPoint &pos) 0044 { 0045 tabId = tabAt(pos); 0046 0047 if (tabId != -1) { 0048 Q_EMIT closeTab(tabId); 0049 } 0050 } 0051 0052 void DetachableTabBar::mousePressEvent(QMouseEvent *event) 0053 { 0054 QTabBar::mousePressEvent(event); 0055 _containers = window()->findChildren<Konsole::TabbedViewContainer *>(); 0056 } 0057 0058 void DetachableTabBar::mouseMoveEvent(QMouseEvent *event) 0059 { 0060 QTabBar::mouseMoveEvent(event); 0061 auto widgetAtPos = qApp->topLevelAt(event->globalPosition().toPoint()); 0062 if (widgetAtPos != nullptr) { 0063 if (window() == widgetAtPos->window()) { 0064 if (dragType != DragType::NONE) { 0065 dragType = DragType::NONE; 0066 setCursor(_originalCursor); 0067 } 0068 } else { 0069 if (dragType != DragType::WINDOW) { 0070 dragType = DragType::WINDOW; 0071 setCursor(QCursor(Qt::DragMoveCursor)); 0072 } 0073 } 0074 } else if (!contentsRect().adjusted(-30, -30, 30, 30).contains(event->pos())) { 0075 // Don't let it detach the last tab. 0076 if (count() == 1) { 0077 return; 0078 } 0079 if (dragType != DragType::OUTSIDE) { 0080 dragType = DragType::OUTSIDE; 0081 setCursor(QCursor(Qt::DragCopyCursor)); 0082 } 0083 } 0084 } 0085 0086 void DetachableTabBar::mouseReleaseEvent(QMouseEvent *event) 0087 { 0088 QTabBar::mouseReleaseEvent(event); 0089 0090 switch (event->button()) { 0091 case Qt::MiddleButton: 0092 if (KonsoleSettings::closeTabOnMiddleMouseButton()) { 0093 middleMouseButtonClickAt(event->pos()); 0094 } 0095 0096 tabId = tabAt(event->pos()); 0097 if (tabId == -1) { 0098 Q_EMIT newTabRequest(); 0099 } 0100 break; 0101 case Qt::LeftButton: 0102 _containers = window()->findChildren<Konsole::TabbedViewContainer *>(); 0103 break; 0104 default: 0105 break; 0106 } 0107 0108 setCursor(_originalCursor); 0109 0110 if (contentsRect().adjusted(-30, -30, 30, 30).contains(event->pos())) { 0111 return; 0112 } 0113 0114 auto widgetAtPos = qApp->topLevelAt(event->globalPosition().toPoint()); 0115 if (widgetAtPos == nullptr) { 0116 if (count() != 1) { 0117 Q_EMIT detachTab(currentIndex()); 0118 } 0119 } else if (window() != widgetAtPos->window()) { 0120 if (_containers.size() == 1 || count() > 1) { 0121 Q_EMIT moveTabToWindow(currentIndex(), widgetAtPos); 0122 } 0123 } 0124 } 0125 0126 void DetachableTabBar::dragEnterEvent(QDragEnterEvent *event) 0127 { 0128 const auto dragId = QStringLiteral("konsole/terminal_display"); 0129 if (!event->mimeData()->hasFormat(dragId)) { 0130 return; 0131 } 0132 auto other_pid = event->mimeData()->data(dragId).toInt(); 0133 // don't accept the drop if it's another instance of konsole 0134 if (qApp->applicationPid() != other_pid) { 0135 return; 0136 } 0137 event->accept(); 0138 } 0139 0140 void DetachableTabBar::dragMoveEvent(QDragMoveEvent *event) 0141 { 0142 int tabIdx = tabAt(event->position().toPoint()); 0143 if (tabIdx != -1) { 0144 setCurrentIndex(tabIdx); 0145 } 0146 } 0147 0148 void DetachableTabBar::paintEvent(QPaintEvent *event) 0149 { 0150 QTabBar::paintEvent(event); 0151 if (!event->isAccepted()) { 0152 return; // Reduces repainting 0153 } 0154 0155 QPainter painter(this); 0156 painter.setPen(Qt::NoPen); 0157 0158 for (int tabIndex = 0; tabIndex < count(); tabIndex++) { 0159 const QVariant data = tabData(tabIndex); 0160 if (!data.isValid() || data.isNull()) { 0161 continue; 0162 } 0163 0164 QColor varColor = data.value<QColor>(); 0165 if (!varColor.isValid() || varColor.alpha() == 0) { 0166 continue; 0167 } 0168 0169 painter.setBrush(varColor); 0170 QRect tRect = tabRect(tabIndex); 0171 tRect.setTop(painter.fontMetrics().height() + 6); // Color bar top position consider a height the font and fixed spacing of 6px 0172 tRect.setHeight(4); 0173 tRect.setLeft(tRect.left() + 6); 0174 tRect.setWidth(tRect.width() - 6); 0175 painter.drawRect(tRect); 0176 } 0177 } 0178 0179 } 0180 0181 #include "moc_DetachableTabBar.cpp"