592 lines
21 KiB
C++
592 lines
21 KiB
C++
|
|
/**
|
|||
|
|
* @file PaiTabWidget.cpp
|
|||
|
|
* @date 2011-07-19
|
|||
|
|
*/
|
|||
|
|
#include <QApplication>
|
|||
|
|
#include <QStyle>
|
|||
|
|
#include <QPainter>
|
|||
|
|
#include <QStyleOption>
|
|||
|
|
#include <QMouseEvent>
|
|||
|
|
#include <QByteArray>
|
|||
|
|
#include <QDataStream>
|
|||
|
|
#include <QToolTip>
|
|||
|
|
#include <QStylePainter>
|
|||
|
|
#include <QDrag>
|
|||
|
|
#include <QMimeData>
|
|||
|
|
#include "PaiTabWidget.h"
|
|||
|
|
#include "PaiWorkspace.h"
|
|||
|
|
// #include "Log.h"
|
|||
|
|
#include "PaiWindow.h"
|
|||
|
|
#include "GlobalUtility.h"
|
|||
|
|
|
|||
|
|
using namespace pai::gui;
|
|||
|
|
|
|||
|
|
void pai::gui::Serialize(const DragState & dragState, QByteArray & blob)
|
|||
|
|
{
|
|||
|
|
QDataStream stream(&blob, QIODevice::WriteOnly);
|
|||
|
|
stream << QString("PAIDragState:"); // 二进制识别头
|
|||
|
|
stream << dragState.isValid;
|
|||
|
|
stream << dragState.isDragging;
|
|||
|
|
stream << reinterpret_cast< qint64 > (dragState.pDraggingWidget);
|
|||
|
|
stream << dragState.tabIcon;
|
|||
|
|
stream << dragState.tabText;
|
|||
|
|
stream << dragState.pressPosition;
|
|||
|
|
stream << dragState.srcRect;
|
|||
|
|
stream << dragState.appPid;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void pai::gui::Unserialize(DragState & dragState, QByteArray & blob)
|
|||
|
|
{
|
|||
|
|
QDataStream stream(&blob, QIODevice::ReadOnly);
|
|||
|
|
QString strIdent;
|
|||
|
|
stream >> strIdent;
|
|||
|
|
if(strIdent != "PAIDragState:") // 二进制识别头验证
|
|||
|
|
{
|
|||
|
|
// pai::log::Debug(_FLF(QObject::tr("Unrecognized dragging state!").toStdString()));
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
stream >> dragState.isValid;
|
|||
|
|
stream >> dragState.isDragging;
|
|||
|
|
qint64 pointer;
|
|||
|
|
stream >> pointer;
|
|||
|
|
dragState.pDraggingWidget = reinterpret_cast< QWidget* > (pointer);
|
|||
|
|
stream >> dragState.tabIcon;
|
|||
|
|
stream >> dragState.tabText;
|
|||
|
|
stream >> dragState.pressPosition;
|
|||
|
|
stream >> dragState.srcRect;
|
|||
|
|
stream >> dragState.appPid;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
PaiInfoTabBar::PaiInfoTabBar(QWidget *pParent, bool isSubTabBar, SelectionBehavior behavior) :
|
|||
|
|
QTabBar(pParent),
|
|||
|
|
m_draggable(true),
|
|||
|
|
m_OutOfConsoleTimer(0)
|
|||
|
|
{
|
|||
|
|
setFocusPolicy(Qt::StrongFocus); // 保证LineEdit的editingFinished先执行
|
|||
|
|
setMouseTracking(true);
|
|||
|
|
setElideMode(Qt::ElideRight);
|
|||
|
|
InitDragState(); // 由于setMouseTracking为true,所以mouseMoveEvent会无条件进入,需要对该结构初始化
|
|||
|
|
m_IsSubTabwidget = isSubTabBar;
|
|||
|
|
setProperty("isSubTabBar", isSubTabBar);
|
|||
|
|
setSelectionBehaviorOnRemove(behavior);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PaiInfoTabBar::SetDraggable(bool draggable)
|
|||
|
|
{
|
|||
|
|
m_draggable = draggable;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//该重绘函数主要解决在未拖动的情况的绘制,其中style sheet中
|
|||
|
|
//margin: 0px 0px 1px 5px; padding-right:0px; padding-left:5px;必需设置,
|
|||
|
|
//否则因系统会因为大约5像素的偏差而导致文字的...(elide)被设置错误,在拖动的情况下则完全由QSS来决定。
|
|||
|
|
void PaiInfoTabBar::paintEvent(QPaintEvent *pEvent)
|
|||
|
|
{
|
|||
|
|
QTabBar::paintEvent(pEvent);
|
|||
|
|
QLinearGradient normalLG(QPointF(0, 0), QPointF(0, height()));
|
|||
|
|
QLinearGradient selectedLG(QPointF(0, 0), QPointF(0, height()));
|
|||
|
|
QLinearGradient hoverLG(QPointF(0, 0), QPointF(0, height()));
|
|||
|
|
QLinearGradient shLG(QPointF(0, 0), QPointF(0, height()));
|
|||
|
|
if(m_IsSubTabwidget)
|
|||
|
|
{
|
|||
|
|
normalLG.setColorAt(1.0, QColor("#D6E4F3"));
|
|||
|
|
selectedLG.setColorAt(0.0, QColor("#E7F0F8"));
|
|||
|
|
selectedLG.setColorAt(1.0, QColor("#FFFFFF"));
|
|||
|
|
hoverLG.setColorAt(1.0, QColor("#F2F7FB"));
|
|||
|
|
shLG.setColorAt(1.00, QColor("#F2F7FB"));
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
normalLG.setColorAt(0.0, QColor("#ECF3FC"));
|
|||
|
|
normalLG.setColorAt(1.0, QColor("#DFEAF9"));
|
|||
|
|
selectedLG.setColorAt(0.0, QColor("#FEF6D1"));
|
|||
|
|
selectedLG.setColorAt(1.0, QColor("#FDE88C"));
|
|||
|
|
hoverLG.setColorAt(0.0, QColor("#FFFFFF"));
|
|||
|
|
hoverLG.setColorAt(1.0, QColor("#E1ECFA"));
|
|||
|
|
shLG.setColorAt(0.00, QColor("#FFFBEB"));
|
|||
|
|
shLG.setColorAt(0.49, QColor("#FEF7D8"));
|
|||
|
|
shLG.setColorAt(0.50, QColor("#FEF4C2"));
|
|||
|
|
shLG.setColorAt(1.00, QColor("#FDEB99"));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
QLinearGradient grayLG(QPointF(0, 0), QPointF(0, height()));
|
|||
|
|
grayLG.setColorAt(0.0, QColor("#E8F1F9"));
|
|||
|
|
grayLG.setColorAt(1.0, QColor("#E8F1F9"));
|
|||
|
|
|
|||
|
|
QLinearGradient errorLG(QPointF(0, 0), QPointF(0, height()));
|
|||
|
|
errorLG.setColorAt(0.0, QColor(255, 255, 255));
|
|||
|
|
errorLG.setColorAt(1.0, QColor(255, 0, 0));
|
|||
|
|
|
|||
|
|
QPainter painter(this);
|
|||
|
|
|
|||
|
|
for(int i = 0; i < count(); i++)
|
|||
|
|
{
|
|||
|
|
QStyleOptionTab opt;
|
|||
|
|
initStyleOption(&opt, i);
|
|||
|
|
|
|||
|
|
QRect rt = opt.rect.adjusted(0, 0, -2, 0); // tab 页之间预留2像素间距
|
|||
|
|
QRect contentRect = rt.adjusted(5, 0, tabsClosable() ? -15 : -5, 0); // 内容区 margin-left:5px, margin-right:15px,因右侧有关闭按钮
|
|||
|
|
|
|||
|
|
painter.setPen(QColor("#677B8E"));
|
|||
|
|
if(opt.text == "Error") // 错误模式
|
|||
|
|
{
|
|||
|
|
painter.setBrush(QBrush(errorLG));
|
|||
|
|
}
|
|||
|
|
else if((opt.state & QStyle::State_Selected) && (opt.state & QStyle::State_MouseOver)) // 选中并且鼠标在上面
|
|||
|
|
{
|
|||
|
|
painter.setBrush(QBrush(shLG));
|
|||
|
|
}
|
|||
|
|
else if(opt.state & QStyle::State_Selected) // 仅仅选中
|
|||
|
|
{
|
|||
|
|
painter.setBrush(QBrush(selectedLG));
|
|||
|
|
}
|
|||
|
|
else if(opt.state & QStyle::State_MouseOver) // 鼠标在上面,没有选中
|
|||
|
|
{
|
|||
|
|
painter.setBrush(QBrush(hoverLG));
|
|||
|
|
}
|
|||
|
|
else // 其它情况
|
|||
|
|
{
|
|||
|
|
painter.setBrush(QBrush(normalLG));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(!isTabEnabled(i))
|
|||
|
|
{
|
|||
|
|
painter.setBrush(QBrush(grayLG));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if((opt.shape == QTabBar::RoundedNorth) || (opt.shape == QTabBar::TriangularNorth)) // 页签在上面
|
|||
|
|
{
|
|||
|
|
painter.drawRoundedRect(rt.adjusted(0, 0, 0, 3), 3, 3); // 矩形留3px圆角,为使底部无圆角,向下拉大3px,使下部隐藏
|
|||
|
|
}
|
|||
|
|
else if((opt.shape == QTabBar::RoundedSouth) || (opt.shape == QTabBar::TriangularSouth)) // 页签在下面
|
|||
|
|
{
|
|||
|
|
painter.drawRoundedRect(rt.adjusted(0, -3, 0, -1), 3, 3); // 矩形留3px圆角,为使顶部无圆角,向下拉大3px,使顶部隐藏,为了保证矩形底部直线可以显示向下移动1px
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
painter.drawRect(rt); // 其它情况
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(opt.icon.isNull()) // 没有图标
|
|||
|
|
{
|
|||
|
|
QString text = opt.fontMetrics.elidedText(opt.text, Qt::ElideRight, contentRect.width());
|
|||
|
|
if(isTabEnabled(i))
|
|||
|
|
{
|
|||
|
|
painter.setPen(QColor(Qt::black));
|
|||
|
|
}
|
|||
|
|
painter.drawText(contentRect, Qt::AlignLeft | Qt::AlignVCenter, text);
|
|||
|
|
}
|
|||
|
|
else // 有图标
|
|||
|
|
{
|
|||
|
|
QString text = opt.fontMetrics.elidedText(opt.text, Qt::ElideRight, contentRect.width() - 20);
|
|||
|
|
if(isTabEnabled(i))
|
|||
|
|
{
|
|||
|
|
painter.setPen(QColor(Qt::black));
|
|||
|
|
}
|
|||
|
|
painter.drawText(contentRect.adjusted(20, 0, 0, 0), Qt::AlignLeft | Qt::AlignVCenter, text); // 有图标时左侧预留20像素绘制图标
|
|||
|
|
tabIcon(i).paint(&painter, contentRect, Qt::AlignLeft | Qt::AlignVCenter);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PaiInfoTabBar::InitDragState()
|
|||
|
|
{
|
|||
|
|
m_DragState.appPid = QCoreApplication::applicationPid();
|
|||
|
|
m_DragState.isValid = false;
|
|||
|
|
m_DragState.isDragging = false;
|
|||
|
|
m_DragState.pDraggingWidget = NULL;
|
|||
|
|
m_DragState.tabIcon = QIcon();
|
|||
|
|
m_DragState.tabText = "";
|
|||
|
|
m_DragState.pressPosition = QPoint(0, 0);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool PaiInfoTabBar::IsDraggable() const
|
|||
|
|
{
|
|||
|
|
if(!m_draggable)
|
|||
|
|
{
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
return ((NULL != GetFirstParentObject< pai::gui::PaiWorkspace > (const_cast< PaiInfoTabBar* > (this)))
|
|||
|
|
&& tabsClosable());
|
|||
|
|
}
|
|||
|
|
void PaiInfoTabBar::mousePressEvent(QMouseEvent *pEvent)
|
|||
|
|
{
|
|||
|
|
InitDragState();
|
|||
|
|
if(pEvent->button() == Qt::LeftButton)
|
|||
|
|
{
|
|||
|
|
if(IsDraggable())
|
|||
|
|
{
|
|||
|
|
for(int i = 0; i < count(); ++i)
|
|||
|
|
{
|
|||
|
|
if(tabButton(i, RightSide) != NULL)
|
|||
|
|
{
|
|||
|
|
// 禁止从关闭按钮上发起拖拽
|
|||
|
|
if(tabButton(i, RightSide)->geometry().contains(pEvent->pos()))
|
|||
|
|
{
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if(tabRect(i).contains(pEvent->pos()))
|
|||
|
|
{
|
|||
|
|
QTabWidget *pTabWidget = dynamic_cast< QTabWidget* > (parentWidget());
|
|||
|
|
if(pTabWidget != NULL)
|
|||
|
|
{
|
|||
|
|
m_DragState.pDraggingWidget = pTabWidget->widget(i);
|
|||
|
|
m_DragState.tabIcon = tabIcon(i);
|
|||
|
|
m_DragState.tabText = tabText(i);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if(m_DragState.pDraggingWidget != NULL)
|
|||
|
|
{
|
|||
|
|
m_DragState.isValid = true;
|
|||
|
|
m_DragState.pressPosition = pEvent->pos();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
QTabBar::mousePressEvent(pEvent);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PaiInfoTabBar::mouseMoveEvent(QMouseEvent *pEvent)
|
|||
|
|
{
|
|||
|
|
if(m_DragState.isValid)
|
|||
|
|
{
|
|||
|
|
QPoint pos = (pEvent->pos() - m_DragState.pressPosition);
|
|||
|
|
|
|||
|
|
//只有在以下条件满足时才修改拖拽状态,视为拖拽开始
|
|||
|
|
//1.本身还未记录为拖拽状态
|
|||
|
|
//2.鼠标按压状态下移动的布线长度大于系统设定的拖拽起始长度
|
|||
|
|
//3.鼠标拖动轨迹大于30度角(0.71约为30度角的直角边长之比),如果
|
|||
|
|
// 小于30度则认为其是移动页签而不是拖拽页签。(注*:如果取消这个条
|
|||
|
|
// 件,在小角度快速频繁按压移动鼠标时会误认为是拖拽,造成绘制混乱)
|
|||
|
|
if((!m_DragState.isDragging)
|
|||
|
|
&& (pos.manhattanLength() > QApplication::startDragDistance())
|
|||
|
|
&& (qAbs(pos.y()) / (float) qAbs(pos.x())) > 0.71)
|
|||
|
|
{
|
|||
|
|
m_DragState.isDragging = true;
|
|||
|
|
m_DragState.srcRect = parentWidget()->geometry();
|
|||
|
|
}
|
|||
|
|
if(m_DragState.isDragging)
|
|||
|
|
{
|
|||
|
|
if(!MapToGlobal(this, rect()).contains(pEvent->globalPos()))
|
|||
|
|
{
|
|||
|
|
QDrag *pDrag = new QDrag(this);
|
|||
|
|
QPixmap pixmap(m_DragState.srcRect.size());
|
|||
|
|
pixmap.fill(QColor(0, 0, 0, 0));
|
|||
|
|
QStylePainter p(&pixmap, this);
|
|||
|
|
QStyleOptionTabV3 tab;
|
|||
|
|
initStyleOption(&tab, this->currentIndex());
|
|||
|
|
|
|||
|
|
p.drawControl(QStyle::CE_TabBarTab, tab);
|
|||
|
|
m_DragState.pDraggingWidget->render(&pixmap, QPoint(0, this->height()));
|
|||
|
|
|
|||
|
|
pDrag->setPixmap(pixmap);
|
|||
|
|
pDrag->setHotSpot(QPoint(rect().width() / 2, rect().height() / 2));
|
|||
|
|
QMimeData *pMimeData = new QMimeData;
|
|||
|
|
QByteArray blob;
|
|||
|
|
Serialize(m_DragState, blob);
|
|||
|
|
pMimeData->setData("text/csv", blob);
|
|||
|
|
pDrag->setMimeData(pMimeData);
|
|||
|
|
|
|||
|
|
killTimer(m_OutOfConsoleTimer);
|
|||
|
|
m_OutOfConsoleTimer = startTimer(150);
|
|||
|
|
Qt::DropAction eDropAction = pDrag->exec(Qt::MoveAction | Qt::IgnoreAction, Qt::IgnoreAction);
|
|||
|
|
killTimer(m_OutOfConsoleTimer);
|
|||
|
|
qApp->restoreOverrideCursor();
|
|||
|
|
|
|||
|
|
// Note:为拖拽到类似firefox的页面的情况做特殊处理,当拖拽到firefox页面上时,底层返回Action认为是MoveAction,这时的targe返回为空
|
|||
|
|
// 如果是拖拽到前面拖出的窗口中,返回的targe会是一个PaiWorkspace。
|
|||
|
|
if(((eDropAction == Qt::IgnoreAction)
|
|||
|
|
&& !window()->geometry().contains(QCursor::pos()))
|
|||
|
|
|| ((eDropAction == Qt::MoveAction)
|
|||
|
|
&& (pDrag->target() == NULL)
|
|||
|
|
&& !window()->geometry().contains(QCursor::pos())))
|
|||
|
|
{
|
|||
|
|
PaiTabWidget *pTabWidget = dynamic_cast< PaiTabWidget* > (parentWidget());
|
|||
|
|
if(pTabWidget != NULL)
|
|||
|
|
{
|
|||
|
|
// 将拖拽的页签先从之前的页签区域移除
|
|||
|
|
int iDraggingIndex = pTabWidget->indexOf(m_DragState.pDraggingWidget);
|
|||
|
|
|
|||
|
|
QIcon icon = tabIcon(iDraggingIndex);
|
|||
|
|
QString text = tabText(iDraggingIndex);
|
|||
|
|
|
|||
|
|
PaiWindow *pParent = GetLastParentObject< PaiWindow > (this);
|
|||
|
|
PaiWindow *pNewWindow = new PaiWindow(pParent);
|
|||
|
|
pai::gui::PaiWorkspace::RemoveViewFromTabWidget(m_DragState.pDraggingWidget, pTabWidget);
|
|||
|
|
|
|||
|
|
pai::gui::PaiWorkspace *pNewWorkspace = new pai::gui::PaiWorkspace(pNewWindow);
|
|||
|
|
connect(pNewWorkspace, SIGNAL(SubtitleChanged()), pParent, SLOT(RefreshWindowTitle()));
|
|||
|
|
pNewWorkspace->setAttribute(Qt::WA_DeleteOnClose);
|
|||
|
|
pNewWorkspace->setWindowIcon(QIcon(":/Logo.png"));
|
|||
|
|
if(!m_DragState.srcRect.isValid())
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 将拖拽的页签添加到拖出来的新窗口
|
|||
|
|
pNewWorkspace->AddWidget("#", m_DragState.pDraggingWidget, text, icon);
|
|||
|
|
pNewWindow->setAttribute(Qt::WA_DeleteOnClose);
|
|||
|
|
pNewWindow->setGeometry(QCursor::pos().x() - m_DragState.srcRect.width() / 2,
|
|||
|
|
QCursor::pos().y() - 5,
|
|||
|
|
m_DragState.srcRect.width(),
|
|||
|
|
m_DragState.srcRect.height());
|
|||
|
|
QHBoxLayout *pNewWindowLayout = new QHBoxLayout(pNewWindow->GetContainer());
|
|||
|
|
pNewWindowLayout->setContentsMargins(0, 5, 0, 0);
|
|||
|
|
pNewWindowLayout->addWidget(pNewWorkspace);
|
|||
|
|
|
|||
|
|
pNewWindow->setVisible(true);
|
|||
|
|
pNewWindow->raise();
|
|||
|
|
InitDragState();
|
|||
|
|
pEvent->ignore();
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// 由于拖拽的页面可能落在其他地方,所以拖拽源需要刷新一下
|
|||
|
|
parentWidget()->repaint();
|
|||
|
|
// 由于拖拽功能劫持了页签的移动位置过程,下面让移动了的页签复位
|
|||
|
|
QMouseEvent fake(QEvent::MouseButtonPress,
|
|||
|
|
m_DragState.pressPosition,
|
|||
|
|
mapToGlobal(m_DragState.pressPosition),
|
|||
|
|
Qt::LeftButton,
|
|||
|
|
QApplication::mouseButtons(),
|
|||
|
|
QApplication::keyboardModifiers());
|
|||
|
|
QTabBar::mousePressEvent(&fake);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
QTabBar::mouseMoveEvent(pEvent);
|
|||
|
|
}
|
|||
|
|
void PaiInfoTabBar::mouseReleaseEvent(QMouseEvent *pEvent)
|
|||
|
|
{
|
|||
|
|
InitDragState();
|
|||
|
|
|
|||
|
|
QTabBar::mouseReleaseEvent(pEvent);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool PaiInfoTabBar::event(QEvent *pEvent)
|
|||
|
|
{
|
|||
|
|
if(pEvent->type() == QEvent::ToolTip)
|
|||
|
|
{
|
|||
|
|
QHelpEvent *pHelpEvent = static_cast< QHelpEvent * > (pEvent);
|
|||
|
|
int index = tabAt(pHelpEvent->pos());
|
|||
|
|
|
|||
|
|
if(index != -1)
|
|||
|
|
{
|
|||
|
|
QString text = tabText(index);
|
|||
|
|
// 如果文本的长度+关闭按钮的宽度大于页签宽度,则以tooltip形式将文本显示全
|
|||
|
|
int widthText = 0;
|
|||
|
|
int widthButton = 0;
|
|||
|
|
|
|||
|
|
if(!text.isNull() && !text.isEmpty())
|
|||
|
|
{
|
|||
|
|
widthText = fontMetrics().width(text);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(tabButton(index, RightSide) != NULL)
|
|||
|
|
{
|
|||
|
|
widthButton = tabButton(index, RightSide)->width();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if((widthText + widthButton) > tabRect(index).width())
|
|||
|
|
{
|
|||
|
|
QToolTip::showText(pHelpEvent->globalPos(), text);
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
QToolTip::hideText();
|
|||
|
|
pEvent->ignore();
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
return QTabBar::event(pEvent);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PaiInfoTabBar::timerEvent(QTimerEvent *pEvent)
|
|||
|
|
{
|
|||
|
|
if(pEvent->timerId() == m_OutOfConsoleTimer)
|
|||
|
|
{
|
|||
|
|
QList< QWidget* > lstHiddenPaiWindow;
|
|||
|
|
foreach (QWidget *pWidget, QApplication::topLevelWidgets())
|
|||
|
|
{
|
|||
|
|
if(dynamic_cast< pai::gui::PaiWindow* > (pWidget))
|
|||
|
|
{
|
|||
|
|
if(pWidget->isHidden())
|
|||
|
|
{
|
|||
|
|
lstHiddenPaiWindow << pWidget;
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(pWidget->geometry().contains(QCursor::pos()))
|
|||
|
|
{
|
|||
|
|
if(qApp->overrideCursor() == NULL)
|
|||
|
|
{
|
|||
|
|
qApp->setOverrideCursor(Qt::ArrowCursor);//拖到PaiWindow上则复原光标重载的功能
|
|||
|
|
}
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
for(int i = lstHiddenPaiWindow.size() - 1; i >= 0; --i)
|
|||
|
|
{
|
|||
|
|
delete lstHiddenPaiWindow[i];//ToDo 暂时在这里消除PaiWorkspace::OnAllTabRemoved函数中的close不能销毁PaiWindow实例的缺陷
|
|||
|
|
lstHiddenPaiWindow[i] = NULL;
|
|||
|
|
}
|
|||
|
|
while(qApp->overrideCursor() != NULL)
|
|||
|
|
{
|
|||
|
|
qApp->restoreOverrideCursor();//拖到外面的情况下去掉光标重载
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
PaiTabWidget::PaiTabWidget(QWidget *pParent,
|
|||
|
|
bool isSubTabBar,
|
|||
|
|
QTabBar::SelectionBehavior behavior) :
|
|||
|
|
QTabWidget(pParent),
|
|||
|
|
m_IsDropableTab(true)
|
|||
|
|
{
|
|||
|
|
setTabBar(new PaiInfoTabBar(this, isSubTabBar, behavior));
|
|||
|
|
setTabsClosable(true);
|
|||
|
|
setMovable(true);
|
|||
|
|
connect(this, SIGNAL(tabCloseRequested(int)), SLOT(OnTabClose(int)));
|
|||
|
|
connect(this, SIGNAL(currentChanged(int)), SLOT(OnCurrentChanged(int)));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PaiTabWidget::CloseTab(int index)
|
|||
|
|
{
|
|||
|
|
emit tabCloseRequested(index);
|
|||
|
|
}
|
|||
|
|
void PaiTabWidget::CloseAll()
|
|||
|
|
{
|
|||
|
|
for(int i = count() - 1; i >= 0; --i)
|
|||
|
|
{
|
|||
|
|
emit tabCloseRequested(i);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PaiTabWidget::SetTabVisible(bool visible)
|
|||
|
|
{
|
|||
|
|
tabBar()->setVisible(visible);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PaiTabWidget::OnTabClose(int index)
|
|||
|
|
{
|
|||
|
|
QWidget *pTabPage = widget(index);
|
|||
|
|
if(!pTabPage)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool deleteOnClose = true;
|
|||
|
|
if(pTabPage->property("IsDeleteOnClose").isValid())
|
|||
|
|
{
|
|||
|
|
deleteOnClose = pTabPage->property("IsDeleteOnClose").toBool();
|
|||
|
|
}
|
|||
|
|
QVariant varExtensionID = pTabPage->property("ExtensionID");
|
|||
|
|
QString extensionID = varExtensionID.isValid() ? varExtensionID.toString() : QString::number(index);
|
|||
|
|
AcceptClosing_P(this);
|
|||
|
|
emit TabWillBeClosed(extensionID); // 该功能的正常使用,是利用在主进程中信号即关联的槽函数是顺序执行的
|
|||
|
|
if(!IsCloseable(this))
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if(widget(index) == pTabPage)
|
|||
|
|
{
|
|||
|
|
if(deleteOnClose)
|
|||
|
|
{
|
|||
|
|
removeTab(index);
|
|||
|
|
pTabPage->deleteLater();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
removeTab(index);
|
|||
|
|
|
|||
|
|
// 目前所有不允许析构的页面都是PageService下的辅助页面,
|
|||
|
|
// 此时由PageService::CloseExtraViewExtensions()释放pTabPage
|
|||
|
|
pTabPage->setParent(NULL);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
m_ClosedTabID = extensionID;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PaiTabWidget::OnCurrentChanged(int index)
|
|||
|
|
{
|
|||
|
|
QWidget *pTabPage = this->widget(index);
|
|||
|
|
if(pTabPage != NULL)
|
|||
|
|
{
|
|||
|
|
QVariant varExtensionID = pTabPage->property("ExtensionID");
|
|||
|
|
QString extensionID = varExtensionID.isValid() ? varExtensionID.toString() : QString::number(index);
|
|||
|
|
emit CurrentTabChanged(extensionID);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PaiTabWidget::tabInserted(int index)
|
|||
|
|
{
|
|||
|
|
QTabWidget::tabInserted(index);
|
|||
|
|
|
|||
|
|
emit TabInserted(index);//发出一个Tab被添加的消息
|
|||
|
|
}
|
|||
|
|
void PaiTabWidget::tabRemoved(int index)
|
|||
|
|
{
|
|||
|
|
QTabWidget::tabRemoved(index);
|
|||
|
|
if(0 == count())
|
|||
|
|
{
|
|||
|
|
QString areaName = this->property("AreaName").toString();
|
|||
|
|
emit AllTabClosed(areaName);//发出最后一个Tab被移除的消息
|
|||
|
|
}
|
|||
|
|
if(!m_ClosedTabID.isEmpty())
|
|||
|
|
{
|
|||
|
|
emit TabRemoved(m_ClosedTabID);
|
|||
|
|
m_ClosedTabID = "";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
void PaiTabWidget::paintEvent(QPaintEvent *pEvent)
|
|||
|
|
{
|
|||
|
|
if(count() == 0)
|
|||
|
|
{
|
|||
|
|
QPainter p(this);
|
|||
|
|
p.fillRect(pEvent->rect(), QBrush(QColor("#829BB5")));
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
QTabWidget::paintEvent(pEvent);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool PaiTabWidget::eventFilter(QObject *pObj, QEvent *pEvent)
|
|||
|
|
{
|
|||
|
|
if((pEvent->type() == QEvent::DragEnter) || (pEvent->type() == QEvent::DragMove) || (pEvent->type() == QEvent::Drop))
|
|||
|
|
{
|
|||
|
|
pEvent->ignore();//ToDo 由于QWebView的拖拽功能和PAI系统拖拽页签不兼容,暂时将页签中的QWebView的拖拽功能禁止掉
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
return QTabWidget::eventFilter(pObj, pEvent);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PaiTabWidget::SetDropable(bool dropable)
|
|||
|
|
{
|
|||
|
|
m_IsDropableTab = dropable;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool PaiTabWidget::IsDropable()
|
|||
|
|
{
|
|||
|
|
return m_IsDropableTab;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void PaiTabWidget::SetTabBarDraggable(bool draggable)
|
|||
|
|
{
|
|||
|
|
PaiInfoTabBar *pTabBar = qobject_cast< PaiInfoTabBar* > (tabBar());
|
|||
|
|
if(pTabBar)
|
|||
|
|
{
|
|||
|
|
pTabBar->SetDraggable(draggable);
|
|||
|
|
}
|
|||
|
|
}
|