/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Designer of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qdesigner_tabwidget_p.h"
#include "qdesigner_command_p.h"
#include "qdesigner_propertycommand_p.h"
#include "promotiontaskmenu_p.h"
#include "formwindowbase_p.h"

#include <QtDesigner/QDesignerFormWindowInterface>

#include <QtGui/QApplication>
#include <QtGui/QTabBar>
#include <QtGui/QAction>
#include <QtGui/QMouseEvent>
#include <QtGui/QMenu>
#include <QtGui/QLabel>
#include <QtGui/QTabWidget>

#include <QtCore/qdebug.h>

QT_BEGIN_NAMESPACE

namespace qdesigner_internal {
// Store tab widget as drag source
class MyMimeData : public QMimeData
{
    Q_OBJECT
public:
    MyMimeData(const QTabWidget *tab) : m_tab(tab) {}
    static bool fromMyTab(const QMimeData *mimeData, const QTabWidget *tab) {
        if (!mimeData)
            return false;
        const MyMimeData *m = qobject_cast<const MyMimeData *>(mimeData);
        return m &&  m->m_tab ==  tab;
    }
private:
    const QTabWidget *m_tab;
};

} // namespace qdesigner_internal

// ------------- QTabWidgetEventFilter

QTabWidgetEventFilter::QTabWidgetEventFilter(QTabWidget *parent) :
    QObject(parent),
    m_tabWidget(parent),
    m_dropIndicator(0),
    m_dragPage(0),
    m_mousePressed(false),
    m_actionDeletePage(new QAction(tr("Delete"),  this)),
    m_actionInsertPage(new QAction(tr("Before Current Page"), this)),
    m_actionInsertPageAfter(new QAction(tr("After Current Page"), this)),
    m_pagePromotionTaskMenu(new qdesigner_internal::PromotionTaskMenu(0, qdesigner_internal::PromotionTaskMenu::ModeSingleWidget, this))
{
    tabBar()->setAcceptDrops(true);
    tabBar()->installEventFilter(this);

    connect(m_actionInsertPage, SIGNAL(triggered()), this, SLOT(addPage()));
    connect(m_actionInsertPageAfter, SIGNAL(triggered()), this, SLOT(addPageAfter()));
    connect(m_actionDeletePage, SIGNAL(triggered()), this, SLOT(removeCurrentPage()));
}

QTabWidgetEventFilter::~QTabWidgetEventFilter()
{
}

void QTabWidgetEventFilter::install(QTabWidget *tabWidget)
{
    new QTabWidgetEventFilter(tabWidget);
}

QTabWidgetEventFilter *QTabWidgetEventFilter::eventFilterOf(const QTabWidget *tabWidget)
{
    // Look for 1st order children only..otherwise, we might get filters of nested tab widgets
    const QObjectList children = tabWidget->children();
    const QObjectList::const_iterator cend = children.constEnd();
    for (QObjectList::const_iterator it = children.constBegin(); it != cend; ++it) {
        QObject *o = *it;
        if (!o->isWidgetType())
            if (QTabWidgetEventFilter *ef = qobject_cast<QTabWidgetEventFilter*>(o))
                return ef;
    }
    return 0;
}

QMenu *QTabWidgetEventFilter::addTabWidgetContextMenuActions(const QTabWidget *tabWidget, QMenu *popup)
{
    QTabWidgetEventFilter *filter = eventFilterOf(tabWidget);
    if (!filter)
        return 0;
    return filter->addContextMenuActions(popup);
}

QTabBar *QTabWidgetEventFilter::tabBar() const
{
    // QTabWidget::tabBar() accessor is protected, grmbl...
    if (!m_cachedTabBar) {
        const QList<QTabBar *> tabBars = qFindChildren<QTabBar *>(m_tabWidget);
        Q_ASSERT(tabBars.size() == 1);
        m_cachedTabBar = tabBars.front();
    }
    return m_cachedTabBar;

}

static bool canMove(const QPoint &pressPoint, const QMouseEvent *e)
{
    const QPoint pt = pressPoint - e->pos();
    return pt.manhattanLength() > QApplication::startDragDistance();
}

