tools/designer/src/lib/shared/formwindowbase.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 "formwindowbase_p.h"
       
    43 #include "connectionedit_p.h"
       
    44 #include "qdesigner_command_p.h"
       
    45 #include "qdesigner_propertysheet_p.h"
       
    46 #include "qdesigner_propertyeditor_p.h"
       
    47 #include "qdesigner_menu_p.h"
       
    48 #include "qdesigner_menubar_p.h"
       
    49 #include "shared_settings_p.h"
       
    50 #include "grid_p.h" 
       
    51 #include "deviceprofile_p.h"
       
    52 #include "qdesigner_utils_p.h"
       
    53 
       
    54 #include "qsimpleresource_p.h"
       
    55 
       
    56 #include <QtDesigner/QDesignerFormEditorInterface>
       
    57 #include <QtDesigner/QDesignerContainerExtension>
       
    58 #include <QtDesigner/QExtensionManager>
       
    59 #include <QtDesigner/QDesignerTaskMenuExtension>
       
    60 
       
    61 #include <QtCore/qdebug.h>
       
    62 #include <QtCore/QList>
       
    63 #include <QtCore/QTimer>
       
    64 #include <QtGui/QMenu>
       
    65 #include <QtGui/QListWidget>
       
    66 #include <QtGui/QTreeWidget>
       
    67 #include <QtGui/QTableWidget>
       
    68 #include <QtGui/QComboBox>
       
    69 #include <QtGui/QTabWidget>
       
    70 #include <QtGui/QToolBox>
       
    71 #include <QtGui/QToolBar>
       
    72 #include <QtGui/QStatusBar>
       
    73 #include <QtGui/QMenu>
       
    74 #include <QtGui/QAction>
       
    75 
       
    76 QT_BEGIN_NAMESPACE
       
    77 
       
    78 namespace qdesigner_internal {
       
    79 
       
    80 class FormWindowBasePrivate {
       
    81 public:
       
    82     explicit FormWindowBasePrivate(QDesignerFormEditorInterface *core);
       
    83 
       
    84     static Grid m_defaultGrid;
       
    85 
       
    86     QDesignerFormWindowInterface::Feature m_feature;
       
    87     Grid m_grid;
       
    88     bool m_hasFormGrid;
       
    89     DesignerPixmapCache *m_pixmapCache;
       
    90     DesignerIconCache *m_iconCache;
       
    91     QtResourceSet *m_resourceSet;
       
    92     QMap<QDesignerPropertySheet *, QMap<int, bool> > m_reloadableResources; // bool is dummy, QMap used as QSet
       
    93     QMap<QDesignerPropertySheet *, QObject *> m_reloadablePropertySheets;
       
    94     const DeviceProfile m_deviceProfile;
       
    95     FormWindowBase::LineTerminatorMode m_lineTerminatorMode;
       
    96     FormWindowBase::SaveResourcesBehaviour m_saveResourcesBehaviour;
       
    97 };
       
    98 
       
    99 FormWindowBasePrivate::FormWindowBasePrivate(QDesignerFormEditorInterface *core) :
       
   100     m_feature(QDesignerFormWindowInterface::DefaultFeature),
       
   101     m_grid(m_defaultGrid),
       
   102     m_hasFormGrid(false),
       
   103     m_pixmapCache(0),
       
   104     m_iconCache(0),
       
   105     m_resourceSet(0),
       
   106     m_deviceProfile(QDesignerSharedSettings(core).currentDeviceProfile()),
       
   107     m_lineTerminatorMode(FormWindowBase::NativeLineTerminator),
       
   108     m_saveResourcesBehaviour(FormWindowBase::SaveAll)
       
   109 {
       
   110 }
       
   111 
       
   112 Grid FormWindowBasePrivate::m_defaultGrid;
       
   113 
       
   114 FormWindowBase::FormWindowBase(QDesignerFormEditorInterface *core, QWidget *parent, Qt::WindowFlags flags) :
       
   115     QDesignerFormWindowInterface(parent, flags),
       
   116     m_d(new FormWindowBasePrivate(core))
       
   117 {
       
   118     syncGridFeature();
       
   119     m_d->m_pixmapCache = new DesignerPixmapCache(this);
       
   120     m_d->m_iconCache = new DesignerIconCache(m_d->m_pixmapCache, this);
       
   121 }
       
   122 
       
   123 FormWindowBase::~FormWindowBase()
       
   124 {
       
   125     delete m_d;
       
   126 }
       
   127 
       
   128 DesignerPixmapCache *FormWindowBase::pixmapCache() const
       
   129 {
       
   130     return m_d->m_pixmapCache;
       
   131 }
       
   132 
       
   133 DesignerIconCache *FormWindowBase::iconCache() const
       
   134 {
       
   135     return m_d->m_iconCache;
       
   136 }
       
   137 
       
   138 QtResourceSet *FormWindowBase::resourceSet() const
       
   139 {
       
   140     return m_d->m_resourceSet;
       
   141 }
       
   142 
       
   143 void FormWindowBase::setResourceSet(QtResourceSet *resourceSet)
       
   144 {
       
   145     m_d->m_resourceSet = resourceSet;
       
   146 }
       
   147 
       
   148 void FormWindowBase::addReloadableProperty(QDesignerPropertySheet *sheet, int index)
       
   149 {
       
   150     m_d->m_reloadableResources[sheet][index] = true;
       
   151 }
       
   152 
       
   153 void FormWindowBase::removeReloadableProperty(QDesignerPropertySheet *sheet, int index)
       
   154 {
       
   155     m_d->m_reloadableResources[sheet].remove(index);
       
   156     if (m_d->m_reloadableResources[sheet].count() == 0)
       
   157         m_d->m_reloadableResources.remove(sheet);
       
   158 }
       
   159 
       
   160 void FormWindowBase::addReloadablePropertySheet(QDesignerPropertySheet *sheet, QObject *object)
       
   161 {
       
   162     if (qobject_cast<QTreeWidget *>(object) ||
       
   163             qobject_cast<QTableWidget *>(object) ||
       
   164             qobject_cast<QListWidget *>(object) ||
       
   165             qobject_cast<QComboBox *>(object))
       
   166         m_d->m_reloadablePropertySheets[sheet] = object;
       
   167 }
       
   168 
       
   169 void FormWindowBase::removeReloadablePropertySheet(QDesignerPropertySheet *sheet)
       
   170 {
       
   171     m_d->m_reloadablePropertySheets.remove(sheet);
       
   172 }
       
   173 
       
   174 void FormWindowBase::reloadProperties()
       
   175 {
       
   176     pixmapCache()->clear();
       
   177     iconCache()->clear();
       
   178     QMapIterator<QDesignerPropertySheet *, QMap<int, bool> > itSheet(m_d->m_reloadableResources);
       
   179     while (itSheet.hasNext()) {
       
   180         QDesignerPropertySheet *sheet = itSheet.next().key();
       
   181         QMapIterator<int, bool> itIndex(itSheet.value());
       
   182         while (itIndex.hasNext()) {
       
   183             const int index = itIndex.next().key();
       
   184             sheet->setProperty(index, sheet->property(index));
       
   185         }
       
   186         if (QTabWidget *tabWidget = qobject_cast<QTabWidget *>(sheet->object())) {
       
   187             const int count = tabWidget->count();
       
   188             const int current = tabWidget->currentIndex();
       
   189             const QString currentTabIcon = QLatin1String("currentTabIcon");
       
   190             for (int i = 0; i < count; i++) {
       
   191                 tabWidget->setCurrentIndex(i);
       
   192                 const int index = sheet->indexOf(currentTabIcon);
       
   193                 sheet->setProperty(index, sheet->property(index));
       
   194             }
       
   195             tabWidget->setCurrentIndex(current);
       
   196         } else if (QToolBox *toolBox = qobject_cast<QToolBox *>(sheet->object())) {
       
   197             const int count = toolBox->count();
       
   198             const int current = toolBox->currentIndex();
       
   199             const QString currentItemIcon = QLatin1String("currentItemIcon");
       
   200             for (int i = 0; i < count; i++) {
       
   201                 toolBox->setCurrentIndex(i);
       
   202                 const int index = sheet->indexOf(currentItemIcon);
       
   203                 sheet->setProperty(index, sheet->property(index));
       
   204             }
       
   205             toolBox->setCurrentIndex(current);
       
   206         }
       
   207     }
       
   208     QMapIterator<QDesignerPropertySheet *, QObject *> itSh(m_d->m_reloadablePropertySheets);
       
   209     while (itSh.hasNext()) {
       
   210         QObject *object = itSh.next().value();
       
   211         reloadIconResources(iconCache(), object);
       
   212     }
       
   213 }
       
   214 
       
   215 void FormWindowBase::resourceSetActivated(QtResourceSet *resource, bool resourceSetChanged)
       
   216 {
       
   217     if (resource == resourceSet() && resourceSetChanged) {
       
   218         reloadProperties();
       
   219         emit pixmapCache()->reloaded();
       
   220         emit iconCache()->reloaded();
       
   221         if (QDesignerPropertyEditor *propertyEditor = qobject_cast<QDesignerPropertyEditor *>(core()->propertyEditor()))
       
   222             propertyEditor->reloadResourceProperties();
       
   223     }
       
   224 }
       
   225 
       
   226 QVariantMap FormWindowBase::formData()
       
   227 {
       
   228     QVariantMap rc;
       
   229     if (m_d->m_hasFormGrid)
       
   230         m_d->m_grid.addToVariantMap(rc, true);
       
   231     return rc;
       
   232 }
       
   233 
       
   234 void FormWindowBase::setFormData(const QVariantMap &vm)
       
   235 {
       
   236     Grid formGrid;
       
   237     m_d->m_hasFormGrid = formGrid.fromVariantMap(vm);
       
   238     if (m_d->m_hasFormGrid)
       
   239          m_d->m_grid = formGrid;
       
   240 }
       
   241 
       
   242 QPoint FormWindowBase::grid() const
       
   243 {
       
   244     return QPoint(m_d->m_grid.deltaX(), m_d->m_grid.deltaY());
       
   245 }
       
   246 
       
   247 void FormWindowBase::setGrid(const QPoint &grid)
       
   248 {
       
   249     m_d->m_grid.setDeltaX(grid.x());
       
   250     m_d->m_grid.setDeltaY(grid.y());
       
   251 }
       
   252 
       
   253 bool FormWindowBase::hasFeature(Feature f) const
       
   254 {
       
   255     return f & m_d->m_feature;
       
   256 }
       
   257 
       
   258 static void recursiveUpdate(QWidget *w)
       
   259 {
       
   260     w->update();
       
   261 
       
   262     const QObjectList &l = w->children();
       
   263     const QObjectList::const_iterator cend = l.constEnd();
       
   264     for (QObjectList::const_iterator it = l.constBegin(); it != cend; ++it) {
       
   265         if (QWidget *w = qobject_cast<QWidget*>(*it))
       
   266             recursiveUpdate(w);
       
   267     }
       
   268 }
       
   269 
       
   270 void FormWindowBase::setFeatures(Feature f)
       
   271 {
       
   272     m_d->m_feature = f;
       
   273     const bool enableGrid = f & GridFeature;
       
   274     m_d->m_grid.setVisible(enableGrid);
       
   275     m_d->m_grid.setSnapX(enableGrid);
       
   276     m_d->m_grid.setSnapY(enableGrid);
       
   277     emit featureChanged(f);
       
   278     recursiveUpdate(this);
       
   279 }
       
   280 
       
   281 FormWindowBase::Feature FormWindowBase::features() const
       
   282 {
       
   283     return m_d->m_feature;
       
   284 }
       
   285 
       
   286 bool FormWindowBase::gridVisible() const
       
   287 {
       
   288     return m_d->m_grid.visible() && currentTool() == 0;
       
   289 }
       
   290 
       
   291 FormWindowBase::SaveResourcesBehaviour FormWindowBase::saveResourcesBehaviour() const
       
   292 {
       
   293     return m_d->m_saveResourcesBehaviour;
       
   294 }
       
   295 
       
   296 void FormWindowBase::setSaveResourcesBehaviour(SaveResourcesBehaviour behaviour)
       
   297 {
       
   298     m_d->m_saveResourcesBehaviour = behaviour;
       
   299 }
       
   300 
       
   301 void FormWindowBase::syncGridFeature()
       
   302 {
       
   303     if (m_d->m_grid.snapX() || m_d->m_grid.snapY())
       
   304         m_d->m_feature |= GridFeature;
       
   305     else
       
   306         m_d->m_feature &= ~GridFeature;
       
   307 }
       
   308 
       
   309 void FormWindowBase::setDesignerGrid(const  Grid& grid)
       
   310 {
       
   311     m_d->m_grid = grid;
       
   312     syncGridFeature();
       
   313     recursiveUpdate(this);
       
   314 }
       
   315 
       
   316 const Grid &FormWindowBase::designerGrid() const
       
   317 {
       
   318     return m_d->m_grid;
       
   319 }
       
   320 
       
   321 bool FormWindowBase::hasFormGrid() const
       
   322 {
       
   323     return m_d->m_hasFormGrid;
       
   324 }
       
   325 
       
   326 void FormWindowBase::setHasFormGrid(bool b)
       
   327 {
       
   328     m_d->m_hasFormGrid = b;
       
   329 }
       
   330 
       
   331 void FormWindowBase::setDefaultDesignerGrid(const Grid& grid)
       
   332 {
       
   333     FormWindowBasePrivate::m_defaultGrid = grid;
       
   334 }
       
   335 
       
   336 const Grid &FormWindowBase::defaultDesignerGrid()
       
   337 {
       
   338     return FormWindowBasePrivate::m_defaultGrid;
       
   339 }
       
   340 
       
   341 QMenu *FormWindowBase::initializePopupMenu(QWidget * /*managedWidget*/)
       
   342 {
       
   343     return 0;
       
   344 }
       
   345 
       
   346 // Widget under mouse for finding the Widget to highlight
       
   347 // when doing DnD. Restricts to pages by geometry if a container with
       
   348 // a container extension (or one of its helper widgets) is hit; otherwise
       
   349 // returns the widget as such (be it managed/unmanaged)
       
   350 
       
   351 QWidget *FormWindowBase::widgetUnderMouse(const QPoint &formPos, WidgetUnderMouseMode /* wum */)
       
   352 {
       
   353     // widget_under_mouse might be some temporary thing like the dropLine. We need
       
   354     // the actual widget that's part of the edited GUI.
       
   355     QWidget *rc = widgetAt(formPos);
       
   356     if (!rc || qobject_cast<ConnectionEdit*>(rc))
       
   357         return 0;
       
   358 
       
   359     if (rc == mainContainer()) {
       
   360         // Refuse main container areas if the main container has a container extension,
       
   361         // for example when hitting QToolBox/QTabWidget empty areas.
       
   362         if (qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), rc))
       
   363             return 0;
       
   364         return rc;
       
   365     }
       
   366 
       
   367     // If we hit on container extension type container, make sure
       
   368     // we use the top-most current page
       
   369     if (QWidget *container = findContainer(rc, false))
       
   370         if (QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), container)) {
       
   371             // For container that do not have a "stacked" nature (QToolBox, QMdiArea),
       
   372             // make sure the position is within the current page
       
   373             const int ci = c->currentIndex();
       
   374             if (ci < 0)
       
   375                 return 0;
       
   376             QWidget *page = c->widget(ci);
       
   377             QRect pageGeometry = page->geometry();
       
   378             pageGeometry.moveTo(page->mapTo(this, pageGeometry.topLeft()));
       
   379             if (!pageGeometry.contains(formPos))
       
   380                 return 0;
       
   381             return page;
       
   382         }
       
   383 
       
   384     return rc;
       
   385 }
       
   386 
       
   387 void FormWindowBase::deleteWidgetList(const QWidgetList &widget_list)
       
   388 {
       
   389     // We need a macro here even for single widgets because the some components (for example,
       
   390     // the signal slot editor are connected to widgetRemoved() and add their
       
   391     // own commands (for example, to delete w's connections)
       
   392     const QString description = widget_list.size() == 1 ?
       
   393         tr("Delete '%1'").arg(widget_list.front()->objectName()) : tr("Delete");
       
   394 
       
   395     commandHistory()->beginMacro(description);
       
   396     foreach (QWidget *w, widget_list) {
       
   397         emit widgetRemoved(w);
       
   398         DeleteWidgetCommand *cmd = new DeleteWidgetCommand(this);
       
   399         cmd->init(w);
       
   400         commandHistory()->push(cmd);
       
   401     }
       
   402     commandHistory()->endMacro();
       
   403 }
       
   404 
       
   405 QMenu *FormWindowBase::createExtensionTaskMenu(QDesignerFormWindowInterface *fw, QObject *o, bool trailingSeparator)
       
   406 {
       
   407     typedef QList<QAction *> ActionList;
       
   408     ActionList actions;
       
   409     // 1) Standard public extension
       
   410     QExtensionManager *em = fw->core()->extensionManager();
       
   411     if (const QDesignerTaskMenuExtension *extTaskMenu = qt_extension<QDesignerTaskMenuExtension*>(em, o))
       
   412         actions += extTaskMenu->taskActions();
       
   413     if (const QDesignerTaskMenuExtension *intTaskMenu = qobject_cast<QDesignerTaskMenuExtension *>(em->extension(o, QLatin1String("QDesignerInternalTaskMenuExtension")))) {
       
   414         if (!actions.empty()) {
       
   415             QAction *a = new QAction(fw);
       
   416             a->setSeparator(true);
       
   417             actions.push_back(a);
       
   418         }
       
   419         actions += intTaskMenu->taskActions();
       
   420     }
       
   421     if (actions.empty())
       
   422         return 0;
       
   423     if (trailingSeparator && !actions.back()->isSeparator()) {
       
   424         QAction *a  = new QAction(fw);
       
   425         a->setSeparator(true);
       
   426         actions.push_back(a);
       
   427     }
       
   428     QMenu *rc = new QMenu;
       
   429     const ActionList::const_iterator cend = actions.constEnd();
       
   430     for (ActionList::const_iterator it = actions.constBegin(); it != cend; ++it)
       
   431         rc->addAction(*it);
       
   432     return rc;
       
   433 }
       
   434 
       
   435 void FormWindowBase::emitObjectRemoved(QObject *o)
       
   436 {
       
   437     emit objectRemoved(o);
       
   438 }
       
   439 
       
   440 DeviceProfile FormWindowBase::deviceProfile() const
       
   441 {
       
   442     return m_d->m_deviceProfile;
       
   443 }
       
   444 
       
   445 QString FormWindowBase::styleName() const
       
   446 {
       
   447     return m_d->m_deviceProfile.isEmpty() ? QString() : m_d->m_deviceProfile.style();
       
   448 }
       
   449 
       
   450 void FormWindowBase::emitWidgetRemoved(QWidget *w)
       
   451 {
       
   452     emit widgetRemoved(w);
       
   453 }
       
   454 
       
   455 QString FormWindowBase::deviceProfileName() const
       
   456 {
       
   457     return m_d->m_deviceProfile.isEmpty() ? QString() : m_d->m_deviceProfile.name();
       
   458 }
       
   459 
       
   460 void FormWindowBase::setLineTerminatorMode(FormWindowBase::LineTerminatorMode mode)
       
   461 {
       
   462     m_d->m_lineTerminatorMode = mode;
       
   463 }
       
   464 
       
   465 FormWindowBase::LineTerminatorMode FormWindowBase::lineTerminatorMode() const
       
   466 {
       
   467     return m_d->m_lineTerminatorMode;
       
   468 }
       
   469 
       
   470 void FormWindowBase::triggerDefaultAction(QWidget *widget)
       
   471 {
       
   472     if (QAction *action = qdesigner_internal::preferredEditAction(core(), widget))
       
   473         QTimer::singleShot(0, action, SIGNAL(triggered()));
       
   474 }
       
   475 
       
   476 void FormWindowBase::setupDefaultAction(QDesignerFormWindowInterface *fw)
       
   477 {
       
   478     QObject::connect(fw, SIGNAL(activated(QWidget*)), fw, SLOT(triggerDefaultAction(QWidget*)));
       
   479 }
       
   480 
       
   481 QString FormWindowBase::fileContents() const
       
   482 {
       
   483     const bool oldValue = QSimpleResource::setWarningsEnabled(false);
       
   484     const QString rc = contents();
       
   485     QSimpleResource::setWarningsEnabled(oldValue);
       
   486     return rc;
       
   487 }
       
   488 
       
   489 } // namespace qdesigner_internal
       
   490 
       
   491 QT_END_NAMESPACE