kde-extraapps/yakuake/app/tabbar.cpp
Ivailo Monev 05e4ee3725 generic: replace obsolete Qt::MidButton with Qt::MiddleButton
Signed-off-by: Ivailo Monev <xakepa10@laimg.moc>
2019-05-15 00:25:42 +00:00

1056 lines
31 KiB
C++

/*
Copyright (C) 2008-2009 by Eike Hein <hein@kde.org>
Copyright (C) 2009 by Juan Carlos Torres <carlosdgtorres@gmail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License or (at your option) version 3 or any later version
accepted by the membership of KDE e.V. (or its successor appro-
ved by the membership of KDE e.V.), which shall act as a proxy
defined in Section 14 of version 3 of the license.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
*/
#include "tabbar.h"
#include "mainwindow.h"
#include "skin.h"
#include "session.h"
#include "sessionstack.h"
#include "settings.h"
#include <KLineEdit>
#include <KMenu>
#include <KPushButton>
#include <KActionCollection>
#include <KGlobalSettings>
#include <KLocalizedString>
#include <QBitmap>
#include <QPainter>
#include <QtDBus/QtDBus>
#include <QToolButton>
#include <QtGui/qevent.h>
#include <QWhatsThis>
#include <QMimeData>
#include <QDrag>
#include <QLabel>
TabBar::TabBar(MainWindow* mainWindow) : QWidget(mainWindow)
{
QDBusConnection::sessionBus().registerObject("/yakuake/tabs", this, QDBusConnection::ExportScriptableSlots);
setWhatsThis(i18nc("@info:whatsthis",
"<title>Tab Bar</title>"
"<para>The tab bar allows you to switch between sessions. You can double-click a tab to edit its label.</para>"));
m_selectedSessionId = -1;
m_renamingSessionId = -1;
m_mousePressed = false;
m_mousePressedIndex = -1;
m_dropIndicator = 0;
m_mainWindow = mainWindow;
m_skin = mainWindow->skin();
connect(m_skin, SIGNAL(iconChanged()), this, SLOT(repaint()));
m_tabContextMenu = new KMenu(this);
connect(m_tabContextMenu, SIGNAL(hovered(QAction*)), this, SLOT(contextMenuActionHovered(QAction*)));
m_toggleKeyboardInputMenu = new KMenu(i18nc("@title:menu", "Disable Keyboard Input"), this);
m_toggleMonitorActivityMenu = new KMenu(i18nc("@title:menu", "Monitor for Activity"), this);
m_toggleMonitorSilenceMenu = new KMenu(i18nc("@title:menu", "Monitor for Silence"), this);
m_sessionMenu = new KMenu(this);
connect(m_sessionMenu, SIGNAL(aboutToShow()), this, SLOT(readySessionMenu()));
m_newTabButton = new QToolButton(this);
m_newTabButton->setFocusPolicy(Qt::NoFocus);
m_newTabButton->setMenu(m_sessionMenu);
m_newTabButton->setPopupMode(QToolButton::DelayedPopup);
m_newTabButton->setToolTip(i18nc("@info:tooltip", "New Session"));
m_newTabButton->setWhatsThis(i18nc("@info:whatsthis", "Adds a new session. Press and hold to select session type from menu."));
connect(m_newTabButton, SIGNAL(clicked()), this, SIGNAL(newTabRequested()));
m_closeTabButton = new KPushButton(this);
m_closeTabButton->setFocusPolicy(Qt::NoFocus);
m_closeTabButton->setToolTip(i18nc("@info:tooltip", "Close Session"));
m_closeTabButton->setWhatsThis(i18nc("@info:whatsthis", "Closes the active session."));
connect(m_closeTabButton, SIGNAL(clicked()), this, SLOT(closeTabButtonClicked()));
m_lineEdit = new KLineEdit(this);
m_lineEdit->setFrame(false);
m_lineEdit->setClearButtonShown(false);
m_lineEdit->setAlignment(Qt::AlignHCenter);
m_lineEdit->hide();
connect(m_lineEdit, SIGNAL(editingFinished()), m_lineEdit, SLOT(hide()));
connect(m_lineEdit, SIGNAL(returnPressed()), this, SLOT(interactiveRenameDone()));
setAcceptDrops(true);
}
TabBar::~TabBar()
{
}
void TabBar::applySkin()
{
resize(width(), m_skin->tabBarBackgroundImage().height());
m_newTabButton->setStyleSheet(m_skin->tabBarNewTabButtonStyleSheet());
m_closeTabButton->setStyleSheet(m_skin->tabBarCloseTabButtonStyleSheet());
m_newTabButton->move( m_skin->tabBarNewTabButtonPosition().x(), m_skin->tabBarNewTabButtonPosition().y());
m_closeTabButton->move(width() - m_skin->tabBarCloseTabButtonPosition().x(), m_skin->tabBarCloseTabButtonPosition().y());
repaint();
}
void TabBar::readyTabContextMenu()
{
if (m_tabContextMenu->isEmpty())
{
m_tabContextMenu->addAction(m_mainWindow->actionCollection()->action("split-left-right"));
m_tabContextMenu->addAction(m_mainWindow->actionCollection()->action("split-top-bottom"));
m_tabContextMenu->addSeparator();
m_tabContextMenu->addAction(m_mainWindow->actionCollection()->action("edit-profile"));
m_tabContextMenu->addAction(m_mainWindow->actionCollection()->action("rename-session"));
m_tabContextMenu->addAction(m_mainWindow->actionCollection()->action("toggle-session-prevent-closing"));
m_tabContextMenu->addMenu(m_toggleKeyboardInputMenu);
m_tabContextMenu->addMenu(m_toggleMonitorActivityMenu);
m_tabContextMenu->addMenu(m_toggleMonitorSilenceMenu);
m_tabContextMenu->addSeparator();
m_tabContextMenu->addAction(m_mainWindow->actionCollection()->action("move-session-left"));
m_tabContextMenu->addAction(m_mainWindow->actionCollection()->action("move-session-right"));
m_tabContextMenu->addSeparator();
m_tabContextMenu->addAction(m_mainWindow->actionCollection()->action("close-active-terminal"));
m_tabContextMenu->addAction(m_mainWindow->actionCollection()->action("close-session"));
}
}
void TabBar::readySessionMenu()
{
if (m_sessionMenu->isEmpty())
{
m_sessionMenu->addAction(m_mainWindow->actionCollection()->action("new-session"));
m_sessionMenu->addSeparator();
m_sessionMenu->addAction(m_mainWindow->actionCollection()->action("new-session-two-horizontal"));
m_sessionMenu->addAction(m_mainWindow->actionCollection()->action("new-session-two-vertical"));
m_sessionMenu->addAction(m_mainWindow->actionCollection()->action("new-session-quad"));
}
}
void TabBar::updateMoveActions(int index)
{
if (index == -1) return;
m_mainWindow->actionCollection()->action("move-session-left")->setEnabled(false);
m_mainWindow->actionCollection()->action("move-session-right")->setEnabled(false);
if (index != m_tabs.indexOf(m_tabs.first()))
m_mainWindow->actionCollection()->action("move-session-left")->setEnabled(true);
if (index != m_tabs.indexOf(m_tabs.last()))
m_mainWindow->actionCollection()->action("move-session-right")->setEnabled(true);
}
void TabBar::updateToggleActions(int sessionId)
{
if (sessionId == -1) return;
KActionCollection* actionCollection = m_mainWindow->actionCollection();
SessionStack* sessionStack = m_mainWindow->sessionStack();
QAction* toggleAction = actionCollection->action("toggle-session-prevent-closing");
toggleAction->setChecked(!sessionStack->isSessionClosable(sessionId));
toggleAction = actionCollection->action("toggle-session-keyboard-input");
toggleAction->setChecked(!sessionStack->hasTerminalsWithKeyboardInputEnabled(sessionId));
toggleAction = actionCollection->action("toggle-session-monitor-activity");
toggleAction->setChecked(!sessionStack->hasTerminalsWithMonitorActivityDisabled(sessionId));
toggleAction = actionCollection->action("toggle-session-monitor-silence");
toggleAction->setChecked(!sessionStack->hasTerminalsWithMonitorSilenceDisabled(sessionId));
}
void TabBar::updateToggleKeyboardInputMenu(int sessionId)
{
if (!m_tabs.contains(sessionId)) return;
QAction* toggleKeyboardInputAction = m_mainWindow->actionCollection()->action("toggle-session-keyboard-input");
QAction* anchor = m_toggleKeyboardInputMenu->menuAction();
SessionStack* sessionStack = m_mainWindow->sessionStack();
QStringList terminalIds = sessionStack->terminalIdsForSessionId(sessionId).split(',', QString::SkipEmptyParts);
m_toggleKeyboardInputMenu->clear();
if (terminalIds.count() <= 1)
{
toggleKeyboardInputAction->setText(i18nc("@action", "Disable Keyboard Input"));
m_tabContextMenu->insertAction(anchor, toggleKeyboardInputAction);
m_toggleKeyboardInputMenu->menuAction()->setVisible(false);
}
else
{
toggleKeyboardInputAction->setText(i18nc("@action", "For This Session"));
m_toggleKeyboardInputMenu->menuAction()->setVisible(true);
m_tabContextMenu->removeAction(toggleKeyboardInputAction);
m_toggleKeyboardInputMenu->addAction(toggleKeyboardInputAction);
m_toggleKeyboardInputMenu->addSeparator();
int count = 0;
QStringListIterator i(terminalIds);
while (i.hasNext())
{
int terminalId = i.next().toInt();
++count;
QAction* action = m_toggleKeyboardInputMenu->addAction(i18nc("@action", "For Terminal %1", count));
action->setCheckable(true);
action->setChecked(!sessionStack->isTerminalKeyboardInputEnabled(terminalId));
action->setData(terminalId);
connect(action, SIGNAL(triggered(bool)), m_mainWindow, SLOT(handleToggleTerminalKeyboardInput(bool)));
}
}
}
void TabBar::updateToggleMonitorActivityMenu(int sessionId)
{
if (!m_tabs.contains(sessionId)) return;
QAction* toggleMonitorActivityAction = m_mainWindow->actionCollection()->action("toggle-session-monitor-activity");
QAction* anchor = m_toggleMonitorActivityMenu->menuAction();
SessionStack* sessionStack = m_mainWindow->sessionStack();
QStringList terminalIds = sessionStack->terminalIdsForSessionId(sessionId).split(',', QString::SkipEmptyParts);
m_toggleMonitorActivityMenu->clear();
if (terminalIds.count() <= 1)
{
toggleMonitorActivityAction->setText(i18nc("@action", "Monitor for Activity"));
m_tabContextMenu->insertAction(anchor, toggleMonitorActivityAction);
m_toggleMonitorActivityMenu->menuAction()->setVisible(false);
}
else
{
toggleMonitorActivityAction->setText(i18nc("@action", "In This Session"));
m_toggleMonitorActivityMenu->menuAction()->setVisible(true);
m_tabContextMenu->removeAction(toggleMonitorActivityAction);
m_toggleMonitorActivityMenu->addAction(toggleMonitorActivityAction);
m_toggleMonitorActivityMenu->addSeparator();
int count = 0;
QStringListIterator i(terminalIds);
while (i.hasNext())
{
int terminalId = i.next().toInt();
++count;
QAction* action = m_toggleMonitorActivityMenu->addAction(i18nc("@action", "In Terminal %1", count));
action->setCheckable(true);
action->setChecked(sessionStack->isTerminalMonitorActivityEnabled(terminalId));
action->setData(terminalId);
connect(action, SIGNAL(triggered(bool)), m_mainWindow, SLOT(handleToggleTerminalMonitorActivity(bool)));
}
}
}
void TabBar::updateToggleMonitorSilenceMenu(int sessionId)
{
if (!m_tabs.contains(sessionId)) return;
QAction* toggleMonitorSilenceAction = m_mainWindow->actionCollection()->action("toggle-session-monitor-silence");
QAction* anchor = m_toggleMonitorSilenceMenu->menuAction();
SessionStack* sessionStack = m_mainWindow->sessionStack();
QStringList terminalIds = sessionStack->terminalIdsForSessionId(sessionId).split(',', QString::SkipEmptyParts);
m_toggleMonitorSilenceMenu->clear();
if (terminalIds.count() <= 1)
{
toggleMonitorSilenceAction->setText(i18nc("@action", "Monitor for Silence"));
m_tabContextMenu->insertAction(anchor, toggleMonitorSilenceAction);
m_toggleMonitorSilenceMenu->menuAction()->setVisible(false);
}
else
{
toggleMonitorSilenceAction->setText(i18nc("@action", "In This Session"));
m_toggleMonitorSilenceMenu->menuAction()->setVisible(true);
m_tabContextMenu->removeAction(toggleMonitorSilenceAction);
m_toggleMonitorSilenceMenu->addAction(toggleMonitorSilenceAction);
m_toggleMonitorSilenceMenu->addSeparator();
int count = 0;
QStringListIterator i(terminalIds);
while (i.hasNext())
{
int terminalId = i.next().toInt();
++count;
QAction* action = m_toggleMonitorSilenceMenu->addAction(i18nc("@action", "In Terminal %1", count));
action->setCheckable(true);
action->setChecked(sessionStack->isTerminalMonitorSilenceEnabled(terminalId));
action->setData(terminalId);
connect(action, SIGNAL(triggered(bool)), m_mainWindow, SLOT(handleToggleTerminalMonitorSilence(bool)));
}
}
}
void TabBar::contextMenuActionHovered(QAction* action)
{
bool ok = false;
if (!action->data().isNull())
{
int terminalId = action->data().toInt(&ok);
if (ok) emit requestTerminalHighlight(terminalId);
}
else if (!ok)
emit requestRemoveTerminalHighlight();
}
void TabBar::contextMenuEvent(QContextMenuEvent* event)
{
if (event->x() < 0) return;
int index = tabAt(event->x());
if (index == -1)
m_sessionMenu->exec(QCursor::pos());
else
{
readyTabContextMenu();
updateMoveActions(index);
int sessionId = sessionAtTab(index);
updateToggleActions(sessionId);
updateToggleKeyboardInputMenu(sessionId);
updateToggleMonitorActivityMenu(sessionId);
updateToggleMonitorSilenceMenu(sessionId);
m_mainWindow->setContextDependentActionsQuiet(true);
QAction* action = m_tabContextMenu->exec(QCursor::pos());
emit tabContextMenuClosed();
if (action)
{
if (action->isCheckable())
m_mainWindow->handleContextDependentToggleAction(action->isChecked(), action, sessionId);
else
m_mainWindow->handleContextDependentAction(action, sessionId);
}
m_mainWindow->setContextDependentActionsQuiet(false);
updateMoveActions(m_tabs.indexOf(m_selectedSessionId));
updateToggleActions(m_selectedSessionId);
updateToggleKeyboardInputMenu(m_selectedSessionId);
updateToggleMonitorActivityMenu(m_selectedSessionId);
updateToggleMonitorSilenceMenu(m_selectedSessionId);
}
QWidget::contextMenuEvent(event);
}
void TabBar::resizeEvent(QResizeEvent* event)
{
m_newTabButton->move(m_skin->tabBarNewTabButtonPosition().x(), m_skin->tabBarNewTabButtonPosition().y());
m_closeTabButton->move(width() - m_skin->tabBarCloseTabButtonPosition().x(), m_skin->tabBarCloseTabButtonPosition().y());
QWidget::resizeEvent(event);
}
void TabBar::paintEvent(QPaintEvent*)
{
QPainter painter(this);
painter.setPen(m_skin->tabBarTextColor());
int x = m_skin->tabBarPosition().x();
int y = m_skin->tabBarPosition().y();
m_tabWidths.clear();
QRect tabsClipRect(x, y, m_closeTabButton->x() - x, height() - y);
painter.setClipRect(tabsClipRect);
for (int index = 0; index < m_tabs.count(); ++index)
{
x = drawButton(x, y, index, painter);
m_tabWidths << x;
}
const QPixmap& backgroundImage = m_skin->tabBarBackgroundImage();
const QPixmap& leftCornerImage = m_skin->tabBarLeftCornerImage();
const QPixmap& rightCornerImage = m_skin->tabBarRightCornerImage();
x = x > tabsClipRect.right() ? tabsClipRect.right() + 1 : x;
QRegion backgroundClipRegion(rect());
backgroundClipRegion = backgroundClipRegion.subtracted(m_newTabButton->geometry());
backgroundClipRegion = backgroundClipRegion.subtracted(m_closeTabButton->geometry());
QRect tabsRect(m_skin->tabBarPosition().x(), y, x - m_skin->tabBarPosition().x(),
height() - m_skin->tabBarPosition().y());
backgroundClipRegion = backgroundClipRegion.subtracted(tabsRect);
painter.setClipRegion(backgroundClipRegion);
painter.drawImage(0, 0, leftCornerImage.toImage());
QRect leftCornerImageRect(0, 0, leftCornerImage.width(), height());
backgroundClipRegion = backgroundClipRegion.subtracted(leftCornerImageRect);
painter.drawImage(width() - rightCornerImage.width(), 0, rightCornerImage.toImage());
QRect rightCornerImageRect(width() - rightCornerImage.width(), 0, rightCornerImage.width(), height());
backgroundClipRegion = backgroundClipRegion.subtracted(rightCornerImageRect);
painter.setClipRegion(backgroundClipRegion);
painter.drawTiledPixmap(0, 0, width(), height(), backgroundImage);
painter.end();
}
int TabBar::drawButton(int x, int y, int index, QPainter& painter)
{
QString title;
int sessionId;
bool selected;
QFont font = KGlobalSettings::generalFont();
int textWidth = 0;
sessionId = m_tabs.at(index);
selected = (sessionId == m_selectedSessionId);
title = m_tabTitles[sessionId];
if (selected)
{
painter.drawPixmap(x, y, m_skin->tabBarSelectedLeftCornerImage());
x += m_skin->tabBarSelectedLeftCornerImage().width();
}
else if (index != m_tabs.indexOf(m_selectedSessionId) + 1)
{
painter.drawPixmap(x, y, m_skin->tabBarSeparatorImage());
x += m_skin->tabBarSeparatorImage().width();
}
if (selected) font.setBold(true);
else font.setBold(false);
painter.setFont(font);
QFontMetrics fontMetrics(font);
textWidth = fontMetrics.width(title) + 10;
// Draw the Prevent Closing image in the tab button.
if (m_mainWindow->sessionStack()->isSessionClosable(sessionId) == false)
{
if (selected)
painter.drawTiledPixmap(x, y,
m_skin->tabBarPreventClosingImagePosition().x() +
m_skin->tabBarPreventClosingImage().width(), height(),
m_skin->tabBarSelectedBackgroundImage());
else
painter.drawTiledPixmap(x, y,
m_skin->tabBarPreventClosingImagePosition().x() +
m_skin->tabBarPreventClosingImage().width(), height(),
m_skin->tabBarUnselectedBackgroundImage());
painter.drawPixmap(x + m_skin->tabBarPreventClosingImagePosition().x(),
m_skin->tabBarPreventClosingImagePosition().y(),
m_skin->tabBarPreventClosingImage());
x += m_skin->tabBarPreventClosingImagePosition().x();
x += m_skin->tabBarPreventClosingImage().width();
}
if (selected)
painter.drawTiledPixmap(x, y, textWidth, height(), m_skin->tabBarSelectedBackgroundImage());
else
painter.drawTiledPixmap(x, y, textWidth, height(), m_skin->tabBarUnselectedBackgroundImage());
painter.drawText(x, y, textWidth + 1, height() + 2, Qt::AlignHCenter | Qt::AlignVCenter, title);
x += textWidth;
if (selected)
{
painter.drawPixmap(x, m_skin->tabBarPosition().y(), m_skin->tabBarSelectedRightCornerImage());
x += m_skin->tabBarSelectedRightCornerImage().width();
}
else if (index != m_tabs.indexOf(m_selectedSessionId) - 1)
{
painter.drawPixmap(x, m_skin->tabBarPosition().y(), m_skin->tabBarSeparatorImage());
x += m_skin->tabBarSeparatorImage().width();
}
return x;
}
int TabBar::tabAt(int x)
{
for (int index = 0; index < m_tabWidths.count(); ++index)
{
if (x > m_skin->tabBarPosition().x() && x < m_tabWidths.at(index))
return index;
}
return -1;
}
void TabBar::wheelEvent(QWheelEvent* event)
{
if (event->delta() < 0)
selectNextTab();
else
selectPreviousTab();
}
void TabBar::keyPressEvent(QKeyEvent* event)
{
if (event->key() == Qt::Key_Escape && m_lineEdit->isVisible())
m_lineEdit->hide();
QWidget::keyPressEvent(event);
}
void TabBar::mousePressEvent(QMouseEvent* event)
{
if (QWhatsThis::inWhatsThisMode()) return;
if (event->x() < m_skin->tabBarPosition().x()) return;
int index = tabAt(event->x());
if (index == -1) return;
if (event->button() == Qt::LeftButton || event->button() == Qt::MiddleButton)
{
m_startPos = event->pos();
if (index != m_tabs.indexOf(m_selectedSessionId) || event->button() == Qt::MiddleButton)
{
m_mousePressed = true;
m_mousePressedIndex = index;
}
return;
}
QWidget::mousePressEvent(event);
}
void TabBar::mouseReleaseEvent(QMouseEvent* event)
{
if (QWhatsThis::inWhatsThisMode()) return;
if (event->x() < m_skin->tabBarPosition().x()) return;
int index = tabAt(event->x());
if (m_mousePressed && m_mousePressedIndex == index)
{
if (event->button() == Qt::LeftButton && index != m_tabs.indexOf(m_selectedSessionId))
emit tabSelected(m_tabs.at(index));
if (event->button() == Qt::MiddleButton)
emit tabClosed(m_tabs.at(index));
}
m_mousePressed = false;
m_startPos.setX(0);
m_startPos.setY(0);
QWidget::mouseReleaseEvent(event);
}
void TabBar::mouseMoveEvent(QMouseEvent* event)
{
if (!m_startPos.isNull() && ((event->buttons() & Qt::LeftButton) || (event->buttons() & Qt::MiddleButton)))
{
int distance = (event->pos() - m_startPos).manhattanLength();
if (distance >= KGlobalSettings::dndEventDelay())
{
int index = tabAt(m_startPos.x());
if (index >= 0 && !m_lineEdit->isVisible())
startDrag(index);
}
}
QWidget::mouseMoveEvent(event);
}
void TabBar::dragEnterEvent(QDragEnterEvent* event)
{
TabBar* eventSource = qobject_cast<TabBar*>(event->source());
if (eventSource)
{
event->setDropAction(Qt::MoveAction);
event->acceptProposedAction();
}
else
{
drawDropIndicator(-1);
event->ignore();
}
return;
}
void TabBar::dragMoveEvent(QDragMoveEvent* event)
{
TabBar* eventSource = qobject_cast<TabBar*>(event->source());
if (eventSource && event->pos().x() > m_skin->tabBarPosition().x() && event->pos().x() < m_closeTabButton->x())
{
int index = dropIndex(event->pos());
if (index == -1)
index = m_tabs.count();
drawDropIndicator(index, isSameTab(event));
event->setDropAction(Qt::MoveAction);
event->accept();
}
else
{
drawDropIndicator(-1);
event->ignore();
}
return;
}
void TabBar::dragLeaveEvent(QDragLeaveEvent* event)
{
drawDropIndicator(-1);
event->ignore();
return;
}
void TabBar::dropEvent(QDropEvent* event)
{
drawDropIndicator(-1);
int x = event->pos().x();
if (isSameTab(event) || x < m_skin->tabBarPosition().x() || x > m_closeTabButton->x())
event->ignore();
else
{
int targetIndex = dropIndex(event->pos());
int sourceSessionId = event->mimeData()->text().toInt();
int sourceIndex = m_tabs.indexOf(sourceSessionId);
if (targetIndex == -1)
targetIndex = m_tabs.count() - 1;
else if (targetIndex < 0)
targetIndex = 0;
else if (sourceIndex < targetIndex)
--targetIndex;
m_tabs.move(sourceIndex, targetIndex);
emit tabSelected(m_tabs.at(targetIndex));
event->accept();
}
return;
}
void TabBar::mouseDoubleClickEvent(QMouseEvent* event)
{
if (QWhatsThis::inWhatsThisMode()) return;
m_lineEdit->hide();
if (event->x() < 0) return;
int index = tabAt(event->x());
if (event->button() == Qt::LeftButton)
{
if (event->x() <= m_tabWidths.last())
interactiveRename(m_tabs.at(index));
else if (event->x() > m_tabWidths.last())
emit newTabRequested();
}
QWidget::mouseDoubleClickEvent(event);
}
void TabBar::leaveEvent(QEvent* event)
{
m_mousePressed = false;
drawDropIndicator(-1);
event->ignore();
QWidget::leaveEvent(event);
}
void TabBar::addTab(int sessionId, const QString& title)
{
m_tabs.append(sessionId);
if (title.isEmpty())
m_tabTitles.insert(sessionId, standardTabTitle());
else
m_tabTitles.insert(sessionId, title);
emit tabSelected(sessionId);
}
void TabBar::removeTab(int sessionId)
{
if (sessionId == -1) sessionId = m_selectedSessionId;
if (sessionId == -1) return;
if (!m_tabs.contains(sessionId)) return;
int index = m_tabs.indexOf(sessionId);
if (m_lineEdit->isVisible() && sessionId == m_renamingSessionId)
m_lineEdit->hide();
m_tabs.removeAt(index);
m_tabTitles.remove(sessionId);
if (m_tabs.count() == 0)
emit lastTabClosed();
else
emit tabSelected(m_tabs.last());
}
void TabBar::interactiveRename(int sessionId)
{
if (sessionId == -1) return;
if (!m_tabs.contains(sessionId)) return;
m_renamingSessionId = sessionId;
int index = m_tabs.indexOf(sessionId);
int x = index ? m_tabWidths.at(index - 1) : m_skin->tabBarPosition().x();
int y = m_skin->tabBarPosition().y();
int width = m_tabWidths.at(index) - x;
m_lineEdit->setText(m_tabTitles[sessionId]);
m_lineEdit->setGeometry(x-1, y-1, width+3, height()+2);
m_lineEdit->selectAll();
m_lineEdit->setFocus();
m_lineEdit->show();
}
void TabBar::interactiveRenameDone()
{
int sessionId = m_renamingSessionId;
m_renamingSessionId = -1;
setTabTitle(sessionId, m_lineEdit->text().trimmed());
}
void TabBar::selectTab(int sessionId)
{
if (!m_tabs.contains(sessionId)) return;
m_selectedSessionId = sessionId;
updateMoveActions(m_tabs.indexOf(sessionId));
updateToggleActions(sessionId);
repaint();
}
void TabBar::selectNextTab()
{
int index = m_tabs.indexOf(m_selectedSessionId);
int newSelectedSessionId = m_selectedSessionId;
if (index == -1)
return;
else if (index == m_tabs.count() - 1)
newSelectedSessionId = m_tabs.at(0);
else
newSelectedSessionId = m_tabs.at(index + 1);
emit tabSelected(newSelectedSessionId);
}
void TabBar::selectPreviousTab()
{
int index = m_tabs.indexOf(m_selectedSessionId);
int newSelectedSessionId = m_selectedSessionId;
if (index == -1)
return;
else if (index == 0)
newSelectedSessionId = m_tabs.at(m_tabs.count() - 1);
else
newSelectedSessionId = m_tabs.at(index - 1);
emit tabSelected(newSelectedSessionId);
}
void TabBar::moveTabLeft(int sessionId)
{
if (sessionId == -1) sessionId = m_selectedSessionId;
int index = m_tabs.indexOf(sessionId);
if (index < 1) return;
m_tabs.swap(index, index - 1);
repaint();
updateMoveActions(index - 1);
}
void TabBar::moveTabRight(int sessionId)
{
if (sessionId == -1) sessionId = m_selectedSessionId;
int index = m_tabs.indexOf(sessionId);
if (index == -1 || index == m_tabs.count() - 1) return;
m_tabs.swap(index, index + 1);
repaint();
updateMoveActions(index + 1);
}
void TabBar::closeTabButtonClicked()
{
emit tabClosed(m_selectedSessionId);
}
QString TabBar::tabTitle(int sessionId)
{
if (m_tabTitles.contains(sessionId))
return m_tabTitles[sessionId];
else
return QString();
}
void TabBar::setTabTitle(int sessionId, const QString& newTitle)
{
if (sessionId == -1) return;
if (!m_tabTitles.contains(sessionId)) return;
if (!newTitle.isEmpty())
m_tabTitles[sessionId] = newTitle;
update();
}
int TabBar::sessionAtTab(int index)
{
if (index > m_tabs.count() - 1)
return -1;
else
return m_tabs.at(index);
}
QString TabBar::standardTabTitle()
{
QString newTitle = makeTabTitle(0);
bool nameOk;
int count = 0;
do
{
nameOk = true;
QHashIterator<int, QString> it(m_tabTitles);
while (it.hasNext())
{
it.next();
if (newTitle == it.value())
{
nameOk = false;
break;
}
}
if (!nameOk)
{
count++;
newTitle = makeTabTitle(count);
}
}
while (!nameOk);
return newTitle;
}
QString TabBar::makeTabTitle(int id)
{
if (id == 0)
{
return i18nc("@title:tab", "Shell");
}
else
{
return i18nc("@title:tab", "Shell No. <numid>%1</numid>", id+1);
}
}
void TabBar::startDrag(int index)
{
int sessionId = sessionAtTab(index);
m_startPos.setX(0);
m_startPos.setY(0);
int x = index ? m_tabWidths.at(index - 1) : m_skin->tabBarPosition().x();
int tabWidth = m_tabWidths.at(index) - x;
QString title = tabTitle(sessionId);
QPixmap tab(tabWidth, height());
QColor fillColor(Settings::backgroundColor());
if (m_mainWindow->useTranslucency())
fillColor.setAlphaF(qreal(Settings::backgroundColorOpacity()) / 100);
tab.fill(fillColor);
QPainter painter(&tab);
painter.initFrom(this);
painter.setPen(m_skin->tabBarTextColor());
drawButton(0, 0, index, painter);
painter.end();
QMimeData* mimeData = new QMimeData;
mimeData->setText(QVariant(sessionId).toString());
QDrag* drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setPixmap(tab);
drag->exec(Qt::MoveAction);
return;
}
void TabBar::drawDropIndicator(int index, bool disabled)
{
const int arrowSize = 16;
if (!m_dropIndicator)
{
m_dropIndicator = new QLabel(parentWidget());
m_dropIndicator->resize(arrowSize, arrowSize);
}
QIcon::Mode drawMode = disabled ? QIcon::Disabled : QIcon::Normal;
m_dropIndicator->setPixmap(KIcon("arrow-down").pixmap(arrowSize, arrowSize, drawMode));
if (index < 0)
{
m_dropIndicator->hide();
return;
}
int temp_index;
if (index == m_tabs.count())
temp_index = index - 1;
else
temp_index = index;
int x = temp_index ? m_tabWidths.at(temp_index - 1) : m_skin->tabBarPosition().x();
int tabWidth = m_tabWidths.at(temp_index) - x;
int y = m_skin->tabBarPosition().y();
m_dropRect = QRect(x, y - height(), tabWidth, height() - y);
QPoint pos;
if (index < m_tabs.count())
pos = m_dropRect.topLeft();
else
pos = m_dropRect.topRight();
pos.rx() -= arrowSize/2;
m_dropIndicator->move(mapTo(parentWidget(),pos));
m_dropIndicator->show();
return;
}
int TabBar::dropIndex(const QPoint pos)
{
int index = tabAt(pos.x());
if (index < 0)
return index;
int x = index ? m_tabWidths.at(index - 1) : m_skin->tabBarPosition().x();
int tabWidth = m_tabWidths.at(index) - x;
int y = m_skin->tabBarPosition().y();
m_dropRect = QRect(x, y - height(), tabWidth, height() - y);
if ((pos.x()-m_dropRect.left()) > (m_dropRect.width()/2))
++index;
if (index == m_tabs.count())
return -1;
return index;
}
bool TabBar::isSameTab(const QDropEvent* event)
{
int index = dropIndex(event->pos());
int sourceSessionId = event->mimeData()->text().toInt();
int sourceIndex = m_tabs.indexOf(sourceSessionId);
bool isLastTab = (sourceIndex == m_tabs.count()-1) && (index == -1);
if ((sourceIndex == index) || (sourceIndex == index-1) || isLastTab)
return true;
else
return false;
}