bool QTabWidgetEventFilter::eventFilter(QObject *o, QEvent *e)
{
    const QEvent::Type type = e->type();
    // Do not try to locate tab bar and form window, etc. for uninteresting events and
    // avoid asserts about missing tab bars when being destroyed
    switch (type) {
    case QEvent::MouseButtonDblClick:
    case QEvent::MouseButtonPress:
    case QEvent::MouseButtonRelease:
    case QEvent::MouseMove:
    case QEvent::DragLeave:
    case QEvent::DragEnter:
    case QEvent::DragMove:
    case QEvent::Drop:
        break;
    default:
        return false;
    }

    if (o != tabBar())
        return false;

    QDesignerFormWindowInterface *fw = formWindow();
    if (!fw)
        return false;

    switch (type) {
    case QEvent::MouseButtonDblClick:
        break;
    case QEvent::MouseButtonPress: {
        QMouseEvent *mev = static_cast<QMouseEvent*>(e);
        if (QDesignerFormWindowInterface *fw = formWindow()) {
            fw->clearSelection();
            fw->selectWidget(m_tabWidget, true);
        }
        if (mev->button() & Qt::LeftButton) {
            m_mousePressed = true;
            m_pressPoint = mev->pos();

            QTabBar *tabbar = tabBar();
            const int count = tabbar->count();
            for (int i = 0; i < count; ++i) {
                if (tabbar->tabRect(i).contains(m_pressPoint)) {
                    if (i != tabbar->currentIndex()) {
                        qdesigner_internal::SetPropertyCommand *cmd = new qdesigner_internal::SetPropertyCommand(fw);
                        cmd->init(m_tabWidget, QLatin1String("currentIndex"), i);
                        fw->commandHistory()->push(cmd);
                    }
                    break;
                }
            }
        }
    } break;

    case QEvent::MouseButtonRelease:
        m_mousePressed = false;
        break;

    case QEvent::MouseMove: {
        QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(e);
        if (m_mousePressed && canMove(m_pressPoint, mouseEvent)) {
            const int index = m_tabWidget->currentIndex();
            if (index == -1)
                break;

            m_mousePressed = false;
            QDrag *drg = new QDrag(m_tabWidget);
            drg->setMimeData(new qdesigner_internal::MyMimeData(m_tabWidget));

            m_dragIndex = index;
            m_dragPage  = m_tabWidget->currentWidget();
            m_dragLabel = m_tabWidget->tabText(index);
            m_dragIcon  = m_tabWidget->tabIcon(index);
            if (m_dragIcon.isNull()) {
                QLabel *label = new QLabel(m_dragLabel);
                label->adjustSize();
                drg->setPixmap(QPixmap::grabWidget(label));
                label->deleteLater();
            } else {
                drg->setPixmap(m_dragIcon.pixmap(22, 22));
            }

            m_tabWidget->removeTab(m_dragIndex);

            const Qt::DropActions dropAction = drg->start(Qt::MoveAction);

            if (dropAction == Qt::IgnoreAction) {
                // abort
                m_tabWidget->insertTab(m_dragIndex, m_dragPage, m_dragIcon, m_dragLabel);
                m_tabWidget->setCurrentIndex(m_dragIndex);
            }

            if (m_dropIndicator)
                m_dropIndicator->hide();
        }
    } break;

    case QEvent::DragLeave: {
        if (m_dropIndicator)
            m_dropIndicator->hide();
    } break;

    case QEvent::DragEnter:
    case QEvent::DragMove: {
        QDragMoveEvent *de = static_cast<QDragMoveEvent*>(e);
        if (!qdesigner_internal::MyMimeData::fromMyTab(de->mimeData(), m_tabWidget))
            return false;

        if (de->proposedAction() == Qt::MoveAction)
            de->acceptProposedAction();
        else {
            de->setDropAction(Qt::MoveAction);
            de->accept();
        }

        QRect rect;
        const int index = pageFromPosition(de->pos(), rect);

        if (!m_dropIndicator) {
            m_dropIndicator = new QWidget(m_tabWidget);
            QPalette p = m_dropIndicator->palette();
            p.setColor(m_tabWidget->backgroundRole(), Qt::red);
            m_dropIndicator->setPalette(p);
        }

        QPoint pos;
        if (index == m_tabWidget->count())
            pos = tabBar()->mapToParent(QPoint(rect.x() + rect.width(), rect.y()));
        else
            pos = tabBar()->mapToParent(QPoint(rect.x(), rect.y()));

        m_dropIndicator->setGeometry(pos.x(), pos.y() , 3, rect.height());
        m_dropIndicator->show();
    } break;

    case QEvent::Drop: {
        QDropEvent *de = static_cast<QDropEvent*>(e);
        if (!qdesigner_internal::MyMimeData::fromMyTab(de->mimeData(), m_tabWidget))
            return false;
        de->acceptProposedAction();
        de->accept();

        QRect rect;
        const int newIndex = pageFromPosition(de->pos(), rect);

        qdesigner_internal::MoveTabPageCommand *cmd = new qdesigner_internal::MoveTabPageCommand(fw);
        m_tabWidget->insertTab(m_dragIndex, m_dragPage, m_dragIcon, m_dragLabel);
        cmd->init(m_tabWidget, m_dragPage, m_dragIcon, m_dragLabel, m_dragIndex, newIndex);
        fw->commandHistory()->push(cmd);
    } break;

    default:
        break;
    }

    return false;
}

