tools/designer/src/lib/shared/qdesigner_toolbox.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_toolbox_p.h"
       
    43 #include "qdesigner_command_p.h"
       
    44 #include "orderdialog_p.h"
       
    45 #include "promotiontaskmenu_p.h"
       
    46 #include "formwindowbase_p.h"
       
    47 
       
    48 #include <QtDesigner/QDesignerFormWindowInterface>
       
    49 
       
    50 #include <QtCore/QEvent>
       
    51 #include <QtGui/QAction>
       
    52 #include <QtGui/QToolBox>
       
    53 #include <QtGui/QMenu>
       
    54 #include <QtGui/QLayout>
       
    55 #include <QtGui/QApplication>
       
    56 #include <QtGui/QContextMenuEvent>
       
    57 #include <QtCore/QHash>
       
    58 
       
    59 QT_BEGIN_NAMESPACE
       
    60 
       
    61 QToolBoxHelper::QToolBoxHelper(QToolBox *toolbox) :
       
    62     QObject(toolbox),
       
    63     m_toolbox(toolbox),
       
    64     m_actionDeletePage(new QAction(tr("Delete Page"), this)),
       
    65     m_actionInsertPage(new QAction(tr("Before Current Page"), this)),
       
    66     m_actionInsertPageAfter(new QAction(tr("After Current Page"), this)),
       
    67     m_actionChangePageOrder(new QAction(tr("Change Page Order..."), this)),
       
    68     m_pagePromotionTaskMenu(new qdesigner_internal::PromotionTaskMenu(0, qdesigner_internal::PromotionTaskMenu::ModeSingleWidget, this))
       
    69 {
       
    70     connect(m_actionDeletePage, SIGNAL(triggered()), this, SLOT(removeCurrentPage()));
       
    71     connect(m_actionInsertPage, SIGNAL(triggered()), this, SLOT(addPage()));
       
    72     connect(m_actionInsertPageAfter, SIGNAL(triggered()), this, SLOT(addPageAfter()));
       
    73     connect(m_actionChangePageOrder, SIGNAL(triggered()), this, SLOT(changeOrder()));
       
    74 
       
    75     m_toolbox->installEventFilter(this);
       
    76 }
       
    77 
       
    78 void QToolBoxHelper::install(QToolBox *toolbox)
       
    79 {
       
    80     new QToolBoxHelper(toolbox);
       
    81 }
       
    82 
       
    83 bool QToolBoxHelper::eventFilter(QObject *watched, QEvent *event)
       
    84 {
       
    85     switch (event->type()) {
       
    86     case QEvent::ChildPolished:
       
    87         // Install on the buttons
       
    88         if (watched == m_toolbox) {
       
    89             QChildEvent *ce = static_cast<QChildEvent *>(event);
       
    90             if (!qstrcmp(ce->child()->metaObject()->className(), "QToolBoxButton"))
       
    91                 ce->child()->installEventFilter(this);
       
    92         }
       
    93         break;
       
    94     case QEvent::ContextMenu:
       
    95         if (watched != m_toolbox) {
       
    96             // An action invoked from the passive interactor (ToolBox button) might
       
    97             // cause its deletion within its event handler, triggering a warning. Re-post
       
    98             // the event to the toolbox.
       
    99             QContextMenuEvent *current = static_cast<QContextMenuEvent *>(event);
       
   100             QContextMenuEvent *copy = new QContextMenuEvent(current->reason(), current->pos(), current-> globalPos(), current->modifiers());
       
   101             QApplication::postEvent(m_toolbox, copy);
       
   102             current->accept();
       
   103             return true;
       
   104         }
       
   105         break;
       
   106     case QEvent::MouseButtonRelease:
       
   107         if (watched != m_toolbox)
       
   108             if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_toolbox)) {
       
   109                 fw->clearSelection();
       
   110                 fw->selectWidget(m_toolbox, true);
       
   111             }
       
   112         break;
       
   113     default:
       
   114         break;
       
   115     }
       
   116     return QObject::eventFilter(watched, event);
       
   117 }
       
   118 
       
   119 QToolBoxHelper *QToolBoxHelper::helperOf(const QToolBox *toolbox)
       
   120 {
       
   121     // Look for 1st order children only..otherwise, we might get filters of nested widgets
       
   122     const QObjectList children = toolbox->children();
       
   123     const QObjectList::const_iterator cend = children.constEnd();
       
   124     for (QObjectList::const_iterator it = children.constBegin(); it != cend; ++it) {
       
   125         QObject *o = *it;
       
   126         if (!o->isWidgetType())
       
   127             if (QToolBoxHelper *h = qobject_cast<QToolBoxHelper *>(o))
       
   128                 return h;
       
   129     }
       
   130     return 0;
       
   131 }
       
   132 
       
   133 QMenu *QToolBoxHelper::addToolBoxContextMenuActions(const QToolBox *toolbox, QMenu *popup)
       
   134 {
       
   135     QToolBoxHelper *helper = helperOf(toolbox);
       
   136     if (!helper)
       
   137         return 0;
       
   138     return helper->addContextMenuActions(popup);
       
   139 }
       
   140 
       
   141 void QToolBoxHelper::removeCurrentPage()
       
   142 {
       
   143     if (m_toolbox->currentIndex() == -1 || !m_toolbox->widget(m_toolbox->currentIndex()))
       
   144         return;
       
   145 
       
   146     if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_toolbox)) {
       
   147         qdesigner_internal::DeleteToolBoxPageCommand *cmd = new qdesigner_internal::DeleteToolBoxPageCommand(fw);
       
   148         cmd->init(m_toolbox);
       
   149         fw->commandHistory()->push(cmd);
       
   150     }
       
   151 }
       
   152 
       
   153 void QToolBoxHelper::addPage()
       
   154 {
       
   155     if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_toolbox)) {
       
   156         qdesigner_internal::AddToolBoxPageCommand *cmd = new qdesigner_internal::AddToolBoxPageCommand(fw);
       
   157         cmd->init(m_toolbox, qdesigner_internal::AddToolBoxPageCommand::InsertBefore);
       
   158         fw->commandHistory()->push(cmd);
       
   159     }
       
   160 }
       
   161 
       
   162 void QToolBoxHelper::changeOrder()
       
   163 {
       
   164     QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_toolbox);
       
   165 
       
   166     if (!fw)
       
   167         return;
       
   168 
       
   169     const QWidgetList oldPages = qdesigner_internal::OrderDialog::pagesOfContainer(fw->core(), m_toolbox);
       
   170     const int pageCount = oldPages.size();
       
   171     if (pageCount < 2)
       
   172         return;
       
   173 
       
   174     qdesigner_internal::OrderDialog dlg(fw);
       
   175     dlg.setPageList(oldPages);
       
   176     if (dlg.exec() == QDialog::Rejected)
       
   177         return;
       
   178 
       
   179     const QWidgetList newPages = dlg.pageList();
       
   180     if (newPages == oldPages)
       
   181         return;
       
   182 
       
   183     fw->beginCommand(tr("Change Page Order"));
       
   184     for(int i=0; i < pageCount; ++i) {
       
   185         if (newPages.at(i) == m_toolbox->widget(i))
       
   186             continue;
       
   187         qdesigner_internal::MoveToolBoxPageCommand *cmd = new qdesigner_internal::MoveToolBoxPageCommand(fw);
       
   188         cmd->init(m_toolbox, newPages.at(i), i);
       
   189         fw->commandHistory()->push(cmd);
       
   190     }
       
   191     fw->endCommand();
       
   192 }
       
   193 
       
   194 void QToolBoxHelper::addPageAfter()
       
   195 {
       
   196     if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_toolbox)) {
       
   197         qdesigner_internal::AddToolBoxPageCommand *cmd = new qdesigner_internal::AddToolBoxPageCommand(fw);
       
   198         cmd->init(m_toolbox, qdesigner_internal::AddToolBoxPageCommand::InsertAfter);
       
   199         fw->commandHistory()->push(cmd);
       
   200     }
       
   201 }
       
   202 
       
   203 QPalette::ColorRole QToolBoxHelper::currentItemBackgroundRole() const
       
   204 {
       
   205     const QWidget *w = m_toolbox->widget(0);
       
   206     if (!w)
       
   207         return  QPalette::Window;
       
   208     return w->backgroundRole();
       
   209 }
       
   210 
       
   211 void QToolBoxHelper::setCurrentItemBackgroundRole(QPalette::ColorRole role)
       
   212 {
       
   213     const int count = m_toolbox->count();
       
   214     for (int i = 0; i < count; ++i) {
       
   215         QWidget *w = m_toolbox->widget(i);
       
   216         w->setBackgroundRole(role);
       
   217         w->update();
       
   218     }
       
   219 }
       
   220 
       
   221 QMenu *QToolBoxHelper::addContextMenuActions(QMenu *popup) const
       
   222 {
       
   223     QMenu *pageMenu = 0;
       
   224     const int count = m_toolbox->count();
       
   225     m_actionDeletePage->setEnabled(count > 1);
       
   226     if (count) {
       
   227         const QString pageSubMenuLabel = tr("Page %1 of %2").arg(m_toolbox->currentIndex() + 1).arg(count);
       
   228         pageMenu = popup->addMenu(pageSubMenuLabel);
       
   229 
       
   230         pageMenu->addAction(m_actionDeletePage);
       
   231         // Set up promotion menu for current widget.
       
   232         if (QWidget *page =  m_toolbox->currentWidget ()) {
       
   233             m_pagePromotionTaskMenu->setWidget(page);
       
   234             m_pagePromotionTaskMenu->addActions(QDesignerFormWindowInterface::findFormWindow(m_toolbox),
       
   235                                                 qdesigner_internal::PromotionTaskMenu::SuppressGlobalEdit,
       
   236                                                 pageMenu);
       
   237         }
       
   238     }
       
   239     QMenu *insertPageMenu = popup->addMenu(tr("Insert Page"));
       
   240     insertPageMenu->addAction(m_actionInsertPageAfter);
       
   241     insertPageMenu->addAction(m_actionInsertPage);
       
   242     if (count > 1) {
       
   243         popup->addAction(m_actionChangePageOrder);
       
   244     }
       
   245     popup->addSeparator();
       
   246     return pageMenu;
       
   247 }
       
   248 
       
   249 // -------- QToolBoxWidgetPropertySheet
       
   250 
       
   251 static const char *currentItemTextKey = "currentItemText";
       
   252 static const char *currentItemNameKey = "currentItemName";
       
   253 static const char *currentItemIconKey = "currentItemIcon";
       
   254 static const char *currentItemToolTipKey = "currentItemToolTip";
       
   255 static const char *tabSpacingKey = "tabSpacing";
       
   256 
       
   257 enum { tabSpacingDefault = -1 };
       
   258 
       
   259 QToolBoxWidgetPropertySheet::QToolBoxWidgetPropertySheet(QToolBox *object, QObject *parent) :
       
   260     QDesignerPropertySheet(object, parent),
       
   261     m_toolBox(object)
       
   262 {
       
   263     createFakeProperty(QLatin1String(currentItemTextKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue()));
       
   264     createFakeProperty(QLatin1String(currentItemNameKey), QString());
       
   265     createFakeProperty(QLatin1String(currentItemIconKey), qVariantFromValue(qdesigner_internal::PropertySheetIconValue()));
       
   266     if (formWindowBase())
       
   267         formWindowBase()->addReloadableProperty(this, indexOf(QLatin1String(currentItemIconKey)));
       
   268     createFakeProperty(QLatin1String(currentItemToolTipKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue()));
       
   269     createFakeProperty(QLatin1String(tabSpacingKey), QVariant(tabSpacingDefault));
       
   270 }
       
   271 
       
   272 QToolBoxWidgetPropertySheet::ToolBoxProperty QToolBoxWidgetPropertySheet::toolBoxPropertyFromName(const QString &name)
       
   273 {
       
   274     typedef QHash<QString, ToolBoxProperty> ToolBoxPropertyHash;
       
   275     static ToolBoxPropertyHash toolBoxPropertyHash;
       
   276     if (toolBoxPropertyHash.empty()) {
       
   277         toolBoxPropertyHash.insert(QLatin1String(currentItemTextKey),    PropertyCurrentItemText);
       
   278         toolBoxPropertyHash.insert(QLatin1String(currentItemNameKey),    PropertyCurrentItemName);
       
   279         toolBoxPropertyHash.insert(QLatin1String(currentItemIconKey),    PropertyCurrentItemIcon);
       
   280         toolBoxPropertyHash.insert(QLatin1String(currentItemToolTipKey), PropertyCurrentItemToolTip);
       
   281         toolBoxPropertyHash.insert(QLatin1String(tabSpacingKey),         PropertyTabSpacing);
       
   282     }
       
   283     return toolBoxPropertyHash.value(name, PropertyToolBoxNone);
       
   284 }
       
   285 
       
   286 void QToolBoxWidgetPropertySheet::setProperty(int index, const QVariant &value)
       
   287 {
       
   288     const ToolBoxProperty toolBoxProperty = toolBoxPropertyFromName(propertyName(index));
       
   289     // independent of index
       
   290     switch (toolBoxProperty) {
       
   291     case PropertyTabSpacing:
       
   292         m_toolBox->layout()->setSpacing(value.toInt());
       
   293         return;
       
   294     case PropertyToolBoxNone:
       
   295         QDesignerPropertySheet::setProperty(index, value);
       
   296         return;
       
   297     default:
       
   298         break;
       
   299     }
       
   300     // index-dependent
       
   301     const int currentIndex = m_toolBox->currentIndex();
       
   302     QWidget *currentWidget = m_toolBox->currentWidget();
       
   303     if (!currentWidget)
       
   304         return;
       
   305 
       
   306     switch (toolBoxProperty) {
       
   307     case PropertyCurrentItemText:
       
   308         m_toolBox->setItemText(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value)));
       
   309         m_pageToData[currentWidget].text = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value);
       
   310         break;
       
   311     case PropertyCurrentItemName:
       
   312         currentWidget->setObjectName(value.toString());
       
   313         break;
       
   314     case PropertyCurrentItemIcon:
       
   315         m_toolBox->setItemIcon(currentIndex, qvariant_cast<QIcon>(resolvePropertyValue(index, value)));
       
   316         m_pageToData[currentWidget].icon = qVariantValue<qdesigner_internal::PropertySheetIconValue>(value);
       
   317         break;
       
   318     case PropertyCurrentItemToolTip:
       
   319         m_toolBox->setItemToolTip(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value)));
       
   320         m_pageToData[currentWidget].tooltip = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value);
       
   321         break;
       
   322     case PropertyTabSpacing:
       
   323     case PropertyToolBoxNone:
       
   324         break;
       
   325     }
       
   326 }
       
   327 
       
   328 bool QToolBoxWidgetPropertySheet::isEnabled(int index) const
       
   329 {
       
   330     switch (toolBoxPropertyFromName(propertyName(index))) {
       
   331     case PropertyToolBoxNone:  // independent of index
       
   332     case PropertyTabSpacing:
       
   333         return QDesignerPropertySheet::isEnabled(index);
       
   334     default:
       
   335         break;
       
   336     }
       
   337     return m_toolBox->currentIndex() != -1;
       
   338 }
       
   339 
       
   340 QVariant QToolBoxWidgetPropertySheet::property(int index) const
       
   341 {
       
   342     const ToolBoxProperty toolBoxProperty = toolBoxPropertyFromName(propertyName(index));
       
   343     // independent of index
       
   344     switch (toolBoxProperty) {
       
   345     case PropertyTabSpacing:
       
   346         return m_toolBox->layout()->spacing();
       
   347     case PropertyToolBoxNone:
       
   348         return QDesignerPropertySheet::property(index);
       
   349     default:
       
   350         break;
       
   351     }
       
   352     // index-dependent
       
   353     QWidget *currentWidget = m_toolBox->currentWidget();
       
   354     if (!currentWidget) {
       
   355         if (toolBoxProperty == PropertyCurrentItemIcon)
       
   356             return  qVariantFromValue(qdesigner_internal::PropertySheetIconValue());
       
   357         if (toolBoxProperty == PropertyCurrentItemText)
       
   358             return  qVariantFromValue(qdesigner_internal::PropertySheetStringValue());
       
   359         if (toolBoxProperty == PropertyCurrentItemToolTip)
       
   360             return  qVariantFromValue(qdesigner_internal::PropertySheetStringValue());
       
   361         return QVariant(QString());
       
   362     }
       
   363 
       
   364     // index-dependent
       
   365     switch (toolBoxProperty) {
       
   366     case PropertyCurrentItemText:
       
   367         return qVariantFromValue(m_pageToData.value(currentWidget).text);
       
   368     case PropertyCurrentItemName:
       
   369         return currentWidget->objectName();
       
   370     case PropertyCurrentItemIcon:
       
   371         return qVariantFromValue(m_pageToData.value(currentWidget).icon);
       
   372     case PropertyCurrentItemToolTip:
       
   373         return qVariantFromValue(m_pageToData.value(currentWidget).tooltip);
       
   374     case PropertyTabSpacing:
       
   375     case PropertyToolBoxNone:
       
   376         break;
       
   377     }
       
   378     return QVariant();
       
   379 }
       
   380 
       
   381 bool QToolBoxWidgetPropertySheet::reset(int index)
       
   382 {
       
   383     const ToolBoxProperty toolBoxProperty = toolBoxPropertyFromName(propertyName(index));
       
   384     // independent of index
       
   385     switch (toolBoxProperty) {
       
   386     case PropertyTabSpacing:
       
   387         setProperty(index, QVariant(tabSpacingDefault));
       
   388         return true;
       
   389     case PropertyToolBoxNone:
       
   390         return QDesignerPropertySheet::reset(index);
       
   391     default:
       
   392         break;
       
   393     }
       
   394     // index-dependent
       
   395     QWidget *currentWidget = m_toolBox->currentWidget();
       
   396     if (!currentWidget)
       
   397         return false;
       
   398 
       
   399     // index-dependent
       
   400     switch (toolBoxProperty) {
       
   401     case PropertyCurrentItemName:
       
   402         setProperty(index, QString());
       
   403         break;
       
   404     case PropertyCurrentItemToolTip:
       
   405         m_pageToData[currentWidget].tooltip = qdesigner_internal::PropertySheetStringValue();
       
   406         setProperty(index, QString());
       
   407         break;
       
   408     case PropertyCurrentItemText:
       
   409         m_pageToData[currentWidget].text = qdesigner_internal::PropertySheetStringValue();
       
   410         setProperty(index, QString());
       
   411         break;
       
   412     case PropertyCurrentItemIcon:
       
   413         m_pageToData[currentWidget].icon = qdesigner_internal::PropertySheetIconValue();
       
   414         setProperty(index, QIcon());
       
   415         break;
       
   416     case PropertyTabSpacing:
       
   417     case PropertyToolBoxNone:
       
   418         break;
       
   419     }
       
   420     return true;
       
   421 }
       
   422 
       
   423 bool QToolBoxWidgetPropertySheet::checkProperty(const QString &propertyName)
       
   424 {
       
   425     switch (toolBoxPropertyFromName(propertyName)) {
       
   426     case PropertyCurrentItemText:
       
   427     case PropertyCurrentItemName:
       
   428     case PropertyCurrentItemToolTip:
       
   429     case PropertyCurrentItemIcon:
       
   430         return false;
       
   431     default:
       
   432         break;
       
   433     }
       
   434     return true;
       
   435 }
       
   436 
       
   437 QT_END_NAMESPACE