tools/designer/src/lib/shared/qdesigner_stackedbox.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Designer of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qdesigner_stackedbox_p.h"
       
    43 #include "qdesigner_command_p.h"
       
    44 #include "qdesigner_propertycommand_p.h"
       
    45 #include "orderdialog_p.h"
       
    46 #include "promotiontaskmenu_p.h"
       
    47 #include "widgetfactory_p.h"
       
    48 
       
    49 #include <QtDesigner/QDesignerFormWindowInterface>
       
    50 
       
    51 #include <QtGui/QToolButton>
       
    52 #include <QtGui/QAction>
       
    53 #include <QtGui/qevent.h>
       
    54 #include <QtGui/QMenu>
       
    55 #include <QtGui/QStackedWidget>
       
    56 #include <QtCore/QDebug>
       
    57 
       
    58 QT_BEGIN_NAMESPACE
       
    59 
       
    60 static QToolButton *createToolButton(QWidget *parent, Qt::ArrowType at, const QString &name) {
       
    61     QToolButton *rc =  new QToolButton();
       
    62     rc->setAttribute(Qt::WA_NoChildEventsForParent, true);
       
    63     rc->setParent(parent);
       
    64     rc->setObjectName(name);
       
    65     rc->setArrowType(at);
       
    66     rc->setAutoRaise(true);
       
    67     rc->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
       
    68     rc->setFixedSize(QSize(15, 15));
       
    69     return rc;
       
    70 }
       
    71 
       
    72 // ---------------  QStackedWidgetPreviewEventFilter
       
    73 QStackedWidgetPreviewEventFilter::QStackedWidgetPreviewEventFilter(QStackedWidget *parent) :
       
    74     QObject(parent),
       
    75     m_buttonToolTipEnabled(false), // Not on preview
       
    76     m_stackedWidget(parent),
       
    77     m_prev(createToolButton(m_stackedWidget, Qt::LeftArrow,  QLatin1String("__qt__passive_prev"))),
       
    78     m_next(createToolButton(m_stackedWidget, Qt::RightArrow, QLatin1String("__qt__passive_next")))
       
    79 {
       
    80     connect(m_prev, SIGNAL(clicked()), this, SLOT(prevPage()));
       
    81     connect(m_next, SIGNAL(clicked()), this, SLOT(nextPage()));
       
    82 
       
    83     updateButtons();
       
    84     m_stackedWidget->installEventFilter(this);
       
    85     m_prev->installEventFilter(this);
       
    86     m_next->installEventFilter(this);
       
    87 }
       
    88 
       
    89 void QStackedWidgetPreviewEventFilter::install(QStackedWidget *stackedWidget)
       
    90 {
       
    91     new QStackedWidgetPreviewEventFilter(stackedWidget);
       
    92 }
       
    93 
       
    94 void QStackedWidgetPreviewEventFilter::updateButtons()
       
    95 {
       
    96     m_prev->move(m_stackedWidget->width() - 31, 1);
       
    97     m_prev->show();
       
    98     m_prev->raise();
       
    99 
       
   100     m_next->move(m_stackedWidget->width() - 16, 1);
       
   101     m_next->show();
       
   102     m_next->raise();
       
   103 }
       
   104 
       
   105 void QStackedWidgetPreviewEventFilter::prevPage()
       
   106 {
       
   107     if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(stackedWidget())) {
       
   108         fw->clearSelection();
       
   109         fw->selectWidget(stackedWidget(), true);
       
   110     }
       
   111     const int count = m_stackedWidget->count();
       
   112     if (count > 1) {
       
   113         int newIndex = m_stackedWidget->currentIndex() - 1;
       
   114         if (newIndex < 0)
       
   115             newIndex = count - 1;
       
   116         gotoPage(newIndex);
       
   117     }
       
   118 }
       
   119 
       
   120 void QStackedWidgetPreviewEventFilter::nextPage()
       
   121 {
       
   122     if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(stackedWidget())) {
       
   123         fw->clearSelection();
       
   124         fw->selectWidget(stackedWidget(), true);
       
   125     }
       
   126     const int count = m_stackedWidget->count();
       
   127     if (count > 1)
       
   128         gotoPage((m_stackedWidget->currentIndex() + 1) % count);
       
   129 }
       
   130 
       
   131 bool QStackedWidgetPreviewEventFilter::eventFilter(QObject *watched, QEvent *event)
       
   132 {
       
   133     if (watched->isWidgetType()) {
       
   134         if (watched == m_stackedWidget) {
       
   135             switch (event->type()) {
       
   136             case QEvent::LayoutRequest:
       
   137                 updateButtons();
       
   138                 break;
       
   139             case QEvent::ChildAdded:
       
   140             case QEvent::ChildRemoved:
       
   141             case QEvent::Resize:
       
   142             case QEvent::Show:
       
   143                 updateButtons();
       
   144                 break;
       
   145             default:
       
   146                 break;
       
   147             }
       
   148         }
       
   149         if (m_buttonToolTipEnabled && (watched == m_next || watched == m_prev)) {
       
   150             switch (event->type()) {
       
   151             case QEvent::ToolTip:
       
   152                 updateButtonToolTip(watched); // Tooltip includes page number, so, refresh on demand
       
   153                 break;
       
   154             default:
       
   155                 break;
       
   156             }
       
   157         }
       
   158     }
       
   159     return QObject::eventFilter(watched, event);
       
   160 }
       
   161 
       
   162 void QStackedWidgetPreviewEventFilter::gotoPage(int page)
       
   163 {
       
   164     m_stackedWidget->setCurrentIndex(page);
       
   165     updateButtons();
       
   166 }
       
   167 
       
   168 static inline QString stackedClassName(QStackedWidget *w)
       
   169 {
       
   170     if (const QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(w))
       
   171         return qdesigner_internal::WidgetFactory::classNameOf(fw->core(), w);
       
   172     return QLatin1String("Stacked widget");
       
   173 }
       
   174 
       
   175 void QStackedWidgetPreviewEventFilter::updateButtonToolTip(QObject *o)
       
   176 {
       
   177     QString className = QLatin1String("Stacked widget");
       
   178     if (const QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_stackedWidget))
       
   179         className = qdesigner_internal::WidgetFactory::classNameOf(fw->core(), m_stackedWidget);
       
   180     if (o == m_prev) {
       
   181         const QString msg = tr("Go to previous page of %1 '%2' (%3/%4).").arg(stackedClassName(m_stackedWidget)).arg(m_stackedWidget->objectName()).arg(m_stackedWidget->currentIndex() + 1).arg(m_stackedWidget->count());
       
   182         m_prev->setToolTip(msg);
       
   183     } else {
       
   184         if (o == m_next) {
       
   185             const QString msg = tr("Go to next page of %1 '%2' (%3/%4).").arg(stackedClassName(m_stackedWidget)).arg(m_stackedWidget->objectName()).arg(m_stackedWidget->currentIndex() + 1).arg(m_stackedWidget->count());
       
   186             m_next->setToolTip(msg);
       
   187         }
       
   188     }
       
   189 }
       
   190 
       
   191 // ---------------  QStackedWidgetEventFilter
       
   192 QStackedWidgetEventFilter::QStackedWidgetEventFilter(QStackedWidget *parent) :
       
   193     QStackedWidgetPreviewEventFilter(parent),
       
   194     m_actionPreviousPage(new QAction(tr("Previous Page"), this)),
       
   195     m_actionNextPage(new QAction(tr("Next Page"), this)),
       
   196     m_actionDeletePage(new QAction(tr("Delete"), this)),
       
   197     m_actionInsertPage(new QAction(tr("Before Current Page"), this)),
       
   198     m_actionInsertPageAfter(new QAction(tr("After Current Page"), this)),
       
   199     m_actionChangePageOrder(new QAction(tr("Change Page Order..."), this)),
       
   200     m_pagePromotionTaskMenu(new qdesigner_internal::PromotionTaskMenu(0, qdesigner_internal::PromotionTaskMenu::ModeSingleWidget, this))
       
   201 {
       
   202     setButtonToolTipEnabled(true);
       
   203     connect(m_actionPreviousPage, SIGNAL(triggered()), this, SLOT(prevPage()));
       
   204     connect(m_actionNextPage, SIGNAL(triggered()), this, SLOT(nextPage()));
       
   205     connect(m_actionDeletePage, SIGNAL(triggered()), this, SLOT(removeCurrentPage()));
       
   206     connect(m_actionInsertPage, SIGNAL(triggered()), this, SLOT(addPage()));
       
   207     connect(m_actionInsertPageAfter, SIGNAL(triggered()), this, SLOT(addPageAfter()));
       
   208     connect(m_actionChangePageOrder, SIGNAL(triggered()), this, SLOT(changeOrder()));
       
   209 }
       
   210 
       
   211 void QStackedWidgetEventFilter::install(QStackedWidget *stackedWidget)
       
   212 {
       
   213     new QStackedWidgetEventFilter(stackedWidget);
       
   214 }
       
   215 
       
   216 QStackedWidgetEventFilter *QStackedWidgetEventFilter::eventFilterOf(const QStackedWidget *stackedWidget)
       
   217 {
       
   218     // Look for 1st order children only..otherwise, we might get filters of nested widgets
       
   219     const QObjectList children = stackedWidget->children();
       
   220     const QObjectList::const_iterator cend = children.constEnd();
       
   221     for (QObjectList::const_iterator it = children.constBegin(); it != cend; ++it) {
       
   222         QObject *o = *it;
       
   223         if (!o->isWidgetType())
       
   224             if (QStackedWidgetEventFilter *ef = qobject_cast<QStackedWidgetEventFilter *>(o))
       
   225                 return ef;
       
   226     }
       
   227     return 0;
       
   228 }
       
   229 
       
   230 QMenu *QStackedWidgetEventFilter::addStackedWidgetContextMenuActions(const QStackedWidget *stackedWidget, QMenu *popup)
       
   231 {
       
   232     QStackedWidgetEventFilter *filter = eventFilterOf(stackedWidget);
       
   233     if (!filter)
       
   234         return 0;
       
   235     return filter->addContextMenuActions(popup);
       
   236 }
       
   237 
       
   238 void QStackedWidgetEventFilter::removeCurrentPage()
       
   239 {
       
   240     if (stackedWidget()->currentIndex() == -1)
       
   241         return;
       
   242 
       
   243     if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(stackedWidget())) {
       
   244         qdesigner_internal::DeleteStackedWidgetPageCommand *cmd = new qdesigner_internal::DeleteStackedWidgetPageCommand(fw);
       
   245         cmd->init(stackedWidget());
       
   246         fw->commandHistory()->push(cmd);
       
   247     }
       
   248 }
       
   249 
       
   250 void QStackedWidgetEventFilter::changeOrder()
       
   251 {
       
   252     QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(stackedWidget());
       
   253 
       
   254     if (!fw)
       
   255         return;
       
   256 
       
   257     const QWidgetList oldPages = qdesigner_internal::OrderDialog::pagesOfContainer(fw->core(), stackedWidget());
       
   258     const int pageCount = oldPages.size();
       
   259     if (pageCount < 2)
       
   260         return;
       
   261 
       
   262     qdesigner_internal::OrderDialog dlg(fw);
       
   263     dlg.setPageList(oldPages);
       
   264     if (dlg.exec() == QDialog::Rejected)
       
   265         return;
       
   266 
       
   267     const QWidgetList newPages = dlg.pageList();
       
   268     if (newPages == oldPages)
       
   269         return;
       
   270 
       
   271     fw->beginCommand(tr("Change Page Order"));
       
   272     for(int i=0; i < pageCount; ++i) {
       
   273         if (newPages.at(i) == stackedWidget()->widget(i))
       
   274             continue;
       
   275         qdesigner_internal::MoveStackedWidgetCommand *cmd = new qdesigner_internal::MoveStackedWidgetCommand(fw);
       
   276         cmd->init(stackedWidget(), newPages.at(i), i);
       
   277         fw->commandHistory()->push(cmd);
       
   278     }
       
   279     fw->endCommand();
       
   280 }
       
   281 
       
   282 void QStackedWidgetEventFilter::addPage()
       
   283 {
       
   284     if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(stackedWidget())) {
       
   285         qdesigner_internal::AddStackedWidgetPageCommand *cmd = new qdesigner_internal::AddStackedWidgetPageCommand(fw);
       
   286         cmd->init(stackedWidget(), qdesigner_internal::AddStackedWidgetPageCommand::InsertBefore);
       
   287         fw->commandHistory()->push(cmd);
       
   288     }
       
   289 }
       
   290 
       
   291 void QStackedWidgetEventFilter::addPageAfter()
       
   292 {
       
   293     if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(stackedWidget())) {
       
   294         qdesigner_internal::AddStackedWidgetPageCommand *cmd = new qdesigner_internal::AddStackedWidgetPageCommand(fw);
       
   295         cmd->init(stackedWidget(), qdesigner_internal::AddStackedWidgetPageCommand::InsertAfter);
       
   296         fw->commandHistory()->push(cmd);
       
   297     }
       
   298 }
       
   299 
       
   300 void QStackedWidgetEventFilter::gotoPage(int page) {
       
   301     // Are we on a form or in a preview?
       
   302     if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(stackedWidget())) {
       
   303         qdesigner_internal::SetPropertyCommand *cmd = new  qdesigner_internal::SetPropertyCommand(fw);
       
   304         cmd->init(stackedWidget(), QLatin1String("currentIndex"), page);
       
   305         fw->commandHistory()->push(cmd);
       
   306         fw->emitSelectionChanged(); // Magically prevent an endless loop triggered by auto-repeat.
       
   307         updateButtons();
       
   308     } else {
       
   309         QStackedWidgetPreviewEventFilter::gotoPage(page);
       
   310     }
       
   311 }
       
   312 
       
   313 QMenu *QStackedWidgetEventFilter::addContextMenuActions(QMenu *popup)
       
   314 {
       
   315     QMenu *pageMenu = 0;
       
   316     const int count = stackedWidget()->count();
       
   317     const bool hasSeveralPages = count > 1;
       
   318     m_actionDeletePage->setEnabled(count);
       
   319     if (count) {
       
   320         const QString pageSubMenuLabel = tr("Page %1 of %2").arg(stackedWidget()->currentIndex() + 1).arg(count);
       
   321         pageMenu = popup->addMenu(pageSubMenuLabel);
       
   322         pageMenu->addAction(m_actionDeletePage);
       
   323         // Set up promotion menu for current widget.
       
   324         if (QWidget *page =  stackedWidget()->currentWidget ()) {
       
   325             m_pagePromotionTaskMenu->setWidget(page);
       
   326             m_pagePromotionTaskMenu->addActions(QDesignerFormWindowInterface::findFormWindow(stackedWidget()),
       
   327                                                 qdesigner_internal::PromotionTaskMenu::SuppressGlobalEdit,
       
   328                                                 pageMenu);
       
   329         }
       
   330         QMenu *insertPageMenu = popup->addMenu(tr("Insert Page"));
       
   331         insertPageMenu->addAction(m_actionInsertPageAfter);
       
   332         insertPageMenu->addAction(m_actionInsertPage);
       
   333     } else {
       
   334         QAction *insertPageAction = popup->addAction(tr("Insert Page"));
       
   335         connect(insertPageAction, SIGNAL(triggered()), this, SLOT(addPage()));
       
   336     }
       
   337     popup->addAction(m_actionNextPage);
       
   338     m_actionNextPage->setEnabled(hasSeveralPages);
       
   339     popup->addAction(m_actionPreviousPage);
       
   340     m_actionPreviousPage->setEnabled(hasSeveralPages);
       
   341     popup->addAction(m_actionChangePageOrder);
       
   342     m_actionChangePageOrder->setEnabled(hasSeveralPages);
       
   343     popup->addSeparator();
       
   344     return pageMenu;
       
   345 }
       
   346 
       
   347 // --------  QStackedWidgetPropertySheet
       
   348 
       
   349 static const char *pagePropertyName = "currentPageName";
       
   350 
       
   351 QStackedWidgetPropertySheet::QStackedWidgetPropertySheet(QStackedWidget *object, QObject *parent) :
       
   352     QDesignerPropertySheet(object, parent),
       
   353     m_stackedWidget(object)
       
   354 {
       
   355     createFakeProperty(QLatin1String(pagePropertyName), QString());
       
   356 }
       
   357 
       
   358 bool QStackedWidgetPropertySheet::isEnabled(int index) const
       
   359 {
       
   360     if (propertyName(index) != QLatin1String(pagePropertyName))
       
   361         return QDesignerPropertySheet::isEnabled(index);
       
   362     return  m_stackedWidget->currentWidget() != 0;
       
   363 }
       
   364 
       
   365 void QStackedWidgetPropertySheet::setProperty(int index, const QVariant &value)
       
   366 {
       
   367     if (propertyName(index) == QLatin1String(pagePropertyName)) {
       
   368         if (QWidget *w = m_stackedWidget->currentWidget())
       
   369             w->setObjectName(value.toString());
       
   370     } else {
       
   371         QDesignerPropertySheet::setProperty(index, value);
       
   372     }
       
   373 }
       
   374 
       
   375 QVariant QStackedWidgetPropertySheet::property(int index) const
       
   376 {
       
   377     if (propertyName(index) == QLatin1String(pagePropertyName)) {
       
   378         if (const QWidget *w = m_stackedWidget->currentWidget())
       
   379             return w->objectName();
       
   380         return QString();
       
   381     }
       
   382     return QDesignerPropertySheet::property(index);
       
   383 }
       
   384 
       
   385 bool QStackedWidgetPropertySheet::reset(int index)
       
   386 {
       
   387     if (propertyName(index) == QLatin1String(pagePropertyName)) {
       
   388         setProperty(index, QString());
       
   389         return true;
       
   390     }
       
   391     return QDesignerPropertySheet::reset(index);
       
   392 }
       
   393 
       
   394 bool QStackedWidgetPropertySheet::checkProperty(const QString &propertyName)
       
   395 {
       
   396     return propertyName != QLatin1String(pagePropertyName);
       
   397 }
       
   398 
       
   399 QT_END_NAMESPACE