void QTabWidgetEventFilter::removeCurrentPage()
{
    if (!m_tabWidget->currentWidget())
        return;

    if (QDesignerFormWindowInterface *fw = formWindow()) {
        qdesigner_internal::DeleteTabPageCommand *cmd = new qdesigner_internal::DeleteTabPageCommand(fw);
        cmd->init(m_tabWidget);
        fw->commandHistory()->push(cmd);
    }
}

void QTabWidgetEventFilter::addPage()
{
    if (QDesignerFormWindowInterface *fw = formWindow()) {
        qdesigner_internal::AddTabPageCommand *cmd = new qdesigner_internal::AddTabPageCommand(fw);
        cmd->init(m_tabWidget, qdesigner_internal::AddTabPageCommand::InsertBefore);
        fw->commandHistory()->push(cmd);
    }
}

void QTabWidgetEventFilter::addPageAfter()
{
    if (QDesignerFormWindowInterface *fw = formWindow()) {
        qdesigner_internal::AddTabPageCommand *cmd = new qdesigner_internal::AddTabPageCommand(fw);
        cmd->init(m_tabWidget, qdesigner_internal::AddTabPageCommand::InsertAfter);
        fw->commandHistory()->push(cmd);
    }
}

QDesignerFormWindowInterface *QTabWidgetEventFilter::formWindow() const
{
    return QDesignerFormWindowInterface::findFormWindow(const_cast<QTabWidget*>(m_tabWidget));
}

// Get page from mouse position. Default to new page if in right half of last page?
int QTabWidgetEventFilter::pageFromPosition(const QPoint &pos, QRect &rect) const
{
    int index = 0;
    const QTabBar *tabbar = tabBar();
    const int count = m_tabWidget->count();
    for (; index < count; index++) {
        const QRect rc = tabbar->tabRect(index);
        if (rc.contains(pos)) {
            rect = rc;
            break;
        }
    }

    if (index == count -1) {
        QRect rect2 = rect;
        rect2.setLeft(rect2.left() + rect2.width() / 2);
        if (rect2.contains(pos))
            index++;
    }
    return index;
}

QMenu *QTabWidgetEventFilter::addContextMenuActions(QMenu *popup)
{
    QMenu *pageMenu = 0;
    const int count = m_tabWidget->count();
    m_actionDeletePage->setEnabled(count);
    if (count) {
        const int currentIndex = m_tabWidget->currentIndex();
        const QString pageSubMenuLabel = tr("Page %1 of %2").arg(currentIndex + 1).arg(count);
        pageMenu = popup->addMenu(pageSubMenuLabel);
        pageMenu->addAction(m_actionDeletePage);
        // Set up promotion menu for current widget.
        if (QWidget *page =  m_tabWidget->currentWidget ()) {
            m_pagePromotionTaskMenu->setWidget(page);
            m_pagePromotionTaskMenu->addActions(QDesignerFormWindowInterface::findFormWindow(m_tabWidget),
                                                qdesigner_internal::PromotionTaskMenu::SuppressGlobalEdit,
                                                pageMenu);
        }
        QMenu *insertPageMenu = popup->addMenu(tr("Insert Page"));
        insertPageMenu->addAction(m_actionInsertPageAfter);
        insertPageMenu->addAction(m_actionInsertPage);
    } else {
        QAction *insertPageAction = popup->addAction(tr("Insert Page"));
        connect(insertPageAction, SIGNAL(triggered()), this, SLOT(addPage()));
    }
    popup->addSeparator();
    return pageMenu;
}

