You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

229 lines
6.4 KiB

/*
This file is part of the Konsole Terminal.
Copyright 2006-2008 Robert Knight <robertknight@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) any later version.
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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
*/
// Own
#include "ViewContainerTabBar.h"
#include "ViewContainer.h"
// Qt
#include <QtCore/QMimeData>
#include <QLabel>
#include <QtGui/QPainter>
#include <QtGui/QDragMoveEvent>
// KDE
#include <KLocalizedString>
#include <KIcon>
using Konsole::ViewContainerTabBar;
using Konsole::TabbedViewContainer;
ViewContainerTabBar::ViewContainerTabBar(QWidget* parent, TabbedViewContainer* container)
: KTabBar(parent)
, _dropIndicator(0)
, _dropIndicatorIndex(-1)
, _drawIndicatorDisabled(false)
, _connectedContainer(container)
{
setDrawBase(true);
setDocumentMode(true);
setFocusPolicy(Qt::NoFocus);
setSelectionBehaviorOnRemove(QTabBar::SelectPreviousTab);
setElideMode(Qt::ElideLeft);
setWhatsThis(i18nc("@info:whatsthis",
"<title>Tab Bar</title>"
"<para>The tab bar allows you to switch and move tabs. You can double-click a tab to change its name.</para>"));
}
void ViewContainerTabBar::dragEnterEvent(QDragEnterEvent* event)
{
if (event->mimeData()->hasFormat(_supportedMimeType) &&
event->source() != 0)
event->acceptProposedAction();
}
void ViewContainerTabBar::dragLeaveEvent(QDragLeaveEvent*)
{
setDropIndicator(-1);
}
void ViewContainerTabBar::dragMoveEvent(QDragMoveEvent* event)
{
if (event->mimeData()->hasFormat(_supportedMimeType)
&& event->source() != 0) {
int index = dropIndex(event->pos());
if (index == -1)
index = count();
setDropIndicator(index, proposedDropIsSameTab(event));
event->acceptProposedAction();
}
}
void ViewContainerTabBar::dropEvent(QDropEvent* event)
{
setDropIndicator(-1);
if (!event->mimeData()->hasFormat(_supportedMimeType)) {
event->ignore();
return;
}
if (proposedDropIsSameTab(event)) {
event->setDropAction(Qt::IgnoreAction);
event->accept();
return;
}
const int index = dropIndex(event->pos());
bool success = false;
ViewContainerTabBar* sourceContainerTabBar = static_cast<ViewContainerTabBar*>(event->source());
// check if the moved tab is the last of source view.
if (sourceContainerTabBar->count() == 1) {
TabbedViewContainer* sourceTabbedContainer = sourceContainerTabBar->connectedTabbedViewContainer();
emit moveViewRequest(index, event, success, sourceTabbedContainer);
} else {
emit moveViewRequest(index, event, success, NULL);
}
if (success)
event->accept();
else
event->ignore();
}
TabbedViewContainer* ViewContainerTabBar::connectedTabbedViewContainer()
{
return _connectedContainer;
}
void ViewContainerTabBar::setDropIndicator(int index, bool drawDisabled)
{
if (!parentWidget() || _dropIndicatorIndex == index)
return;
_dropIndicatorIndex = index;
const int ARROW_SIZE = 32;
const bool north = shape() == KTabBar::RoundedNorth || shape() == KTabBar::TriangularNorth;
if (!_dropIndicator || _drawIndicatorDisabled != drawDisabled) {
if (!_dropIndicator) {
_dropIndicator = new QLabel(parentWidget());
_dropIndicator->resize(ARROW_SIZE, ARROW_SIZE);
}
QIcon::Mode drawMode = drawDisabled ? QIcon::Disabled : QIcon::Normal;
const QString iconName = north ? "arrow-up" : "arrow-down";
_dropIndicator->setPixmap(KIcon(iconName).pixmap(ARROW_SIZE, ARROW_SIZE, drawMode));
_drawIndicatorDisabled = drawDisabled;
}
if (index < 0) {
_dropIndicator->hide();
return;
}
const QRect rect = tabRect(index < count() ? index : index - 1);
QPoint pos;
if (index < count())
pos = rect.topLeft();
else
pos = rect.topRight();
if (north)
pos.ry() += ARROW_SIZE;
else
pos.ry() -= ARROW_SIZE;
pos.rx() -= ARROW_SIZE / 2;
_dropIndicator->move(mapTo(parentWidget(), pos));
_dropIndicator->show();
}
void ViewContainerTabBar::setSupportedMimeType(const QString& mimeType)
{
_supportedMimeType = mimeType;
}
int ViewContainerTabBar::dropIndex(const QPoint& pos) const
{
int tab = tabAt(pos);
if (tab < 0)
return tab;
// pick the closest tab boundary
QRect rect = tabRect(tab);
if ((pos.x() - rect.left()) > (rect.width() / 2))
tab++;
if (tab == count())
return -1;
return tab;
}
bool ViewContainerTabBar::proposedDropIsSameTab(const QDropEvent* event) const
{
const bool sameTabBar = event->source() == this;
if (!sameTabBar)
return false;
const int index = dropIndex(event->pos());
int sourceIndex = -1;
emit querySourceIndex(event, sourceIndex);
const bool sourceAndDropAreLast = sourceIndex == count() - 1 && index == -1;
if (sourceIndex == index || sourceIndex == index - 1 || sourceAndDropAreLast)
return true;
else
return false;
}
QPixmap ViewContainerTabBar::dragDropPixmap(int tab)
{
Q_ASSERT(tab >= 0 && tab < count());
// TODO - grabWidget() works except that it includes part
// of the tab bar outside the tab itself if the tab has
// curved corners
const QRect rect = tabRect(tab);
const int borderWidth = 1;
QPixmap tabPixmap(rect.width() + borderWidth,
rect.height() + borderWidth);
QPainter painter(&tabPixmap);
painter.drawPixmap(0, 0, QPixmap::grabWidget(this, rect));
QPen borderPen;
borderPen.setBrush(palette().dark());
borderPen.setWidth(borderWidth);
painter.setPen(borderPen);
painter.drawRect(0, 0, rect.width(), rect.height());
painter.end();
return tabPixmap;
}