// ----------- QTabWidgetPropertySheet

static const char *currentTabTextKey = "currentTabText";
static const char *currentTabNameKey = "currentTabName";
static const char *currentTabIconKey = "currentTabIcon";
static const char *currentTabToolTipKey = "currentTabToolTip";
static const char *currentTabWhatsThisKey = "currentTabWhatsThis";
static const char *tabMovableKey = "movable";

QTabWidgetPropertySheet::QTabWidgetPropertySheet(QTabWidget *object, QObject *parent) :
    QDesignerPropertySheet(object, parent),
    m_tabWidget(object)
{
    createFakeProperty(QLatin1String(currentTabTextKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue()));
    createFakeProperty(QLatin1String(currentTabNameKey), QString());
    createFakeProperty(QLatin1String(currentTabIconKey), qVariantFromValue(qdesigner_internal::PropertySheetIconValue()));
    if (formWindowBase())
        formWindowBase()->addReloadableProperty(this, indexOf(QLatin1String(currentTabIconKey)));
    createFakeProperty(QLatin1String(currentTabToolTipKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue()));
    createFakeProperty(QLatin1String(currentTabWhatsThisKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue()));
    // Prevent the tab widget's drag and drop handling from interfering with Designer's
    createFakeProperty(QLatin1String(tabMovableKey), QVariant(false));
}

QTabWidgetPropertySheet::TabWidgetProperty QTabWidgetPropertySheet::tabWidgetPropertyFromName(const QString &name)
{
    typedef QHash<QString, TabWidgetProperty> TabWidgetPropertyHash;
    static TabWidgetPropertyHash tabWidgetPropertyHash;
    if (tabWidgetPropertyHash.empty()) {
        tabWidgetPropertyHash.insert(QLatin1String(currentTabTextKey),      PropertyCurrentTabText);
        tabWidgetPropertyHash.insert(QLatin1String(currentTabNameKey),      PropertyCurrentTabName);
        tabWidgetPropertyHash.insert(QLatin1String(currentTabIconKey),      PropertyCurrentTabIcon);
        tabWidgetPropertyHash.insert(QLatin1String(currentTabToolTipKey),   PropertyCurrentTabToolTip);
        tabWidgetPropertyHash.insert(QLatin1String(currentTabWhatsThisKey), PropertyCurrentTabWhatsThis);
    }
    return tabWidgetPropertyHash.value(name, PropertyTabWidgetNone);
}

void QTabWidgetPropertySheet::setProperty(int index, const QVariant &value)
{
    const TabWidgetProperty tabWidgetProperty = tabWidgetPropertyFromName(propertyName(index));
    if (tabWidgetProperty == PropertyTabWidgetNone) {
        QDesignerPropertySheet::setProperty(index, value);
        return;
    }

    // index-dependent
    const int currentIndex = m_tabWidget->currentIndex();
    QWidget *currentWidget = m_tabWidget->currentWidget();
    if (!currentWidget)
        return;

    switch (tabWidgetProperty) {
    case PropertyCurrentTabText:
        m_tabWidget->setTabText(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value)));
        m_pageToData[currentWidget].text = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value);
        break;
    case PropertyCurrentTabName:
        currentWidget->setObjectName(value.toString());
        break;
    case PropertyCurrentTabIcon:
        m_tabWidget->setTabIcon(currentIndex, qvariant_cast<QIcon>(resolvePropertyValue(index, value)));
        m_pageToData[currentWidget].icon = qVariantValue<qdesigner_internal::PropertySheetIconValue>(value);
        break;
    case PropertyCurrentTabToolTip:
        m_tabWidget->setTabToolTip(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value)));
        m_pageToData[currentWidget].tooltip = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value);
        break;
    case PropertyCurrentTabWhatsThis:
        m_tabWidget->setTabWhatsThis(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value)));
        m_pageToData[currentWidget].whatsthis = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value);
        break;
    case PropertyTabWidgetNone:
        break;
    }
}

bool QTabWidgetPropertySheet::isEnabled(int index) const
{
    if (tabWidgetPropertyFromName(propertyName(index)) == PropertyTabWidgetNone)
        return QDesignerPropertySheet::isEnabled(index);
    return m_tabWidget->currentIndex() != -1;
}

QVariant QTabWidgetPropertySheet::property(int index) const
{
    const TabWidgetProperty tabWidgetProperty = tabWidgetPropertyFromName(propertyName(index));
    if (tabWidgetProperty == PropertyTabWidgetNone)
        return  QDesignerPropertySheet::property(index);

    // index-dependent
    QWidget *currentWidget = m_tabWidget->currentWidget();
    if (!currentWidget) {
        if (tabWidgetProperty == PropertyCurrentTabIcon)
            return qVariantFromValue(qdesigner_internal::PropertySheetIconValue());
        if (tabWidgetProperty == PropertyCurrentTabText)
            return qVariantFromValue(qdesigner_internal::PropertySheetStringValue());
        if (tabWidgetProperty == PropertyCurrentTabToolTip)
            return qVariantFromValue(qdesigner_internal::PropertySheetStringValue());
        if (tabWidgetProperty == PropertyCurrentTabWhatsThis)
            return qVariantFromValue(qdesigner_internal::PropertySheetStringValue());
        return QVariant(QString());
    }

    // index-dependent
    switch (tabWidgetProperty) {
    case PropertyCurrentTabText:
        return qVariantFromValue(m_pageToData.value(currentWidget).text);
    case PropertyCurrentTabName:
        return currentWidget->objectName();
    case PropertyCurrentTabIcon:
        return qVariantFromValue(m_pageToData.value(currentWidget).icon);
    case PropertyCurrentTabToolTip:
        return qVariantFromValue(m_pageToData.value(currentWidget).tooltip);
    case PropertyCurrentTabWhatsThis:
        return qVariantFromValue(m_pageToData.value(currentWidget).whatsthis);
    case PropertyTabWidgetNone:
        break;
    }
    return QVariant();
}

bool QTabWidgetPropertySheet::reset(int index)
{
    const TabWidgetProperty tabWidgetProperty = tabWidgetPropertyFromName(propertyName(index));
    if (tabWidgetProperty == PropertyTabWidgetNone)
        return QDesignerPropertySheet::reset(index);

    // index-dependent
    QWidget *currentWidget = m_tabWidget->currentWidget();
    if (!currentWidget)
        return false;

    // index-dependent
    switch (tabWidgetProperty) {
    case PropertyCurrentTabName:
        setProperty(index, QString());
        break;
    case PropertyCurrentTabToolTip:
        m_pageToData[currentWidget].tooltip = qdesigner_internal::PropertySheetStringValue();
        setProperty(index, QString());
        break;
    case PropertyCurrentTabWhatsThis:
        m_pageToData[currentWidget].whatsthis = qdesigner_internal::PropertySheetStringValue();
        setProperty(index, QString());
        break;
    case PropertyCurrentTabText:
        m_pageToData[currentWidget].text = qdesigner_internal::PropertySheetStringValue();
        setProperty(index, QString());
        break;
    case PropertyCurrentTabIcon:
        m_pageToData[currentWidget].icon = qdesigner_internal::PropertySheetIconValue();
        setProperty(index, QIcon());
        break;
    case PropertyTabWidgetNone:
        break;
    }
    return true;
}

bool QTabWidgetPropertySheet::checkProperty(const QString &propertyName)
{
    switch (tabWidgetPropertyFromName(propertyName)) {
    case PropertyCurrentTabText:
    case PropertyCurrentTabName:
    case PropertyCurrentTabToolTip:
    case PropertyCurrentTabWhatsThis:
    case PropertyCurrentTabIcon:
        return false;
    default:
        break;
    }
    return true;
}

QT_END_NAMESPACE

#include "qdesigner_tabwidget.moc" // required for MyMimeData
