diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:34:13 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:34:13 (GMT) |
commit | 67ad0519fd165acee4a4d2a94fa502e9e4847bd0 (patch) | |
tree | 1dbf50b3dff8d5ca7e9344733968c72704eb15ff /tools/designer/src/components/formeditor | |
download | Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.zip Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.gz Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.bz2 |
Long live Qt!
Diffstat (limited to 'tools/designer/src/components/formeditor')
237 files changed, 17830 insertions, 0 deletions
diff --git a/tools/designer/src/components/formeditor/brushmanagerproxy.cpp b/tools/designer/src/components/formeditor/brushmanagerproxy.cpp new file mode 100644 index 0000000..b1c056e --- /dev/null +++ b/tools/designer/src/components/formeditor/brushmanagerproxy.cpp @@ -0,0 +1,305 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtbrushmanager.h" +#include "brushmanagerproxy.h" +#include "qsimpleresource_p.h" +#include "qdesigner_utils_p.h" +#include "ui4_p.h" + +#include <QtXml/QXmlStreamWriter> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +class BrushManagerProxyPrivate +{ + BrushManagerProxy *q_ptr; + Q_DECLARE_PUBLIC(BrushManagerProxy) + +public: + BrushManagerProxyPrivate(BrushManagerProxy *bp, QDesignerFormEditorInterface *core); + void brushAdded(const QString &name, const QBrush &brush); + void brushRemoved(const QString &name); + QString uniqueBrushFileName(const QString &brushName) const; + + QtBrushManager *m_Manager; + QString m_designerFolder; + const QString m_BrushFolder; + QString m_BrushPath; + QDesignerFormEditorInterface *m_Core; + QMap<QString, QString> m_FileToBrush; + QMap<QString, QString> m_BrushToFile; +}; + +BrushManagerProxyPrivate::BrushManagerProxyPrivate(BrushManagerProxy *bp, QDesignerFormEditorInterface *core) : + q_ptr(bp), + m_Manager(0), + m_BrushFolder(QLatin1String("brushes")), + m_Core(core) +{ + m_designerFolder = QDir::homePath(); + m_designerFolder += QDir::separator(); + m_designerFolder += QLatin1String(".designer"); + m_BrushPath = m_designerFolder; + m_BrushPath += QDir::separator(); + m_BrushPath += m_BrushFolder; +} +} // namespace qdesigner_internal + +using namespace qdesigner_internal; + +void BrushManagerProxyPrivate::brushAdded(const QString &name, const QBrush &brush) +{ + const QString filename = uniqueBrushFileName(name); + + QDir designerDir(m_designerFolder); + if (!designerDir.exists(m_BrushFolder)) + designerDir.mkdir(m_BrushFolder); + + QFile file(m_BrushPath + QDir::separator() +filename); + if (file.open(QIODevice::WriteOnly)) { + QSimpleResource resource(m_Core); + + DomBrush *dom = resource.saveBrush(brush); + + QXmlStreamWriter writer(&file); + writer.setAutoFormatting(true); + writer.setAutoFormattingIndent(1); + writer.writeStartDocument(); + writer.writeStartElement(QLatin1String("description")); + writer.writeAttribute(QLatin1String("name"), name); + dom->write(writer); + writer.writeEndElement(); + writer.writeEndDocument(); + + delete dom; + file.close(); + + m_FileToBrush[filename] = name; + m_BrushToFile[name] = filename; + } +} + +void BrushManagerProxyPrivate::brushRemoved(const QString &name) +{ + QDir brushDir(m_BrushPath); + + QString filename = m_BrushToFile[name]; + brushDir.remove(filename); + m_BrushToFile.remove(name); + m_FileToBrush.remove(filename); +} + +QString BrushManagerProxyPrivate::uniqueBrushFileName(const QString &brushName) const +{ + const QString extension = QLatin1String(".br"); + QString filename = brushName.toLower(); + filename += extension; + int i = 0; + while (m_FileToBrush.contains(filename)) { + filename = brushName.toLower(); + filename += QString::number(++i); + filename += extension; + } + return filename; +} + + +BrushManagerProxy::BrushManagerProxy(QDesignerFormEditorInterface *core, QObject *parent) + : QObject(parent) +{ + d_ptr = new BrushManagerProxyPrivate(this, core); +} + +BrushManagerProxy::~BrushManagerProxy() +{ + delete d_ptr; +} + +void BrushManagerProxy::setBrushManager(QtBrushManager *manager) +{ + if (d_ptr->m_Manager == manager) + return; + + if (d_ptr->m_Manager) { + disconnect(d_ptr->m_Manager, SIGNAL(brushAdded(const QString &, const QBrush &)), + this, SLOT(brushAdded(const QString &, const QBrush &))); + disconnect(d_ptr->m_Manager, SIGNAL(brushRemoved(const QString &)), + this, SLOT(brushRemoved(const QString &))); + } + + d_ptr->m_Manager = manager; + + if (!d_ptr->m_Manager) + return; + + // clear the manager + QMap<QString, QBrush> brushes = d_ptr->m_Manager->brushes(); + QMap<QString, QBrush>::ConstIterator it = brushes.constBegin(); + while (it != brushes.constEnd()) { + QString name = it.key(); + d_ptr->m_Manager->removeBrush(name); + + it++; + } + + // fill up the manager from compiled resources or from brush folder here + const QString nameAttribute = QLatin1String("name"); + const QString brush = QLatin1String("brush"); + const QString description = QLatin1String("description"); + + QDir brushDir(d_ptr->m_BrushPath); + bool customBrushesExist = brushDir.exists(); + if (customBrushesExist) { + // load brushes from brush folder + QStringList nameFilters; + nameFilters.append(QLatin1String("*.br")); + + QFileInfoList infos = brushDir.entryInfoList(nameFilters); + QListIterator<QFileInfo> it(infos); + while (it.hasNext()) { + const QFileInfo fi = it.next(); + + QString filename = fi.absoluteFilePath(); + + QFile file(filename); + if (file.open(QIODevice::ReadOnly)) { + QXmlStreamReader reader(&file); + + //<description name="black" > + // <brush brushstyle="SolidPattern" > + // <color alpha="255" .../> + // </brush> + //</description> + + QString descname; + while (!reader.atEnd()) { + if (reader.readNext() == QXmlStreamReader::StartElement) { + const QString tag = reader.name().toString().toLower(); + if (tag == description) { + if (!reader.attributes().hasAttribute(nameAttribute)) + reader.raiseError(tr("The element '%1' is missing the required attribute '%2'.") + .arg(tag, nameAttribute)); + else + descname = reader.attributes().value(nameAttribute).toString(); + continue; + } + if (tag == brush) { + DomBrush brush; + brush.read(reader); + + if (descname.isEmpty()) { + reader.raiseError(tr("Empty brush name encountered.")); + } else { + QSimpleResource resource(d_ptr->m_Core); + QBrush br = resource.setupBrush(&brush); + d_ptr->m_Manager->addBrush(descname, br); + d_ptr->m_FileToBrush[filename] = descname; + d_ptr->m_BrushToFile[descname] = filename; + } + continue; + } + reader.raiseError(tr("An unexpected element '%1' was encountered.").arg(tag)); + } + } + + file.close(); + + if (reader.hasError()) { + qdesigner_internal::designerWarning(tr("An error occurred when reading the brush definition file '%1' at line line %2, column %3: %4") + .arg(fi.fileName()) + .arg(reader.lineNumber()) + .arg(reader.columnNumber()) + .arg(reader.errorString())); + continue; + } + } + } + } + + connect(d_ptr->m_Manager, SIGNAL(brushAdded(QString,QBrush)), + this, SLOT(brushAdded(QString, QBrush))); + connect(d_ptr->m_Manager, SIGNAL(brushRemoved(QString)), + this, SLOT(brushRemoved(QString))); + + if (!customBrushesExist) { + // load brushes from resources + QFile qrcFile(QLatin1String(":trolltech/brushes/defaultbrushes.xml")); + if (!qrcFile.open(QIODevice::ReadOnly)) + Q_ASSERT(0); + + QXmlStreamReader reader(&qrcFile); + + while (!reader.atEnd()) { + if (reader.readNext() == QXmlStreamReader::StartElement) { + if (reader.name().toString().toLower() == QLatin1String("description")) { + const QString name = reader.attributes().value(nameAttribute).toString(); + do { // forward to <brush> element, which DomBrush expects + reader.readNext(); + } while (!reader.atEnd() && reader.tokenType() != QXmlStreamReader::StartElement); + DomBrush brushDom; + brushDom.read(reader); + if (!reader.hasError()) { + QSimpleResource resource(d_ptr->m_Core); + QBrush br = resource.setupBrush(&brushDom); + d_ptr->m_Manager->addBrush(name, br); + } + } + } + } + if (reader.hasError()) { + // Should never happen + qdesigner_internal::designerWarning(tr("An error occurred when reading the resource file '%1' at line %2, column %3: %4") + .arg(qrcFile.fileName()) + .arg(reader.lineNumber()) + .arg(reader.columnNumber()) + .arg(reader.errorString())); + } + + qrcFile.close(); + } +} + +QT_END_NAMESPACE + +#include "moc_brushmanagerproxy.cpp" diff --git a/tools/designer/src/components/formeditor/brushmanagerproxy.h b/tools/designer/src/components/formeditor/brushmanagerproxy.h new file mode 100644 index 0000000..cbe50ae --- /dev/null +++ b/tools/designer/src/components/formeditor/brushmanagerproxy.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BRUSHMANAGERPROXY_H +#define BRUSHMANAGERPROXY_H + +#include <QtCore/QObject> + +QT_BEGIN_NAMESPACE + +class QDesignerFormEditorInterface; + +namespace qdesigner_internal { + +class QtBrushManager; +class BrushManagerProxyPrivate; + +class BrushManagerProxy : public QObject +{ + Q_OBJECT +public: + explicit BrushManagerProxy(QDesignerFormEditorInterface *core, QObject *parent = 0); + ~BrushManagerProxy(); + + void setBrushManager(QtBrushManager *manager); + +private: + BrushManagerProxyPrivate *d_ptr; + Q_DECLARE_PRIVATE(BrushManagerProxy) + Q_DISABLE_COPY(BrushManagerProxy) + Q_PRIVATE_SLOT(d_func(), void brushAdded(const QString &, const QBrush &)) + Q_PRIVATE_SLOT(d_func(), void brushRemoved(const QString &name)) +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif diff --git a/tools/designer/src/components/formeditor/default_actionprovider.cpp b/tools/designer/src/components/formeditor/default_actionprovider.cpp new file mode 100644 index 0000000..49bf095 --- /dev/null +++ b/tools/designer/src/components/formeditor/default_actionprovider.cpp @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "default_actionprovider.h" +#include "invisible_widget_p.h" +#include "qdesigner_toolbar_p.h" + +#include <QtGui/QAction> +#include <QtGui/QApplication> +#include <QtCore/QRect> +#include <QtCore/QDebug> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +// ------------ ActionProviderBase: +// Draws the drag indicator when dragging an action over a widget +// that receives action Dnd, such as ToolBar, Menu or MenuBar. +ActionProviderBase::ActionProviderBase(QWidget *widget) : + m_indicator(new InvisibleWidget(widget)) +{ + Q_ASSERT(widget != 0); + + m_indicator->setAutoFillBackground(true); + m_indicator->setBackgroundRole(QPalette::Window); + + QPalette p; + p.setColor(m_indicator->backgroundRole(), Qt::red); + m_indicator->setPalette(p); + m_indicator->hide(); +} + +enum { indicatorSize = 2 }; + +// Position an indicator horizontally over the rectangle, indicating +// 'Insert before' (left or right according to layout direction) +static inline QRect horizontalIndicatorRect(const QRect &rect) +{ + const Qt::LayoutDirection layoutDirection = QApplication::layoutDirection(); + // Position right? + QRect rc = QRect(rect.x(), 0, indicatorSize, rect.height() - 1); + if (layoutDirection == Qt::RightToLeft) + rc.moveLeft(rc.x() + rect.width() - indicatorSize); + return rc; +} + +// Position an indicator vertically over the rectangle, indicating 'Insert before' (top) +static inline QRect verticalIndicatorRect(const QRect &rect) +{ + return QRect(0, rect.top(), rect.width() - 1, indicatorSize); +} + +// Determine the geometry of the indicator by retrieving +// the action under mouse and positioning the bar within its geometry. +QRect ActionProviderBase::indicatorGeometry(const QPoint &pos) const +{ + QAction *action = actionAt(pos); + if (!action) + return QRect(); + QRect rc = actionGeometry(action); + return orientation() == Qt::Horizontal ? horizontalIndicatorRect(rc) : verticalIndicatorRect(rc); +} + +// Adjust the indicator while dragging. (-1,1) is called to finish a DND operation +void ActionProviderBase::adjustIndicator(const QPoint &pos) +{ + if (pos == QPoint(-1, -1)) { + m_indicator->hide(); + return; + } + const QRect ig = indicatorGeometry(pos); + if (ig.isValid()) { + m_indicator->setGeometry(ig); + QPalette p = m_indicator->palette(); + if (p.color(m_indicator->backgroundRole()) != Qt::red) { + p.setColor(m_indicator->backgroundRole(), Qt::red); + m_indicator->setPalette(p); + } + m_indicator->show(); + m_indicator->raise(); + } else { + m_indicator->hide(); + } +} + +// ------------- QToolBarActionProvider +QToolBarActionProvider::QToolBarActionProvider(QToolBar *widget, QObject *parent) : + QObject(parent), + ActionProviderBase(widget), + m_widget(widget) +{ +} + +QRect QToolBarActionProvider::actionGeometry(QAction *action) const +{ + return m_widget->actionGeometry(action); +} + +QAction *QToolBarActionProvider::actionAt(const QPoint &pos) const +{ + return ToolBarEventFilter::actionAt(m_widget, pos); +} + +Qt::Orientation QToolBarActionProvider::orientation() const +{ + return m_widget->orientation(); +} + +QRect QToolBarActionProvider::indicatorGeometry(const QPoint &pos) const +{ + const QRect actionRect = ActionProviderBase::indicatorGeometry(pos); + if (actionRect.isValid()) + return actionRect; + // Toolbar differs in that is has no dummy placeholder to 'insert before' + // when intending to append. Check the free area. + const QRect freeArea = ToolBarEventFilter::freeArea(m_widget); + if (!freeArea.contains(pos)) + return QRect(); + return orientation() == Qt::Horizontal ? horizontalIndicatorRect(freeArea) : verticalIndicatorRect(freeArea); +} + +// ------------- QMenuBarActionProvider +QMenuBarActionProvider::QMenuBarActionProvider(QMenuBar *widget, QObject *parent) : + QObject(parent), + ActionProviderBase(widget), + m_widget(widget) +{ +} + +QRect QMenuBarActionProvider::actionGeometry(QAction *action) const +{ + return m_widget->actionGeometry(action); +} + +QAction *QMenuBarActionProvider::actionAt(const QPoint &pos) const +{ + return m_widget->actionAt(pos); +} + +Qt::Orientation QMenuBarActionProvider::orientation() const +{ + return Qt::Horizontal; +} + +// ------------- QMenuActionProvider +QMenuActionProvider::QMenuActionProvider(QMenu *widget, QObject *parent) : + QObject(parent), + ActionProviderBase(widget), + m_widget(widget) +{ +} + +QRect QMenuActionProvider::actionGeometry(QAction *action) const +{ + return m_widget->actionGeometry(action); +} + +QAction *QMenuActionProvider::actionAt(const QPoint &pos) const +{ + return m_widget->actionAt(pos); +} + +Qt::Orientation QMenuActionProvider::orientation() const +{ + return Qt::Vertical; +} +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/default_actionprovider.h b/tools/designer/src/components/formeditor/default_actionprovider.h new file mode 100644 index 0000000..6c81ec6 --- /dev/null +++ b/tools/designer/src/components/formeditor/default_actionprovider.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DEFAULT_ACTIONPROVIDER_H +#define DEFAULT_ACTIONPROVIDER_H + +#include "formeditor_global.h" +#include "actionprovider_p.h" +#include <extensionfactory_p.h> + +#include <QtGui/QMenu> +#include <QtGui/QMenuBar> +#include <QtGui/QToolBar> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +class FormWindow; + +class QT_FORMEDITOR_EXPORT ActionProviderBase: public QDesignerActionProviderExtension +{ +protected: + explicit ActionProviderBase(QWidget *widget); + +public: + virtual void adjustIndicator(const QPoint &pos); + virtual Qt::Orientation orientation() const = 0; + +protected: + virtual QRect indicatorGeometry(const QPoint &pos) const; + +private: + QWidget *m_indicator; +}; + +class QT_FORMEDITOR_EXPORT QToolBarActionProvider: public QObject, public ActionProviderBase +{ + Q_OBJECT + Q_INTERFACES(QDesignerActionProviderExtension) +public: + explicit QToolBarActionProvider(QToolBar *widget, QObject *parent = 0); + + virtual QRect actionGeometry(QAction *action) const; + virtual QAction *actionAt(const QPoint &pos) const; + Qt::Orientation orientation() const; + +protected: + virtual QRect indicatorGeometry(const QPoint &pos) const; + +private: + QToolBar *m_widget; +}; + +class QT_FORMEDITOR_EXPORT QMenuBarActionProvider: public QObject, public ActionProviderBase +{ + Q_OBJECT + Q_INTERFACES(QDesignerActionProviderExtension) +public: + explicit QMenuBarActionProvider(QMenuBar *widget, QObject *parent = 0); + + virtual QRect actionGeometry(QAction *action) const; + virtual QAction *actionAt(const QPoint &pos) const; + Qt::Orientation orientation() const; + +private: + QMenuBar *m_widget; +}; + +class QT_FORMEDITOR_EXPORT QMenuActionProvider: public QObject, public ActionProviderBase +{ + Q_OBJECT + Q_INTERFACES(QDesignerActionProviderExtension) +public: + explicit QMenuActionProvider(QMenu *widget, QObject *parent = 0); + + virtual QRect actionGeometry(QAction *action) const; + virtual QAction *actionAt(const QPoint &pos) const; + Qt::Orientation orientation() const; + +private: + QMenu *m_widget; +}; + +typedef ExtensionFactory<QDesignerActionProviderExtension, QToolBar, QToolBarActionProvider> QToolBarActionProviderFactory; +typedef ExtensionFactory<QDesignerActionProviderExtension, QMenuBar, QMenuBarActionProvider> QMenuBarActionProviderFactory; +typedef ExtensionFactory<QDesignerActionProviderExtension, QMenu, QMenuActionProvider> QMenuActionProviderFactory; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // DEFAULT_ACTIONPROVIDER_H diff --git a/tools/designer/src/components/formeditor/default_container.cpp b/tools/designer/src/components/formeditor/default_container.cpp new file mode 100644 index 0000000..eb3cd4f --- /dev/null +++ b/tools/designer/src/components/formeditor/default_container.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "default_container.h" +#include <QtCore/QDebug> + +QT_BEGIN_NAMESPACE + +template <class Container> +static inline void setCurrentContainerIndex(int index, Container *container) +{ + const bool blocked = container->signalsBlocked(); + container->blockSignals(true); + container->setCurrentIndex(index); + container->blockSignals(blocked); +} + +static inline void ensureNoParent(QWidget *widget) +{ + if (widget->parentWidget()) + widget->setParent(0); +} + +static const char *PageLabel = "Page"; + +namespace qdesigner_internal { + +// --------- QStackedWidgetContainer +QStackedWidgetContainer::QStackedWidgetContainer(QStackedWidget *widget, QObject *parent) : + QObject(parent), + m_widget(widget) +{ +} + +void QStackedWidgetContainer::setCurrentIndex(int index) +{ + setCurrentContainerIndex(index, m_widget); +} + +void QStackedWidgetContainer::addWidget(QWidget *widget) +{ + ensureNoParent(widget); + m_widget->addWidget(widget); +} + +void QStackedWidgetContainer::insertWidget(int index, QWidget *widget) +{ + ensureNoParent(widget); + m_widget->insertWidget(index, widget); +} + +void QStackedWidgetContainer::remove(int index) +{ + m_widget->removeWidget(widget(index)); +} + +// --------- QTabWidgetContainer +QTabWidgetContainer::QTabWidgetContainer(QTabWidget *widget, QObject *parent) : + QObject(parent), + m_widget(widget) +{ +} + +void QTabWidgetContainer::setCurrentIndex(int index) +{ + setCurrentContainerIndex(index, m_widget); +} + +void QTabWidgetContainer::addWidget(QWidget *widget) +{ + ensureNoParent(widget); + m_widget->addTab(widget, QString::fromUtf8(PageLabel)); +} + +void QTabWidgetContainer::insertWidget(int index, QWidget *widget) +{ + ensureNoParent(widget); + m_widget->insertTab(index, widget, QString::fromUtf8(PageLabel)); +} + +void QTabWidgetContainer::remove(int index) +{ + m_widget->removeTab(index); +} + +// ------------------- QToolBoxContainer +QToolBoxContainer::QToolBoxContainer(QToolBox *widget, QObject *parent) : + QObject(parent), + m_widget(widget) +{ +} + +void QToolBoxContainer::setCurrentIndex(int index) +{ + setCurrentContainerIndex(index, m_widget); +} + +void QToolBoxContainer::addWidget(QWidget *widget) +{ + ensureNoParent(widget); + m_widget->addItem(widget, QString::fromUtf8(PageLabel)); +} + +void QToolBoxContainer::insertWidget(int index, QWidget *widget) +{ + ensureNoParent(widget); + m_widget->insertItem(index, widget, QString::fromUtf8(PageLabel)); +} + +void QToolBoxContainer::remove(int index) +{ + m_widget->removeItem(index); +} + +// ------------------- QScrollAreaContainer +// We pass on active=true only if there are no children yet. +// If there are children, it is a legacy custom widget QScrollArea that has an internal, +// unmanaged child, in which case we deactivate the extension (otherwise we crash). +// The child will then not show up in the task menu + +QScrollAreaContainer::QScrollAreaContainer(QScrollArea *widget, QObject *parent) : + QObject(parent), + SingleChildContainer<QScrollArea>(widget, widget->widget() == 0) +{ +} +// ------------------- QDockWidgetContainer +QDockWidgetContainer::QDockWidgetContainer(QDockWidget *widget, QObject *parent) : + QObject(parent), + SingleChildContainer<QDockWidget>(widget) +{ +} + +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/default_container.h b/tools/designer/src/components/formeditor/default_container.h new file mode 100644 index 0000000..e8547638 --- /dev/null +++ b/tools/designer/src/components/formeditor/default_container.h @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DEFAULT_CONTAINER_H +#define DEFAULT_CONTAINER_H + +#include <QtDesigner/QDesignerContainerExtension> +#include <QtDesigner/extension.h> +#include <extensionfactory_p.h> + +#include <QtGui/QStackedWidget> +#include <QtGui/QTabWidget> +#include <QtGui/QToolBox> +#include <QtGui/QScrollArea> +#include <QtGui/QDockWidget> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +// ------------ QStackedWidgetContainer +class QStackedWidgetContainer: public QObject, public QDesignerContainerExtension +{ + Q_OBJECT + Q_INTERFACES(QDesignerContainerExtension) +public: + explicit QStackedWidgetContainer(QStackedWidget *widget, QObject *parent = 0); + + virtual int count() const { return m_widget->count(); } + virtual QWidget *widget(int index) const { return m_widget->widget(index); } + + virtual int currentIndex() const { return m_widget->currentIndex(); } + virtual void setCurrentIndex(int index); + + virtual void addWidget(QWidget *widget); + virtual void insertWidget(int index, QWidget *widget); + virtual void remove(int index); + +private: + QStackedWidget *m_widget; +}; + +// ------------ QTabWidgetContainer +class QTabWidgetContainer: public QObject, public QDesignerContainerExtension +{ + Q_OBJECT + Q_INTERFACES(QDesignerContainerExtension) +public: + explicit QTabWidgetContainer(QTabWidget *widget, QObject *parent = 0); + + virtual int count() const { return m_widget->count(); } + virtual QWidget *widget(int index) const { return m_widget->widget(index); } + + virtual int currentIndex() const { return m_widget->currentIndex(); } + virtual void setCurrentIndex(int index); + + virtual void addWidget(QWidget *widget); + virtual void insertWidget(int index, QWidget *widget); + virtual void remove(int index); + +private: + QTabWidget *m_widget; +}; + +// ------------ QToolBoxContainer +class QToolBoxContainer: public QObject, public QDesignerContainerExtension +{ + Q_OBJECT + Q_INTERFACES(QDesignerContainerExtension) +public: + explicit QToolBoxContainer(QToolBox *widget, QObject *parent = 0); + + virtual int count() const { return m_widget->count(); } + virtual QWidget *widget(int index) const { return m_widget->widget(index); } + + virtual int currentIndex() const { return m_widget->currentIndex(); } + virtual void setCurrentIndex(int index); + + virtual void addWidget(QWidget *widget); + virtual void insertWidget(int index, QWidget *widget); + virtual void remove(int index); + +private: + QToolBox *m_widget; +}; + +// ------------ SingleChildContainer: +// Template for containers that have a single child widget using widget()/setWidget(). + +template <class Container> +class SingleChildContainer: public QDesignerContainerExtension +{ +protected: + explicit SingleChildContainer(Container *widget, bool active = true); +public: + virtual int count() const; + virtual QWidget *widget(int index) const; + virtual int currentIndex() const; + virtual void setCurrentIndex(int /*index*/) {} + virtual void addWidget(QWidget *widget); + virtual void insertWidget(int index, QWidget *widget); + virtual void remove(int /*index*/) {} + +private: + const bool m_active; + Container *m_container; +}; + +template <class Container> +SingleChildContainer<Container>::SingleChildContainer(Container *widget, bool active) : + m_active(active), + m_container(widget) +{ +} + +template <class Container> +int SingleChildContainer<Container>::count() const +{ + return m_active && m_container->widget() ? 1 : 0; +} + +template <class Container> +QWidget *SingleChildContainer<Container>::widget(int /* index */) const +{ + return m_container->widget(); +} + +template <class Container> +int SingleChildContainer<Container>::currentIndex() const +{ + return m_active && m_container->widget() ? 0 : -1; +} + +template <class Container> +void SingleChildContainer<Container>::addWidget(QWidget *widget) +{ + Q_ASSERT(m_container->widget() == 0); + widget->setParent(m_container); + m_container->setWidget(widget); +} + +template <class Container> +void SingleChildContainer<Container>::insertWidget(int /* index */, QWidget *widget) +{ + addWidget(widget); +} + +// ------------ QScrollAreaContainer +class QScrollAreaContainer: public QObject, public SingleChildContainer<QScrollArea> +{ + Q_OBJECT + Q_INTERFACES(QDesignerContainerExtension) +public: + explicit QScrollAreaContainer(QScrollArea *widget, QObject *parent = 0); +}; + +// --------------- QDockWidgetContainer +class QDockWidgetContainer: public QObject, public SingleChildContainer<QDockWidget> +{ + Q_OBJECT + Q_INTERFACES(QDesignerContainerExtension) +public: + explicit QDockWidgetContainer(QDockWidget *widget, QObject *parent = 0); +}; + +typedef ExtensionFactory<QDesignerContainerExtension, QStackedWidget, QStackedWidgetContainer> QDesignerStackedWidgetContainerFactory; +typedef ExtensionFactory<QDesignerContainerExtension, QTabWidget, QTabWidgetContainer> QDesignerTabWidgetContainerFactory; +typedef ExtensionFactory<QDesignerContainerExtension, QToolBox, QToolBoxContainer> QDesignerToolBoxContainerFactory; +typedef ExtensionFactory<QDesignerContainerExtension, QScrollArea, QScrollAreaContainer> QScrollAreaContainerFactory; +typedef ExtensionFactory<QDesignerContainerExtension, QDockWidget, QDockWidgetContainer> QDockWidgetContainerFactory; +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // DEFAULT_CONTAINER_H diff --git a/tools/designer/src/components/formeditor/default_layoutdecoration.cpp b/tools/designer/src/components/formeditor/default_layoutdecoration.cpp new file mode 100644 index 0000000..5558068 --- /dev/null +++ b/tools/designer/src/components/formeditor/default_layoutdecoration.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "default_layoutdecoration.h" +#include "qlayout_widget_p.h" + +#include <layoutinfo_p.h> + +#include <QtDesigner/QDesignerMetaDataBaseItemInterface> +#include <QtDesigner/QDesignerFormWindowInterface> +#include <QtDesigner/QDesignerFormEditorInterface> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +// ---- QDesignerLayoutDecorationFactory ---- +QDesignerLayoutDecorationFactory::QDesignerLayoutDecorationFactory(QExtensionManager *parent) + : QExtensionFactory(parent) +{ +} + +QObject *QDesignerLayoutDecorationFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const +{ + if (!object->isWidgetType() || iid != Q_TYPEID(QDesignerLayoutDecorationExtension)) + return 0; + + QWidget *widget = qobject_cast<QWidget*>(object); + + if (const QLayoutWidget *layoutWidget = qobject_cast<const QLayoutWidget*>(widget)) + return QLayoutSupport::createLayoutSupport(layoutWidget->formWindow(), widget, parent); + + if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(widget)) + if (LayoutInfo::managedLayout(fw->core(), widget)) + return QLayoutSupport::createLayoutSupport(fw, widget, parent); + + return 0; +} +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/default_layoutdecoration.h b/tools/designer/src/components/formeditor/default_layoutdecoration.h new file mode 100644 index 0000000..770372f --- /dev/null +++ b/tools/designer/src/components/formeditor/default_layoutdecoration.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DEFAULT_LAYOUTDECORATION_H +#define DEFAULT_LAYOUTDECORATION_H + +#include "formeditor_global.h" +#include <QtDesigner/QDesignerLayoutDecorationExtension> +#include <QtDesigner/default_extensionfactory.h> + +QT_BEGIN_NAMESPACE + +class QDesignerFormWindowInterface; + +namespace qdesigner_internal { +class QDesignerLayoutDecorationFactory: public QExtensionFactory +{ + Q_OBJECT + Q_INTERFACES(QAbstractExtensionFactory) +public: + explicit QDesignerLayoutDecorationFactory(QExtensionManager *parent = 0); + +protected: + virtual QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // DEFAULT_LAYOUTDECORATION_H diff --git a/tools/designer/src/components/formeditor/defaultbrushes.xml b/tools/designer/src/components/formeditor/defaultbrushes.xml new file mode 100644 index 0000000..88035c3 --- /dev/null +++ b/tools/designer/src/components/formeditor/defaultbrushes.xml @@ -0,0 +1,542 @@ +<brushes> + <description name="French" > + <brush brushstyle="LinearGradientPattern" > + <gradient spread="PadSpread" startx="0" starty="0" type="LinearGradient" endx="1" coordinatemode="StretchToDeviceMode" endy="0" > + <gradientstop position="0" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.323" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.343" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.656" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.676" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="1" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + </gradient> + </brush> + </description> + <description name="German" > + <brush brushstyle="LinearGradientPattern" > + <gradient spread="PadSpread" startx="0" starty="0" type="LinearGradient" endx="0" coordinatemode="StretchToDeviceMode" endy="1" > + <gradientstop position="0" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="0.323" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="0.343" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="0.656" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="0.676" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="1" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>0</blue> + </color> + </gradientstop> + </gradient> + </brush> + </description> + <description name="Greek" > + <brush brushstyle="LinearGradientPattern" > + <gradient spread="PadSpread" startx="0" starty="0" type="LinearGradient" endx="0" coordinatemode="StretchToDeviceMode" endy="1" > + <gradientstop position="0" > + <color alpha="255" > + <red>0</red> + <green>176</green> + <blue>221</blue> + </color> + </gradientstop> + <gradientstop position="0.09" > + <color alpha="255" > + <red>0</red> + <green>176</green> + <blue>221</blue> + </color> + </gradientstop> + <gradientstop position="0.105" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.205" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.22" > + <color alpha="255" > + <red>0</red> + <green>176</green> + <blue>221</blue> + </color> + </gradientstop> + <gradientstop position="0.32" > + <color alpha="255" > + <red>0</red> + <green>176</green> + <blue>221</blue> + </color> + </gradientstop> + <gradientstop position="0.335" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.435" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.45" > + <color alpha="255" > + <red>0</red> + <green>176</green> + <blue>221</blue> + </color> + </gradientstop> + <gradientstop position="0.55" > + <color alpha="255" > + <red>0</red> + <green>176</green> + <blue>221</blue> + </color> + </gradientstop> + <gradientstop position="0.565" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.665" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.68" > + <color alpha="255" > + <red>0</red> + <green>176</green> + <blue>221</blue> + </color> + </gradientstop> + <gradientstop position="0.78" > + <color alpha="255" > + <red>0</red> + <green>176</green> + <blue>221</blue> + </color> + </gradientstop> + <gradientstop position="0.795" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.895" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.91" > + <color alpha="255" > + <red>0</red> + <green>176</green> + <blue>221</blue> + </color> + </gradientstop> + <gradientstop position="1" > + <color alpha="255" > + <red>0</red> + <green>176</green> + <blue>221</blue> + </color> + </gradientstop> + </gradient> + </brush> + </description> + <description name="Italian" > + <brush brushstyle="LinearGradientPattern" > + <gradient spread="PadSpread" startx="0" starty="0" type="LinearGradient" endx="1" coordinatemode="StretchToDeviceMode" endy="0" > + <gradientstop position="0" > + <color alpha="255" > + <red>60</red> + <green>160</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="0.323" > + <color alpha="255" > + <red>60</red> + <green>160</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="0.343" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.656" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.676" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="1" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + </gradient> + </brush> + </description> + <description name="Japanese" > + <brush brushstyle="RadialGradientPattern" > + <gradient focalx="0.5" focaly="0.5" radius="0.5" spread="PadSpread" type="RadialGradient" coordinatemode="StretchToDeviceMode" centralx="0.5" centraly="0.5" > + <gradientstop position="0" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="0.49" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="0.51" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="1" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + </gradient> + </brush> + </description> + <description name="Norwegian" > + <brush brushstyle="LinearGradientPattern" > + <gradient spread="PadSpread" startx="0" starty="0" type="LinearGradient" endx="1" coordinatemode="StretchToDeviceMode" endy="0" > + <gradientstop position="0" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="0.225" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="0.25" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.275" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.3" > + <color alpha="255" > + <red>5</red> + <green>0</green> + <blue>70</blue> + </color> + </gradientstop> + <gradientstop position="0.4" > + <color alpha="255" > + <red>5</red> + <green>0</green> + <blue>70</blue> + </color> + </gradientstop> + <gradientstop position="0.425" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.45" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.475" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="1" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + </gradient> + </brush> + </description> + <description name="Polish" > + <brush brushstyle="LinearGradientPattern" > + <gradient spread="PadSpread" startx="0" starty="0" type="LinearGradient" endx="0" coordinatemode="StretchToDeviceMode" endy="1" > + <gradientstop position="0" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.475" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </gradientstop> + <gradientstop position="0.525" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="1" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + </gradient> + </brush> + </description> + <description name="Spanish" > + <brush brushstyle="LinearGradientPattern" > + <gradient spread="PadSpread" startx="0" starty="0" type="LinearGradient" endx="0" coordinatemode="StretchToDeviceMode" endy="1" > + <gradientstop position="0" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="0.24" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="0.26" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="0.74" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="0.76" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + <gradientstop position="1" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </gradientstop> + </gradient> + </brush> + </description> + <description name="black" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </description> + <description name="blue" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>0</green> + <blue>255</blue> + </color> + </brush> + </description> + <description name="cyan" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </description> + <description name="green" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>0</red> + <green>255</green> + <blue>0</blue> + </color> + </brush> + </description> + <description name="magenta" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>255</blue> + </color> + </brush> + </description> + <description name="red" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </description> + <description name="white" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </description> + <description name="yellow" > + <brush brushstyle="SolidPattern" > + <color alpha="255" > + <red>255</red> + <green>255</green> + <blue>0</blue> + </color> + </brush> + </description> +</brushes> diff --git a/tools/designer/src/components/formeditor/deviceprofiledialog.cpp b/tools/designer/src/components/formeditor/deviceprofiledialog.cpp new file mode 100644 index 0000000..995bc3f --- /dev/null +++ b/tools/designer/src/components/formeditor/deviceprofiledialog.cpp @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "deviceprofiledialog.h" +#include "ui_deviceprofiledialog.h" + +#include <abstractdialoggui_p.h> +#include <deviceprofile_p.h> + +#include <QtGui/QDialogButtonBox> +#include <QtGui/QVBoxLayout> +#include <QtGui/QPushButton> +#include <QtGui/QStyleFactory> +#include <QtGui/QFontDatabase> + +#include <QtCore/QFileInfo> +#include <QtCore/QFile> + +QT_BEGIN_NAMESPACE + +static const char *profileExtensionC = "qdp"; + +static inline QString fileFilter() +{ + return qdesigner_internal::DeviceProfileDialog::tr("Device Profiles (*.%1)").arg(QLatin1String(profileExtensionC)); +} + +// Populate a combo with a sequence of integers, also set them as data. +template <class IntIterator> + static void populateNumericCombo(IntIterator i1, IntIterator i2, QComboBox *cb) +{ + QString s; + cb->setEditable(false); + for ( ; i1 != i2 ; ++i1) { + const int n = *i1; + s.setNum(n); + cb->addItem(s, QVariant(n)); + } +} + +namespace qdesigner_internal { + +DeviceProfileDialog::DeviceProfileDialog(QDesignerDialogGuiInterface *dlgGui, QWidget *parent) : + QDialog(parent), + m_ui(new Ui::DeviceProfileDialog), + m_dlgGui(dlgGui) +{ + setModal(true); + m_ui->setupUi(this); + + const QList<int> standardFontSizes = QFontDatabase::standardSizes(); + populateNumericCombo(standardFontSizes.constBegin(), standardFontSizes.constEnd(), m_ui->m_systemFontSizeCombo); + + // Styles + const QStringList styles = QStyleFactory::keys(); + m_ui->m_styleCombo->addItem(tr("Default"), QVariant(QString())); + const QStringList::const_iterator cend = styles.constEnd(); + for (QStringList::const_iterator it = styles.constBegin(); it != cend; ++it) + m_ui->m_styleCombo->addItem(*it, *it); + + connect(m_ui->m_nameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(nameChanged(QString))); + connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + connect(m_ui->buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(accept())); + // Note that Load/Save emit accepted() of the button box.. + connect(m_ui->buttonBox->button(QDialogButtonBox::Save), SIGNAL(clicked()), this, SLOT(save())); + connect(m_ui->buttonBox->button(QDialogButtonBox::Open), SIGNAL(clicked()), this, SLOT(open())); +} + +DeviceProfileDialog::~DeviceProfileDialog() +{ + delete m_ui; +} + +DeviceProfile DeviceProfileDialog::deviceProfile() const +{ + DeviceProfile rc; + rc.setName(m_ui->m_nameLineEdit->text()); + rc.setFontFamily(m_ui->m_systemFontComboBox->currentFont().family()); + rc.setFontPointSize(m_ui->m_systemFontSizeCombo->itemData(m_ui->m_systemFontSizeCombo->currentIndex()).toInt()); + + int dpiX, dpiY; + m_ui->m_dpiChooser->getDPI(&dpiX, &dpiY); + rc.setDpiX(dpiX); + rc.setDpiY(dpiY); + + rc.setStyle(m_ui->m_styleCombo->itemData(m_ui->m_styleCombo->currentIndex()).toString()); + + return rc; +} + +void DeviceProfileDialog::setDeviceProfile(const DeviceProfile &s) +{ + m_ui->m_nameLineEdit->setText(s.name()); + m_ui->m_systemFontComboBox->setCurrentFont(QFont(s.fontFamily())); + const int fontSizeIndex = m_ui->m_systemFontSizeCombo->findData(QVariant(s.fontPointSize())); + m_ui->m_systemFontSizeCombo->setCurrentIndex(fontSizeIndex != -1 ? fontSizeIndex : 0); + m_ui->m_dpiChooser->setDPI(s.dpiX(), s.dpiY()); + const int styleIndex = m_ui->m_styleCombo->findData(s.style()); + m_ui->m_styleCombo->setCurrentIndex(styleIndex != -1 ? styleIndex : 0); +} + +void DeviceProfileDialog::setOkButtonEnabled(bool v) +{ + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(v); +} + +bool DeviceProfileDialog::showDialog(const QStringList &existingNames) +{ + m_existingNames = existingNames; + m_ui->m_nameLineEdit->setFocus(Qt::OtherFocusReason); + nameChanged(m_ui->m_nameLineEdit->text()); + return exec() == Accepted; +} + +void DeviceProfileDialog::nameChanged(const QString &name) +{ + const bool invalid = name.isEmpty() || m_existingNames.indexOf(name) != -1; + setOkButtonEnabled(!invalid); +} + +void DeviceProfileDialog::save() +{ + QString fn = m_dlgGui->getSaveFileName(this, tr("Save Profile"), QString(), fileFilter()); + if (fn.isEmpty()) + return; + if (QFileInfo(fn).completeSuffix().isEmpty()) { + fn += QLatin1Char('.'); + fn += QLatin1String(profileExtensionC); + } + + QFile file(fn); + if (!file.open(QIODevice::WriteOnly|QIODevice::Text)) { + critical(tr("Save Profile - Error"), tr("Unable to open the file '%1' for writing: %2").arg(fn, file.errorString())); + return; + } + file.write(deviceProfile().toXml().toUtf8()); +} + +void DeviceProfileDialog::open() +{ + const QString fn = m_dlgGui->getOpenFileName(this, tr("Open profile"), QString(), fileFilter()); + if (fn.isEmpty()) + return; + + QFile file(fn); + if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) { + critical(tr("Open Profile - Error"), tr("Unable to open the file '%1' for reading: %2").arg(fn, file.errorString())); + return; + } + QString errorMessage; + DeviceProfile newSettings; + if (!newSettings.fromXml(QString::fromUtf8(file.readAll()), &errorMessage)) { + critical(tr("Open Profile - Error"), tr("'%1' is not a valid profile: %2").arg(fn, errorMessage)); + return; + } + setDeviceProfile(newSettings); +} + +void DeviceProfileDialog::critical(const QString &title, const QString &msg) +{ + m_dlgGui->message(this, QDesignerDialogGuiInterface::OtherMessage, QMessageBox::Critical, title, msg); +} +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/deviceprofiledialog.h b/tools/designer/src/components/formeditor/deviceprofiledialog.h new file mode 100644 index 0000000..dafcd77 --- /dev/null +++ b/tools/designer/src/components/formeditor/deviceprofiledialog.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of Qt Designer. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#ifndef SYSTEMSETTINGSDIALOG_H +#define SYSTEMSETTINGSDIALOG_H + +#include <QtGui/QDialog> +#include <QtCore/QStringList> + +QT_BEGIN_NAMESPACE + +namespace Ui { + class DeviceProfileDialog; +} + +class QDesignerDialogGuiInterface; + +class QDialogButtonBox; + +namespace qdesigner_internal { + +class DeviceProfile; + +/* DeviceProfileDialog: Widget to edit system settings for embedded design */ + +class DeviceProfileDialog : public QDialog +{ + Q_DISABLE_COPY(DeviceProfileDialog) + Q_OBJECT +public: + explicit DeviceProfileDialog(QDesignerDialogGuiInterface *dlgGui, QWidget *parent = 0); + ~DeviceProfileDialog(); + + DeviceProfile deviceProfile() const; + void setDeviceProfile(const DeviceProfile &s); + + bool showDialog(const QStringList &existingNames); + +private slots: + void setOkButtonEnabled(bool); + void nameChanged(const QString &name); + void save(); + void open(); + +private: + void critical(const QString &title, const QString &msg); + Ui::DeviceProfileDialog *m_ui; + QDesignerDialogGuiInterface *m_dlgGui; + QStringList m_existingNames; +}; +} + +QT_END_NAMESPACE + +#endif // SYSTEMSETTINGSDIALOG_H diff --git a/tools/designer/src/components/formeditor/deviceprofiledialog.ui b/tools/designer/src/components/formeditor/deviceprofiledialog.ui new file mode 100644 index 0000000..3186c57 --- /dev/null +++ b/tools/designer/src/components/formeditor/deviceprofiledialog.ui @@ -0,0 +1,100 @@ +<ui version="4.0" > + <class>DeviceProfileDialog</class> + <widget class="QDialog" name="dialog" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>348</width> + <height>209</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout" > + <item> + <widget class="QWidget" native="1" name="SystemSettingsWidget" > + <layout class="QFormLayout" name="formLayout" > + <item row="1" column="0" > + <widget class="QLabel" name="m_systemFontFamilyLabel" > + <property name="text" > + <string>&Family</string> + </property> + <property name="buddy" > + <cstring>m_systemFontComboBox</cstring> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="QFontComboBox" name="m_systemFontComboBox" /> + </item> + <item row="2" column="0" > + <widget class="QLabel" name="m_systemFontSizeLabel" > + <property name="text" > + <string>&Point Size</string> + </property> + <property name="buddy" > + <cstring>m_systemFontSizeCombo</cstring> + </property> + </widget> + </item> + <item row="2" column="1" > + <widget class="QComboBox" name="m_systemFontSizeCombo" /> + </item> + <item row="3" column="0" > + <widget class="QLabel" name="m_styleLabel" > + <property name="text" > + <string>Style</string> + </property> + <property name="buddy" > + <cstring>m_styleCombo</cstring> + </property> + </widget> + </item> + <item row="3" column="1" > + <widget class="QComboBox" name="m_styleCombo" /> + </item> + <item row="4" column="0" > + <widget class="QLabel" name="m_systemDPILabel" > + <property name="text" > + <string>Device DPI</string> + </property> + </widget> + </item> + <item row="4" column="1" > + <widget class="qdesigner_internal::DPI_Chooser" native="1" name="m_dpiChooser" /> + </item> + <item row="0" column="0" > + <widget class="QLabel" name="m_nameLabel" > + <property name="text" > + <string>Name</string> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="QLineEdit" name="m_nameLineEdit" /> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons" > + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Open|QDialogButtonBox::Save</set> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>qdesigner_internal::DPI_Chooser</class> + <extends>QWidget</extends> + <header>dpi_chooser.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/tools/designer/src/components/formeditor/dpi_chooser.cpp b/tools/designer/src/components/formeditor/dpi_chooser.cpp new file mode 100644 index 0000000..d766e31 --- /dev/null +++ b/tools/designer/src/components/formeditor/dpi_chooser.cpp @@ -0,0 +1,207 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "dpi_chooser.h" + +#include <deviceprofile_p.h> + +#include <QtGui/QComboBox> +#include <QtGui/QSpinBox> +#include <QtGui/QLabel> +#include <QtGui/QVBoxLayout> +#include <QtGui/QHBoxLayout> +#include <QtGui/QPushButton> +#include <QtGui/QCheckBox> + +QT_BEGIN_NAMESPACE + +enum { minDPI = 50, maxDPI = 400 }; + +namespace qdesigner_internal { + +// Entry struct for predefined values +struct DPI_Entry { + int dpiX; + int dpiY; + const char *description; +}; + +const struct DPI_Entry dpiEntries[] = { + //: Embedded device standard screen resolution + { 96, 96, QT_TRANSLATE_NOOP("DPI_Chooser", "Standard (96 x 96)") }, + //: Embedded device screen resolution + { 179, 185, QT_TRANSLATE_NOOP("DPI_Chooser", "Greenphone (179 x 185)") }, + //: Embedded device high definition screen resolution + { 192, 192, QT_TRANSLATE_NOOP("DPI_Chooser", "High (192 x 192)") } +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(const struct qdesigner_internal::DPI_Entry*); + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +// ------------- DPI_Chooser + +DPI_Chooser::DPI_Chooser(QWidget *parent) : + QWidget(parent), + m_systemEntry(new DPI_Entry), + m_predefinedCombo(new QComboBox), + m_dpiXSpinBox(new QSpinBox), + m_dpiYSpinBox(new QSpinBox) +{ + // Predefined settings: System + DeviceProfile::systemResolution(&(m_systemEntry->dpiX), &(m_systemEntry->dpiY)); + m_systemEntry->description = 0; + const struct DPI_Entry *systemEntry = m_systemEntry; + //: System resolution + m_predefinedCombo->addItem(tr("System (%1 x %2)").arg(m_systemEntry->dpiX).arg(m_systemEntry->dpiY), qVariantFromValue(systemEntry)); + // Devices. Exclude the system values as not to duplicate the entries + const int predefinedCount = sizeof(dpiEntries)/sizeof(DPI_Entry); + const struct DPI_Entry *ecend = dpiEntries + predefinedCount; + for (const struct DPI_Entry *it = dpiEntries; it < ecend; ++it) + if (it->dpiX != m_systemEntry->dpiX || it->dpiY != m_systemEntry->dpiY) + m_predefinedCombo->addItem(tr(it->description), qVariantFromValue(it)); + m_predefinedCombo->addItem(tr("User defined")); + + setFocusProxy(m_predefinedCombo); + m_predefinedCombo->setEditable(false); + m_predefinedCombo->setCurrentIndex(0); + connect(m_predefinedCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(syncSpinBoxes())); + // top row with predefined settings + QVBoxLayout *vBoxLayout = new QVBoxLayout; + vBoxLayout->setMargin(0); + vBoxLayout->addWidget(m_predefinedCombo); + // Spin box row + QHBoxLayout *hBoxLayout = new QHBoxLayout; + hBoxLayout->setMargin(0); + + m_dpiXSpinBox->setMinimum(minDPI); + m_dpiXSpinBox->setMaximum(maxDPI); + hBoxLayout->addWidget(m_dpiXSpinBox); + //: DPI X/Y separator + hBoxLayout->addWidget(new QLabel(tr(" x "))); + + m_dpiYSpinBox->setMinimum(minDPI); + m_dpiYSpinBox->setMaximum(maxDPI); + hBoxLayout->addWidget(m_dpiYSpinBox); + + hBoxLayout->addStretch(); + vBoxLayout->addLayout(hBoxLayout); + setLayout(vBoxLayout); + + syncSpinBoxes(); +} + +DPI_Chooser::~DPI_Chooser() +{ + delete m_systemEntry; +} + +void DPI_Chooser::getDPI(int *dpiX, int *dpiY) const +{ + *dpiX = m_dpiXSpinBox->value(); + *dpiY = m_dpiYSpinBox->value(); +} + +void DPI_Chooser::setDPI(int dpiX, int dpiY) +{ + // Default to system if it is something weird + const bool valid = dpiX >= minDPI && dpiX <= maxDPI && dpiY >= minDPI && dpiY <= maxDPI; + if (!valid) { + m_predefinedCombo->setCurrentIndex(0); + return; + } + // Try to find the values among the predefined settings + const int count = m_predefinedCombo->count(); + int predefinedIndex = -1; + for (int i = 0; i < count; i++) { + const QVariant data = m_predefinedCombo->itemData(i); + if (data.type() != QVariant::Invalid) { + const struct DPI_Entry *entry = qvariant_cast<const struct DPI_Entry *>(data); + if (entry->dpiX == dpiX && entry->dpiY == dpiY) { + predefinedIndex = i; + break; + } + } + } + if (predefinedIndex != -1) { + m_predefinedCombo->setCurrentIndex(predefinedIndex); // triggers syncSpinBoxes() + } else { + setUserDefinedValues(dpiX, dpiY); + } +} + +void DPI_Chooser::setUserDefinedValues(int dpiX, int dpiY) +{ + const bool blocked = m_predefinedCombo->blockSignals(true); + m_predefinedCombo->setCurrentIndex(m_predefinedCombo->count() - 1); + m_predefinedCombo->blockSignals(blocked); + + m_dpiXSpinBox->setEnabled(true); + m_dpiYSpinBox->setEnabled(true); + m_dpiXSpinBox->setValue(dpiX); + m_dpiYSpinBox->setValue(dpiY); +} + +void DPI_Chooser::syncSpinBoxes() +{ + const int predefIdx = m_predefinedCombo->currentIndex(); + const QVariant data = m_predefinedCombo->itemData(predefIdx); + + // Predefined mode in which spin boxes are disabled or user defined? + const bool userSetting = data.type() == QVariant::Invalid; + m_dpiXSpinBox->setEnabled(userSetting); + m_dpiYSpinBox->setEnabled(userSetting); + + if (!userSetting) { + const struct DPI_Entry *entry = qvariant_cast<const struct DPI_Entry *>(data); + m_dpiXSpinBox->setValue(entry->dpiX); + m_dpiYSpinBox->setValue(entry->dpiY); + } +} +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/dpi_chooser.h b/tools/designer/src/components/formeditor/dpi_chooser.h new file mode 100644 index 0000000..f8ca810 --- /dev/null +++ b/tools/designer/src/components/formeditor/dpi_chooser.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of Qt Designer. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#ifndef DPICHOOSER_H +#define DPICHOOSER_H + +#include <QtGui/QWidget> + +QT_BEGIN_NAMESPACE + +class QSpinBox; +class QComboBox; + +namespace qdesigner_internal { + +struct DPI_Entry; + +/* Let the user choose a DPI settings */ +class DPI_Chooser : public QWidget { + Q_DISABLE_COPY(DPI_Chooser) + Q_OBJECT + +public: + explicit DPI_Chooser(QWidget *parent = 0); + ~DPI_Chooser(); + + void getDPI(int *dpiX, int *dpiY) const; + void setDPI(int dpiX, int dpiY); + +private slots: + void syncSpinBoxes(); + +private: + void setUserDefinedValues(int dpiX, int dpiY); + + struct DPI_Entry *m_systemEntry; + QComboBox *m_predefinedCombo; + QSpinBox *m_dpiXSpinBox; + QSpinBox *m_dpiYSpinBox; +}; +} + +QT_END_NAMESPACE + +#endif // DPICHOOSER_H diff --git a/tools/designer/src/components/formeditor/embeddedoptionspage.cpp b/tools/designer/src/components/formeditor/embeddedoptionspage.cpp new file mode 100644 index 0000000..1a41985 --- /dev/null +++ b/tools/designer/src/components/formeditor/embeddedoptionspage.cpp @@ -0,0 +1,453 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "embeddedoptionspage.h" +#include "deviceprofiledialog.h" +#include "widgetfactory_p.h" +#include "formwindowmanager.h" + +#include <deviceprofile_p.h> +#include <iconloader_p.h> +#include <shared_settings_p.h> +#include <abstractdialoggui_p.h> +#include <formwindowbase_p.h> + + +// SDK +#include <QtDesigner/QDesignerFormEditorInterface> +#include <QtDesigner/QDesignerFormWindowManagerInterface> + +#include <QtGui/QLabel> +#include <QtGui/QHBoxLayout> +#include <QtGui/QVBoxLayout> +#include <QtGui/QApplication> +#include <QtGui/QComboBox> +#include <QtGui/QToolButton> +#include <QtGui/QMessageBox> +#include <QtGui/QLabel> +#include <QtGui/QGroupBox> + +#include <QtCore/QSet> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +typedef QList<DeviceProfile> DeviceProfileList; + +enum { profileComboIndexOffset = 1 }; + +// Sort by name. Used by template, do not make it static! +bool deviceProfileLessThan(const DeviceProfile &d1, const DeviceProfile &d2) +{ + return d1.name().toLower() < d2.name().toLower(); +} + +static bool ask(QWidget *parent, + QDesignerDialogGuiInterface *dlgui, + const QString &title, + const QString &what) +{ + return dlgui->message(parent, QDesignerDialogGuiInterface::OtherMessage, + QMessageBox::Question, title, what, + QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::Yes; +} + +// ------------ EmbeddedOptionsControlPrivate +class EmbeddedOptionsControlPrivate { + Q_DISABLE_COPY(EmbeddedOptionsControlPrivate) +public: + EmbeddedOptionsControlPrivate(QDesignerFormEditorInterface *core); + void init(EmbeddedOptionsControl *q); + + bool isDirty() const { return m_dirty; } + + void loadSettings(); + void saveSettings(); + void slotAdd(); + void slotEdit(); + void slotDelete(); + void slotProfileIndexChanged(int); + +private: + QStringList existingProfileNames() const; + void sortAndPopulateProfileCombo(); + void updateState(); + void updateDescriptionLabel(); + + QDesignerFormEditorInterface *m_core; + QComboBox *m_profileCombo; + QToolButton *m_addButton; + QToolButton *m_editButton; + QToolButton *m_deleteButton; + QLabel *m_descriptionLabel; + + DeviceProfileList m_sortedProfiles; + EmbeddedOptionsControl *m_q; + bool m_dirty; + QSet<QString> m_usedProfiles; +}; + +EmbeddedOptionsControlPrivate::EmbeddedOptionsControlPrivate(QDesignerFormEditorInterface *core) : + m_core(core), + m_profileCombo(new QComboBox), + m_addButton(new QToolButton), + m_editButton(new QToolButton), + m_deleteButton(new QToolButton), + m_descriptionLabel(new QLabel), + m_q(0), + m_dirty(false) +{ + m_descriptionLabel->setMinimumHeight(80); + // Determine used profiles to lock them + const QDesignerFormWindowManagerInterface *fwm = core->formWindowManager(); + if (const int fwCount = fwm->formWindowCount()) { + for (int i = 0; i < fwCount; i++) + if (const FormWindowBase *fwb = qobject_cast<const FormWindowBase *>(fwm->formWindow(i))) { + const QString deviceProfileName = fwb->deviceProfileName(); + if (!deviceProfileName.isEmpty()) + m_usedProfiles.insert(deviceProfileName); + } + } +} + +void EmbeddedOptionsControlPrivate::init(EmbeddedOptionsControl *q) +{ + m_q = q; + QVBoxLayout *vLayout = new QVBoxLayout; + QHBoxLayout *hLayout = new QHBoxLayout; + m_profileCombo->setMinimumWidth(200); + m_profileCombo->setEditable(false); + hLayout->addWidget(m_profileCombo); + m_profileCombo->addItem(EmbeddedOptionsControl::tr("None")); + EmbeddedOptionsControl::connect(m_profileCombo, SIGNAL(currentIndexChanged(int)), m_q, SLOT(slotProfileIndexChanged(int))); + + m_addButton->setIcon(createIconSet(QString::fromUtf8("plus.png"))); + m_addButton->setToolTip(EmbeddedOptionsControl::tr("Add a profile")); + EmbeddedOptionsControl::connect(m_addButton, SIGNAL(clicked()), m_q, SLOT(slotAdd())); + hLayout->addWidget(m_addButton); + + EmbeddedOptionsControl::connect(m_editButton, SIGNAL(clicked()), m_q, SLOT(slotEdit())); + m_editButton->setIcon(createIconSet(QString::fromUtf8("edit.png"))); + m_editButton->setToolTip(EmbeddedOptionsControl::tr("Edit the selected profile")); + hLayout->addWidget(m_editButton); + + m_deleteButton->setIcon(createIconSet(QString::fromUtf8("minus.png"))); + m_deleteButton->setToolTip(EmbeddedOptionsControl::tr("Delete the selected profile")); + EmbeddedOptionsControl::connect(m_deleteButton, SIGNAL(clicked()), m_q, SLOT(slotDelete())); + hLayout->addWidget(m_deleteButton); + + hLayout->addStretch(); + vLayout->addLayout(hLayout); + vLayout->addWidget(m_descriptionLabel); + m_q->setLayout(vLayout); +} + +QStringList EmbeddedOptionsControlPrivate::existingProfileNames() const +{ + QStringList rc; + const DeviceProfileList::const_iterator dcend = m_sortedProfiles.constEnd(); + for (DeviceProfileList::const_iterator it = m_sortedProfiles.constBegin(); it != dcend; ++it) + rc.push_back(it->name()); + return rc; +} + +void EmbeddedOptionsControlPrivate::slotAdd() +{ + DeviceProfileDialog dlg(m_core->dialogGui(), m_q); + dlg.setWindowTitle(EmbeddedOptionsControl::tr("Add Profile")); + // Create a new profile with a new, unique name + DeviceProfile settings; + settings.fromSystem(); + dlg.setDeviceProfile(settings); + + const QStringList names = existingProfileNames(); + const QString newNamePrefix = EmbeddedOptionsControl::tr("New profile"); + QString newName = newNamePrefix; + for (int i = 2; names.contains(newName); i++) { + newName = newNamePrefix; + newName += QString::number(i); + } + + settings.setName(newName); + dlg.setDeviceProfile(settings); + if (dlg.showDialog(names)) { + const DeviceProfile newProfile = dlg.deviceProfile(); + m_sortedProfiles.push_back(newProfile); + // Maintain sorted order + sortAndPopulateProfileCombo(); + const int index = m_profileCombo->findText(newProfile.name()); + m_profileCombo->setCurrentIndex(index); + m_dirty = true; + } +} + +void EmbeddedOptionsControlPrivate::slotEdit() +{ + const int index = m_profileCombo->currentIndex() - profileComboIndexOffset; + if (index < 0) + return; + + // Edit the profile, compile a list of existing names + // excluding current one. re-insert if changed, + // re-sort if name changed. + const DeviceProfile oldProfile = m_sortedProfiles.at(index); + const QString oldName = oldProfile.name(); + QStringList names = existingProfileNames(); + names.removeAll(oldName); + + DeviceProfileDialog dlg(m_core->dialogGui(), m_q); + dlg.setWindowTitle(EmbeddedOptionsControl::tr("Edit Profile")); + dlg.setDeviceProfile(oldProfile); + if (dlg.showDialog(names)) { + const DeviceProfile newProfile = dlg.deviceProfile(); + if (newProfile != oldProfile) { + m_dirty = true; + m_sortedProfiles[index] = newProfile; + if (newProfile.name() != oldName) { + sortAndPopulateProfileCombo(); + const int index = m_profileCombo->findText(newProfile.name()); + m_profileCombo->setCurrentIndex(index); + } else { + updateDescriptionLabel(); + } + + } + } +} + +void EmbeddedOptionsControlPrivate::slotDelete() +{ + const int index = m_profileCombo->currentIndex() - profileComboIndexOffset; + if (index < 0) + return; + const QString name = m_sortedProfiles.at(index).name(); + if (ask(m_q, m_core->dialogGui(), + EmbeddedOptionsControl::tr("Delete Profile"), + EmbeddedOptionsControl::tr("Would you like to delete the profile '%1'?").arg(name))) { + m_profileCombo->setCurrentIndex(0); + m_sortedProfiles.removeAt(index); + m_profileCombo->removeItem(index + profileComboIndexOffset); + m_dirty = true; + } +} + +void EmbeddedOptionsControlPrivate::sortAndPopulateProfileCombo() +{ + // Clear items until only "None" is left + for (int i = m_profileCombo->count() - 1; i > 0; i--) + m_profileCombo->removeItem(i); + if (!m_sortedProfiles.empty()) { + qSort(m_sortedProfiles.begin(), m_sortedProfiles.end(), deviceProfileLessThan); + m_profileCombo->addItems(existingProfileNames()); + } +} + +void EmbeddedOptionsControlPrivate::loadSettings() +{ + const QDesignerSharedSettings settings(m_core); + m_sortedProfiles = settings.deviceProfiles(); + sortAndPopulateProfileCombo(); + // Index: 0 is "None" + const int settingsIndex = settings.currentDeviceProfileIndex(); + const int profileIndex = settingsIndex >= 0 && settingsIndex < m_sortedProfiles.size() ? settingsIndex + profileComboIndexOffset : 0; + m_profileCombo->setCurrentIndex(profileIndex); + updateState(); + m_dirty = false; +} + +void EmbeddedOptionsControlPrivate::saveSettings() +{ + QDesignerSharedSettings settings(m_core); + settings.setDeviceProfiles(m_sortedProfiles); + // Index: 0 is "None" + settings.setCurrentDeviceProfileIndex(m_profileCombo->currentIndex() - profileComboIndexOffset); + m_dirty = false; +} + +//: Format embedded device profile description +static const char *descriptionFormat = QT_TRANSLATE_NOOP("EmbeddedOptionsControl", +"<html>" +"<table>" +"<tr><td><b>Font</b></td><td>%1, %2</td></tr>" +"<tr><td><b>Style</b></td><td>%3</td></tr>" +"<tr><td><b>Resolution</b></td><td>%4 x %5</td></tr>" +"</table>" +"</html>"); + +static inline QString description(const DeviceProfile& p) +{ + QString styleName = p.style(); + if (styleName.isEmpty()) + styleName = EmbeddedOptionsControl::tr("Default"); + return EmbeddedOptionsControl::tr(descriptionFormat). + arg(p.fontFamily()).arg(p.fontPointSize()).arg(styleName).arg(p.dpiX()).arg(p.dpiY()); +} + +void EmbeddedOptionsControlPrivate::updateDescriptionLabel() +{ + const int profileIndex = m_profileCombo->currentIndex() - profileComboIndexOffset; + if (profileIndex >= 0) { + m_descriptionLabel->setText(description(m_sortedProfiles.at(profileIndex))); + } else { + m_descriptionLabel->clear(); + } +} + +void EmbeddedOptionsControlPrivate::updateState() +{ + const int profileIndex = m_profileCombo->currentIndex() - profileComboIndexOffset; + // Allow for changing/deleting only if it is not in use + bool modifyEnabled = false; + if (profileIndex >= 0) + modifyEnabled = !m_usedProfiles.contains(m_sortedProfiles.at(profileIndex).name()); + m_editButton->setEnabled(modifyEnabled); + m_deleteButton->setEnabled(modifyEnabled); + updateDescriptionLabel(); +} + +void EmbeddedOptionsControlPrivate::slotProfileIndexChanged(int) +{ + updateState(); + m_dirty = true; +} + +// ------------- EmbeddedOptionsControl +EmbeddedOptionsControl::EmbeddedOptionsControl(QDesignerFormEditorInterface *core, QWidget *parent) : + QWidget(parent), + m_d(new EmbeddedOptionsControlPrivate(core)) +{ + m_d->init(this); +} + +EmbeddedOptionsControl::~EmbeddedOptionsControl() +{ + delete m_d; +} + +void EmbeddedOptionsControl::slotAdd() +{ + m_d->slotAdd(); +} + +void EmbeddedOptionsControl::slotEdit() +{ + m_d->slotEdit(); +} + +void EmbeddedOptionsControl::slotDelete() +{ + m_d->slotDelete(); +} + +void EmbeddedOptionsControl::loadSettings() +{ + m_d->loadSettings(); +} + +void EmbeddedOptionsControl::saveSettings() +{ + m_d->saveSettings(); +} + +void EmbeddedOptionsControl::slotProfileIndexChanged(int i) +{ + m_d->slotProfileIndexChanged(i); +} + +bool EmbeddedOptionsControl::isDirty() const +{ + return m_d->isDirty(); +} + +// EmbeddedOptionsPage: +EmbeddedOptionsPage::EmbeddedOptionsPage(QDesignerFormEditorInterface *core) : + m_core(core) +{ +} + +QString EmbeddedOptionsPage::name() const +{ + //: Tab in preferences dialog + return QCoreApplication::translate("EmbeddedOptionsPage", "Embedded Design"); +} + +QWidget *EmbeddedOptionsPage::createPage(QWidget *parent) +{ + QWidget *optionsWidget = new QWidget(parent); + + QVBoxLayout *optionsVLayout = new QVBoxLayout(); + + //: EmbeddedOptionsControl group box" + QGroupBox *gb = new QGroupBox(QCoreApplication::translate("EmbeddedOptionsPage", "Device Profiles")); + QVBoxLayout *gbVLayout = new QVBoxLayout(); + m_embeddedOptionsControl = new EmbeddedOptionsControl(m_core); + m_embeddedOptionsControl->loadSettings(); + gbVLayout->addWidget(m_embeddedOptionsControl); + gb->setLayout(gbVLayout); + optionsVLayout->addWidget(gb); + + optionsVLayout->addStretch(1); + + // Outer layout to give it horizontal stretch + QHBoxLayout *optionsHLayout = new QHBoxLayout(); + optionsHLayout->addLayout(optionsVLayout); + optionsHLayout->addStretch(1); + optionsWidget->setLayout(optionsHLayout); + return optionsWidget; +} + +void EmbeddedOptionsPage::apply() +{ + if (!m_embeddedOptionsControl || !m_embeddedOptionsControl->isDirty()) + return; + + m_embeddedOptionsControl->saveSettings(); + if (FormWindowManager *fw = qobject_cast<qdesigner_internal::FormWindowManager *>(m_core->formWindowManager())) + fw->deviceProfilesChanged(); +} + +void EmbeddedOptionsPage::finish() +{ +} +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/embeddedoptionspage.h b/tools/designer/src/components/formeditor/embeddedoptionspage.h new file mode 100644 index 0000000..6b76d38 --- /dev/null +++ b/tools/designer/src/components/formeditor/embeddedoptionspage.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef EMBEDDEDOPTIONSPAGE_H +#define EMBEDDEDOPTIONSPAGE_H + +#include <QtDesigner/private/abstractoptionspage_p.h> +#include <QtCore/QPointer> +#include <QtGui/QWidget> + +QT_BEGIN_NAMESPACE + +class QDesignerFormEditorInterface; + +namespace qdesigner_internal { + +class EmbeddedOptionsControlPrivate; + +/* EmbeddedOptions Control. Presents the user with a list of embedded + * device profiles he can modify/add/delete. */ +class EmbeddedOptionsControl : public QWidget { + Q_DISABLE_COPY(EmbeddedOptionsControl) + Q_OBJECT +public: + explicit EmbeddedOptionsControl(QDesignerFormEditorInterface *core, QWidget *parent = 0); + ~EmbeddedOptionsControl(); + + bool isDirty() const; + +public slots: + void loadSettings(); + void saveSettings(); + +private slots: + void slotAdd(); + void slotEdit(); + void slotDelete(); + void slotProfileIndexChanged(int); + +private: + EmbeddedOptionsControlPrivate *m_d; +}; + +// EmbeddedOptionsPage +class EmbeddedOptionsPage : public QDesignerOptionsPageInterface +{ + Q_DISABLE_COPY(EmbeddedOptionsPage) +public: + explicit EmbeddedOptionsPage(QDesignerFormEditorInterface *core); + + QString name() const; + QWidget *createPage(QWidget *parent); + virtual void finish(); + virtual void apply(); + +private: + QDesignerFormEditorInterface *m_core; + QPointer<EmbeddedOptionsControl> m_embeddedOptionsControl; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // EMBEDDEDOPTIONSPAGE_H diff --git a/tools/designer/src/components/formeditor/formeditor.cpp b/tools/designer/src/components/formeditor/formeditor.cpp new file mode 100644 index 0000000..b09ffab --- /dev/null +++ b/tools/designer/src/components/formeditor/formeditor.cpp @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "formeditor.h" +#include "formeditor_optionspage.h" +#include "embeddedoptionspage.h" +#include "templateoptionspage.h" +#include "metadatabase_p.h" +#include "widgetdatabase_p.h" +#include "widgetfactory_p.h" +#include "formwindowmanager.h" +#include "qmainwindow_container.h" +#include "qworkspace_container.h" +#include "qmdiarea_container.h" +#include "qwizard_container.h" +#include "default_container.h" +#include "default_layoutdecoration.h" +#include "default_actionprovider.h" +#include "qlayoutwidget_propertysheet.h" +#include "spacer_propertysheet.h" +#include "line_propertysheet.h" +#include "layout_propertysheet.h" +#include "qdesigner_stackedbox_p.h" +#include "qdesigner_toolbox_p.h" +#include "qdesigner_tabwidget_p.h" +#include "qtbrushmanager.h" +#include "brushmanagerproxy.h" +#include "iconcache.h" +#include "qtresourcemodel_p.h" +#include "qdesigner_integration_p.h" +#include "itemview_propertysheet.h" + +// sdk +#include <QtDesigner/QExtensionManager> + +// shared +#include <pluginmanager_p.h> +#include <qdesigner_taskmenu_p.h> +#include <qdesigner_membersheet_p.h> +#include <qdesigner_promotion_p.h> +#include <dialoggui_p.h> +#include <qdesigner_introspection_p.h> +#include <qdesigner_qsettings_p.h> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +FormEditor::FormEditor(QObject *parent) + : QDesignerFormEditorInterface(parent) +{ + setIntrospection(new QDesignerIntrospection); + setDialogGui(new DialogGui); + QDesignerPluginManager *pluginManager = new QDesignerPluginManager(this); + setPluginManager(pluginManager); + + WidgetDataBase *widgetDatabase = new WidgetDataBase(this, this); + setWidgetDataBase(widgetDatabase); + + MetaDataBase *metaDataBase = new MetaDataBase(this, this); + setMetaDataBase(metaDataBase); + + WidgetFactory *widgetFactory = new WidgetFactory(this, this); + setWidgetFactory(widgetFactory); + + FormWindowManager *formWindowManager = new FormWindowManager(this, this); + setFormManager(formWindowManager); + connect(formWindowManager, SIGNAL(formWindowAdded(QDesignerFormWindowInterface*)), widgetFactory, SLOT(formWindowAdded(QDesignerFormWindowInterface*))); + connect(formWindowManager, SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)), widgetFactory, SLOT(activeFormWindowChanged(QDesignerFormWindowInterface*))); + + QExtensionManager *mgr = new QExtensionManager(this); + const QString containerExtensionId = Q_TYPEID(QDesignerContainerExtension); + + QDesignerStackedWidgetContainerFactory::registerExtension(mgr, containerExtensionId); + QDesignerTabWidgetContainerFactory::registerExtension(mgr, containerExtensionId); + QDesignerToolBoxContainerFactory::registerExtension(mgr, containerExtensionId); + QMainWindowContainerFactory::registerExtension(mgr, containerExtensionId); + QDockWidgetContainerFactory::registerExtension(mgr, containerExtensionId); + QScrollAreaContainerFactory::registerExtension(mgr, containerExtensionId); + QWorkspaceContainerFactory::registerExtension(mgr, containerExtensionId); + QMdiAreaContainerFactory::registerExtension(mgr, containerExtensionId); + QWizardContainerFactory::registerExtension(mgr, containerExtensionId); + + mgr->registerExtensions(new QDesignerLayoutDecorationFactory(mgr), + Q_TYPEID(QDesignerLayoutDecorationExtension)); + + const QString actionProviderExtensionId = Q_TYPEID(QDesignerActionProviderExtension); + QToolBarActionProviderFactory::registerExtension(mgr, actionProviderExtensionId); + QMenuBarActionProviderFactory::registerExtension(mgr, actionProviderExtensionId); + QMenuActionProviderFactory::registerExtension(mgr, actionProviderExtensionId); + + QDesignerDefaultPropertySheetFactory::registerExtension(mgr); + QLayoutWidgetPropertySheetFactory::registerExtension(mgr); + SpacerPropertySheetFactory::registerExtension(mgr); + LinePropertySheetFactory::registerExtension(mgr); + LayoutPropertySheetFactory::registerExtension(mgr); + QStackedWidgetPropertySheetFactory::registerExtension(mgr); + QToolBoxWidgetPropertySheetFactory::registerExtension(mgr); + QTabWidgetPropertySheetFactory::registerExtension(mgr); + QMdiAreaPropertySheetFactory::registerExtension(mgr); + QWorkspacePropertySheetFactory::registerExtension(mgr); + QWizardPagePropertySheetFactory::registerExtension(mgr); + QWizardPropertySheetFactory::registerExtension(mgr); + + QTreeViewPropertySheetFactory::registerExtension(mgr); + QTableViewPropertySheetFactory::registerExtension(mgr); + + const QString internalTaskMenuId = QLatin1String("QDesignerInternalTaskMenuExtension"); + QDesignerTaskMenuFactory::registerExtension(mgr, internalTaskMenuId); + + mgr->registerExtensions(new QDesignerMemberSheetFactory(mgr), + Q_TYPEID(QDesignerMemberSheetExtension)); + + setExtensionManager(mgr); + + setIconCache(new IconCache(this)); + + QtBrushManager *brushManager = new QtBrushManager(this); + setBrushManager(brushManager); + + BrushManagerProxy *brushProxy = new BrushManagerProxy(this, this); + brushProxy->setBrushManager(brushManager); + setPromotion(new QDesignerPromotion(this)); + + QtResourceModel *resourceModel = new QtResourceModel(this); + setResourceModel(resourceModel); + connect(resourceModel, SIGNAL(qrcFileModifiedExternally(const QString &)), + this, SLOT(slotQrcFileChangedExternally(const QString &))); + + QList<QDesignerOptionsPageInterface*> optionsPages; + optionsPages << new TemplateOptionsPage(this) << new FormEditorOptionsPage(this) << new EmbeddedOptionsPage(this); + setOptionsPages(optionsPages); + + setSettingsManager(new QDesignerQSettings()); +} + +FormEditor::~FormEditor() +{ +} + +void FormEditor::slotQrcFileChangedExternally(const QString &path) +{ + QDesignerIntegration *designerIntegration = qobject_cast<QDesignerIntegration *>(integration()); + if (!designerIntegration) + return; + + QDesignerIntegration::ResourceFileWatcherBehaviour behaviour = designerIntegration->resourceFileWatcherBehaviour(); + if (behaviour == QDesignerIntegration::NoWatcher) { + return; + } else if (behaviour == QDesignerIntegration::PromptAndReload) { + QMessageBox::StandardButton button = dialogGui()->message(topLevel(), QDesignerDialogGuiInterface::FileChangedMessage, QMessageBox::Warning, + tr("Resource File Changed"), + tr("The file \"%1\" has changed outside Designer. Do you want to reload it?").arg(path), + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + + if (button != QMessageBox::Yes) + return; + } + + resourceModel()->reload(path); +} + +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/formeditor.h b/tools/designer/src/components/formeditor/formeditor.h new file mode 100644 index 0000000..2e0b819 --- /dev/null +++ b/tools/designer/src/components/formeditor/formeditor.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FORMEDITOR_H +#define FORMEDITOR_H + +#include "formeditor_global.h" + +#include <QtDesigner/QDesignerFormEditorInterface> + +QT_BEGIN_NAMESPACE + +class QObject; + +namespace qdesigner_internal { + +class QT_FORMEDITOR_EXPORT FormEditor: public QDesignerFormEditorInterface +{ + Q_OBJECT +public: + FormEditor(QObject *parent = 0); + virtual ~FormEditor(); +public slots: + void slotQrcFileChangedExternally(const QString &path); +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // FORMEDITOR_H diff --git a/tools/designer/src/components/formeditor/formeditor.pri b/tools/designer/src/components/formeditor/formeditor.pri new file mode 100644 index 0000000..bbe96d5 --- /dev/null +++ b/tools/designer/src/components/formeditor/formeditor.pri @@ -0,0 +1,75 @@ + +QT += xml + +INCLUDEPATH += $$PWD + +FORMS += $$PWD/deviceprofiledialog.ui \ + $$PWD/formwindowsettings.ui \ + $$PWD/templateoptionspage.ui + +HEADERS += $$PWD/qdesigner_resource.h \ + $$PWD/formwindow.h \ + $$PWD/formwindow_widgetstack.h \ + $$PWD/formwindow_dnditem.h \ + $$PWD/formwindowcursor.h \ + $$PWD/widgetselection.h \ + $$PWD/formwindowmanager.h \ + $$PWD/formeditor.h \ + $$PWD/formeditor_global.h \ + $$PWD/qlayoutwidget_propertysheet.h \ + $$PWD/layout_propertysheet.h \ + $$PWD/spacer_propertysheet.h \ + $$PWD/line_propertysheet.h \ + $$PWD/default_container.h \ + $$PWD/default_actionprovider.h \ + $$PWD/qmainwindow_container.h \ + $$PWD/qworkspace_container.h \ + $$PWD/qmdiarea_container.h \ + $$PWD/qwizard_container.h \ + $$PWD/default_layoutdecoration.h \ + $$PWD/qtbrushmanager.h \ + $$PWD/brushmanagerproxy.h \ + $$PWD/iconcache.h \ + $$PWD/tool_widgeteditor.h \ + $$PWD/formeditor_optionspage.h \ + $$PWD/embeddedoptionspage.h \ + $$PWD/formwindowsettings.h \ + $$PWD/deviceprofiledialog.h \ + $$PWD/dpi_chooser.h \ + $$PWD/previewactiongroup.h \ + $$PWD/itemview_propertysheet.h \ + $$PWD/templateoptionspage.h + +SOURCES += $$PWD/qdesigner_resource.cpp \ + $$PWD/formwindow.cpp \ + $$PWD/formwindow_widgetstack.cpp \ + $$PWD/formwindow_dnditem.cpp \ + $$PWD/formwindowcursor.cpp \ + $$PWD/widgetselection.cpp \ + $$PWD/formwindowmanager.cpp \ + $$PWD/formeditor.cpp \ + $$PWD/qlayoutwidget_propertysheet.cpp \ + $$PWD/layout_propertysheet.cpp \ + $$PWD/spacer_propertysheet.cpp \ + $$PWD/line_propertysheet.cpp \ + $$PWD/qmainwindow_container.cpp \ + $$PWD/qworkspace_container.cpp \ + $$PWD/qmdiarea_container.cpp \ + $$PWD/qwizard_container.cpp \ + $$PWD/default_container.cpp \ + $$PWD/default_layoutdecoration.cpp \ + $$PWD/default_actionprovider.cpp \ + $$PWD/tool_widgeteditor.cpp \ + $$PWD/qtbrushmanager.cpp \ + $$PWD/brushmanagerproxy.cpp \ + $$PWD/iconcache.cpp \ + $$PWD/formeditor_optionspage.cpp \ + $$PWD/embeddedoptionspage.cpp \ + $$PWD/formwindowsettings.cpp \ + $$PWD/deviceprofiledialog.cpp \ + $$PWD/dpi_chooser.cpp \ + $$PWD/previewactiongroup.cpp \ + $$PWD/itemview_propertysheet.cpp \ + $$PWD/templateoptionspage.cpp + +RESOURCES += $$PWD/formeditor.qrc diff --git a/tools/designer/src/components/formeditor/formeditor.qrc b/tools/designer/src/components/formeditor/formeditor.qrc new file mode 100644 index 0000000..83cc9c7 --- /dev/null +++ b/tools/designer/src/components/formeditor/formeditor.qrc @@ -0,0 +1,173 @@ +<RCC> + <qresource prefix="/trolltech/formeditor"> + <file>images/submenu.png</file> + <file>images/cursors/arrow.png</file> + <file>images/cursors/busy.png</file> + <file>images/cursors/closedhand.png</file> + <file>images/cursors/cross.png</file> + <file>images/cursors/hand.png</file> + <file>images/cursors/hsplit.png</file> + <file>images/cursors/ibeam.png</file> + <file>images/cursors/no.png</file> + <file>images/cursors/openhand.png</file> + <file>images/cursors/sizeall.png</file> + <file>images/cursors/sizeb.png</file> + <file>images/cursors/sizef.png</file> + <file>images/cursors/sizeh.png</file> + <file>images/cursors/sizev.png</file> + <file>images/cursors/uparrow.png</file> + <file>images/cursors/vsplit.png</file> + <file>images/cursors/wait.png</file> + <file>images/cursors/whatsthis.png</file> + <file>images/emptyicon.png</file> + <file>images/filenew-16.png</file> + <file>images/fileopen-16.png</file> + <file>images/editdelete-16.png</file> + <file>images/plus-16.png</file> + <file>images/minus-16.png</file> + <file>images/prefix-add.png</file> + <file>images/downplus.png</file> + <file>images/leveldown.png</file> + <file>images/levelup.png</file> + <file>images/mac/adjustsize.png</file> + <file>images/mac/widgettool.png</file> + <file>images/mac/signalslottool.png</file> + <file>images/mac/tabordertool.png</file> + <file>images/mac/buddytool.png</file> + <file>images/mac/editbreaklayout.png</file> + <file>images/mac/editcopy.png</file> + <file>images/mac/editcut.png</file> + <file>images/mac/editdelete.png</file> + <file>images/mac/editgrid.png</file> + <file>images/mac/editform.png</file> + <file>images/mac/edithlayout.png</file> + <file>images/mac/edithlayoutsplit.png</file> + <file>images/mac/editlower.png</file> + <file>images/mac/editpaste.png</file> + <file>images/mac/editraise.png</file> + <file>images/mac/editvlayout.png</file> + <file>images/mac/editvlayoutsplit.png</file> + <file>images/mac/filenew.png</file> + <file>images/mac/insertimage.png</file> + <file>images/mac/undo.png</file> + <file>images/mac/redo.png</file> + <file>images/mac/fileopen.png</file> + <file>images/mac/filesave.png</file> + <file>images/mac/resourceeditortool.png</file> + <file>images/mac/plus.png</file> + <file>images/mac/minus.png</file> + <file>images/mac/back.png</file> + <file>images/mac/forward.png</file> + <file>images/mac/down.png</file> + <file>images/mac/up.png</file> + <file>images/qtlogo.png</file> + <file>images/qt3logo.png</file> + <file>images/resetproperty.png</file> + <file>images/sort.png</file> + <file>images/edit.png</file> + <file>images/reload.png</file> + <file>images/configure.png</file> + <file>images/color.png</file> + <file>images/dropdownbutton.png</file> + <file>images/widgets/calendarwidget.png</file> + <file>images/widgets/checkbox.png</file> + <file>images/widgets/columnview.png</file> + <file>images/widgets/combobox.png</file> + <file>images/widgets/commandlinkbutton.png</file> + <file>images/widgets/dateedit.png</file> + <file>images/widgets/datetimeedit.png</file> + <file>images/widgets/dial.png</file> + <file>images/widgets/dialogbuttonbox.png</file> + <file>images/widgets/dockwidget.png</file> + <file>images/widgets/doublespinbox.png</file> + <file>images/widgets/fontcombobox.png</file> + <file>images/widgets/frame.png</file> + <file>images/widgets/graphicsview.png</file> + <file>images/widgets/groupbox.png</file> + <file>images/widgets/hscrollbar.png</file> + <file>images/widgets/hslider.png</file> + <file>images/widgets/hsplit.png</file> + <file>images/widgets/label.png</file> + <file>images/widgets/lcdnumber.png</file> + <file>images/widgets/line.png</file> + <file>images/widgets/lineedit.png</file> + <file>images/widgets/listbox.png</file> + <file>images/widgets/listview.png</file> + <file>images/widgets/mdiarea.png</file> + <file>images/widgets/plaintextedit.png</file> + <file>images/widgets/progress.png</file> + <file>images/widgets/pushbutton.png</file> + <file>images/widgets/radiobutton.png</file> + <file>images/widgets/scrollarea.png</file> + <file>images/widgets/spacer.png</file> + <file>images/widgets/spinbox.png</file> + <file>images/widgets/table.png</file> + <file>images/widgets/tabwidget.png</file> + <file>images/widgets/textedit.png</file> + <file>images/widgets/timeedit.png</file> + <file>images/widgets/toolbox.png</file> + <file>images/widgets/toolbutton.png</file> + <file>images/widgets/vline.png</file> + <file>images/widgets/vscrollbar.png</file> + <file>images/widgets/vslider.png</file> + <file>images/widgets/vspacer.png</file> + <file>images/widgets/widget.png</file> + <file>images/widgets/widget.png</file> + <file>images/widgets/widgetstack.png</file> + <file>images/widgets/wizard.png</file> + <file>images/win/adjustsize.png</file> + <file>images/win/widgettool.png</file> + <file>images/win/signalslottool.png</file> + <file>images/win/tabordertool.png</file> + <file>images/win/buddytool.png</file> + <file>images/win/editbreaklayout.png</file> + <file>images/win/editcopy.png</file> + <file>images/win/editcut.png</file> + <file>images/win/editdelete.png</file> + <file>images/win/editgrid.png</file> + <file>images/win/editform.png</file> + <file>images/win/edithlayout.png</file> + <file>images/win/edithlayoutsplit.png</file> + <file>images/win/editlower.png</file> + <file>images/win/editpaste.png</file> + <file>images/win/editraise.png</file> + <file>images/win/editvlayout.png</file> + <file>images/win/editvlayoutsplit.png</file> + <file>images/win/filenew.png</file> + <file>images/win/insertimage.png</file> + <file>images/win/undo.png</file> + <file>images/win/redo.png</file> + <file>images/win/fileopen.png</file> + <file>images/win/filesave.png</file> + <file>images/win/resourceeditortool.png</file> + <file>images/win/plus.png</file> + <file>images/win/minus.png</file> + <file>images/win/textanchor.png</file> + <file>images/win/textbold.png</file> + <file>images/win/textitalic.png</file> + <file>images/win/textunder.png</file> + <file>images/win/textleft.png</file> + <file>images/win/textcenter.png</file> + <file>images/win/textright.png</file> + <file>images/win/textjustify.png</file> + <file>images/win/textsuperscript.png</file> + <file>images/win/textsubscript.png</file> + <file>images/win/back.png</file> + <file>images/win/forward.png</file> + <file>images/win/down.png</file> + <file>images/win/up.png</file> + <file>images/mac/textanchor.png</file> + <file>images/mac/textbold.png</file> + <file>images/mac/textitalic.png</file> + <file>images/mac/textunder.png</file> + <file>images/mac/textleft.png</file> + <file>images/mac/textcenter.png</file> + <file>images/mac/textright.png</file> + <file>images/mac/textjustify.png</file> + <file>images/mac/textsuperscript.png</file> + <file>images/mac/textsubscript.png</file> + </qresource> + <qresource prefix="/trolltech/brushes"> + <file>defaultbrushes.xml</file> + </qresource> +</RCC> diff --git a/tools/designer/src/components/formeditor/formeditor_global.h b/tools/designer/src/components/formeditor/formeditor_global.h new file mode 100644 index 0000000..0195f1b --- /dev/null +++ b/tools/designer/src/components/formeditor/formeditor_global.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FORMEDITOR_GLOBAL_H +#define FORMEDITOR_GLOBAL_H + +#include <QtCore/qglobal.h> + +#ifdef Q_OS_WIN +#ifdef QT_FORMEDITOR_LIBRARY +# define QT_FORMEDITOR_EXPORT +#else +# define QT_FORMEDITOR_EXPORT +#endif +#else +#define QT_FORMEDITOR_EXPORT +#endif + +#endif // FORMEDITOR_GLOBAL_H diff --git a/tools/designer/src/components/formeditor/formeditor_optionspage.cpp b/tools/designer/src/components/formeditor/formeditor_optionspage.cpp new file mode 100644 index 0000000..0b20531 --- /dev/null +++ b/tools/designer/src/components/formeditor/formeditor_optionspage.cpp @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "formeditor_optionspage.h" + +// shared +#include "formwindowbase_p.h" +#include "gridpanel_p.h" +#include "grid_p.h" +#include "previewconfigurationwidget_p.h" +#include "shared_settings_p.h" +#include "zoomwidget_p.h" + +// SDK +#include <QtDesigner/QDesignerFormEditorInterface> +#include <QtDesigner/QDesignerFormWindowManagerInterface> + +#include <QtCore/QString> +#include <QtCore/QCoreApplication> +#include <QtGui/QGroupBox> +#include <QtGui/QVBoxLayout> +#include <QtGui/QFormLayout> +#include <QtGui/QComboBox> + +QT_BEGIN_NAMESPACE + +typedef QList<int> IntList; + +namespace qdesigner_internal { + +// Zoom, currently for preview only +class ZoomSettingsWidget : public QGroupBox { + Q_DISABLE_COPY(ZoomSettingsWidget) +public: + explicit ZoomSettingsWidget(QWidget *parent = 0); + + void fromSettings(const QDesignerSharedSettings &s); + void toSettings(QDesignerSharedSettings &s) const; + +private: + QComboBox *m_zoomCombo; +}; + +ZoomSettingsWidget::ZoomSettingsWidget(QWidget *parent) : + QGroupBox(parent), + m_zoomCombo(new QComboBox) +{ + m_zoomCombo->setEditable(false); + const IntList zoomValues = ZoomMenu::zoomValues(); + const IntList::const_iterator cend = zoomValues.constEnd(); + //: Zoom percentage + for (IntList::const_iterator it = zoomValues.constBegin(); it != cend; ++it) + m_zoomCombo->addItem(QCoreApplication::translate("FormEditorOptionsPage", "%1 %").arg(*it), QVariant(*it)); + + // Layout + setCheckable(true); + setTitle(QCoreApplication::translate("FormEditorOptionsPage", "Preview Zoom")); + QFormLayout *lt = new QFormLayout; + lt->addRow(QCoreApplication::translate("FormEditorOptionsPage", "Default Zoom"), m_zoomCombo); + setLayout(lt); +} + +void ZoomSettingsWidget::fromSettings(const QDesignerSharedSettings &s) +{ + setChecked(s.zoomEnabled()); + const int idx = m_zoomCombo->findData(QVariant(s.zoom())); + m_zoomCombo->setCurrentIndex(qMax(0, idx)); +} + +void ZoomSettingsWidget::toSettings(QDesignerSharedSettings &s) const +{ + s.setZoomEnabled(isChecked()); + const int zoom = m_zoomCombo->itemData(m_zoomCombo->currentIndex()).toInt(); + s.setZoom(zoom); +} + + + +// FormEditorOptionsPage: +FormEditorOptionsPage::FormEditorOptionsPage(QDesignerFormEditorInterface *core) + : m_core(core) +{ +} + +QString FormEditorOptionsPage::name() const +{ + //: Tab in preferences dialog + return QCoreApplication::translate("FormEditorOptionsPage", "Forms"); +} + +QWidget *FormEditorOptionsPage::createPage(QWidget *parent) +{ + QWidget *optionsWidget = new QWidget(parent); + + const QDesignerSharedSettings settings(m_core); + m_previewConf = new PreviewConfigurationWidget(m_core); + m_zoomSettingsWidget = new ZoomSettingsWidget; + m_zoomSettingsWidget->fromSettings(settings); + + m_defaultGridConf = new GridPanel(); + m_defaultGridConf->setTitle(QCoreApplication::translate("FormEditorOptionsPage", "Default Grid")); + m_defaultGridConf->setGrid(settings.defaultGrid()); + + QVBoxLayout *optionsVLayout = new QVBoxLayout(); + optionsVLayout->addWidget(m_defaultGridConf); + optionsVLayout->addWidget(m_previewConf); + optionsVLayout->addWidget(m_zoomSettingsWidget); + optionsVLayout->addStretch(1); + + // Outer layout to give it horizontal stretch + QHBoxLayout *optionsHLayout = new QHBoxLayout(); + optionsHLayout->addLayout(optionsVLayout); + optionsHLayout->addStretch(1); + optionsWidget->setLayout(optionsHLayout); + + return optionsWidget; +} + +void FormEditorOptionsPage::apply() +{ + QDesignerSharedSettings settings(m_core); + if (m_defaultGridConf) { + const Grid defaultGrid = m_defaultGridConf->grid(); + settings.setDefaultGrid(defaultGrid); + + FormWindowBase::setDefaultDesignerGrid(defaultGrid); + // Update grid settings in all existing form windows + QDesignerFormWindowManagerInterface *fwm = m_core->formWindowManager(); + if (const int numWindows = fwm->formWindowCount()) { + for (int i = 0; i < numWindows; i++) + if (qdesigner_internal::FormWindowBase *fwb + = qobject_cast<qdesigner_internal::FormWindowBase *>( fwm->formWindow(i))) + if (!fwb->hasFormGrid()) + fwb->setDesignerGrid(defaultGrid); + } + } + if (m_previewConf) { + m_previewConf->saveState(); + } + + if (m_zoomSettingsWidget) + m_zoomSettingsWidget->toSettings(settings); +} + +void FormEditorOptionsPage::finish() +{ +} + +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/formeditor_optionspage.h b/tools/designer/src/components/formeditor/formeditor_optionspage.h new file mode 100644 index 0000000..4aeda6a --- /dev/null +++ b/tools/designer/src/components/formeditor/formeditor_optionspage.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FORMEDITOR_OPTIONSPAGE_H +#define FORMEDITOR_OPTIONSPAGE_H + +#include <QtDesigner/private/abstractoptionspage_p.h> +#include <QtCore/QPointer> + +QT_BEGIN_NAMESPACE + +class QDesignerFormEditorInterface; + +namespace qdesigner_internal { + +class PreviewConfigurationWidget; +class GridPanel; +class ZoomSettingsWidget; + +class FormEditorOptionsPage : public QDesignerOptionsPageInterface +{ +public: + explicit FormEditorOptionsPage(QDesignerFormEditorInterface *core); + + QString name() const; + QWidget *createPage(QWidget *parent); + virtual void apply(); + virtual void finish(); + +private: + QDesignerFormEditorInterface *m_core; + QPointer<PreviewConfigurationWidget> m_previewConf; + QPointer<GridPanel> m_defaultGridConf; + QPointer<ZoomSettingsWidget> m_zoomSettingsWidget; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // FORMEDITOR_OPTIONSPAGE_H diff --git a/tools/designer/src/components/formeditor/formwindow.cpp b/tools/designer/src/components/formeditor/formwindow.cpp new file mode 100644 index 0000000..07d785a --- /dev/null +++ b/tools/designer/src/components/formeditor/formwindow.cpp @@ -0,0 +1,2917 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "formwindow.h" +#include "formeditor.h" +#include "formwindow_dnditem.h" +#include "formwindow_widgetstack.h" +#include "formwindowcursor.h" +#include "formwindowmanager.h" +#include "tool_widgeteditor.h" +#include "widgetselection.h" +#include "qtresourcemodel_p.h" +#include "widgetfactory_p.h" + +// shared +#include <metadatabase_p.h> +#include <qdesigner_tabwidget_p.h> +#include <qdesigner_toolbox_p.h> +#include <qdesigner_stackedbox_p.h> +#include <qdesigner_resource.h> +#include <qdesigner_command_p.h> +#include <qdesigner_command2_p.h> +#include <qdesigner_propertycommand_p.h> +#include <qdesigner_taskmenu_p.h> +#include <qdesigner_widget_p.h> +#include <qdesigner_utils_p.h> +#include <qlayout_widget_p.h> +#include <spacer_widget_p.h> +#include <invisible_widget_p.h> +#include <layoutinfo_p.h> +#include <qdesigner_objectinspector_p.h> +#include <connectionedit_p.h> +#include <actionprovider_p.h> +#include <ui4_p.h> +#include <deviceprofile_p.h> +#include <shared_settings_p.h> +#include <grid_p.h> + +#include <QtDesigner/QExtensionManager> +#include <QtDesigner/QDesignerWidgetDataBaseInterface> +#include <QtDesigner/QDesignerPropertySheetExtension> +#include <QtDesigner/QDesignerWidgetFactoryInterface> +#include <QtDesigner/QDesignerContainerExtension> +#include <QtDesigner/QDesignerTaskMenuExtension> +#include <QtDesigner/QDesignerWidgetBoxInterface> +#include <abstractdialoggui_p.h> + +#include <QtCore/QtDebug> +#include <QtCore/QBuffer> +#include <QtCore/QTimer> +#include <QtCore/QXmlStreamReader> +#include <QtGui/QMenu> +#include <QtGui/QAction> +#include <QtGui/QActionGroup> +#include <QtGui/QClipboard> +#include <QtGui/QUndoGroup> +#include <QtGui/QScrollArea> +#include <QtGui/QRubberBand> +#include <QtGui/QApplication> +#include <QtGui/QSplitter> +#include <QtGui/QPainter> +#include <QtGui/QGroupBox> +#include <QtGui/QDockWidget> +#include <QtGui/QToolBox> +#include <QtGui/QStackedWidget> +#include <QtGui/QTabWidget> +#include <QtGui/QButtonGroup> + +Q_DECLARE_METATYPE(QWidget*) + +QT_BEGIN_NAMESPACE + +namespace { +class BlockSelection +{ +public: + BlockSelection(qdesigner_internal::FormWindow *fw) + : m_formWindow(fw), + m_blocked(m_formWindow->blockSelectionChanged(true)) + { + } + + ~BlockSelection() + { + if (m_formWindow) + m_formWindow->blockSelectionChanged(m_blocked); + } + +private: + QPointer<qdesigner_internal::FormWindow> m_formWindow; + const bool m_blocked; +}; + +enum { debugFormWindow = 0 }; +} + +namespace qdesigner_internal { + +// ------------------------ FormWindow::Selection +// Maintains a pool of WidgetSelections to be used for selected widgets. + +class FormWindow::Selection +{ +public: + Selection(); + ~Selection(); + + // Clear + void clear(); + + // Also clear out the pool. Call if reparenting of the main container occurs. + void clearSelectionPool(); + + void repaintSelection(QWidget *w); + void repaintSelection(); + + bool isWidgetSelected(QWidget *w) const; + QWidgetList selectedWidgets() const; + + WidgetSelection *addWidget(FormWindow* fw, QWidget *w); + // remove widget, return new current widget or 0 + QWidget* removeWidget(QWidget *w); + + void raiseList(const QWidgetList& l); + void raiseWidget(QWidget *w); + + void updateGeometry(QWidget *w); + + void hide(QWidget *w); + void show(QWidget *w); + +private: + + typedef QList<WidgetSelection *> SelectionPool; + SelectionPool m_selectionPool; + + typedef QHash<QWidget *, WidgetSelection *> SelectionHash; + SelectionHash m_usedSelections; +}; + +FormWindow::Selection::Selection() +{ +} + +FormWindow::Selection::~Selection() +{ + clearSelectionPool(); +} + +void FormWindow::Selection::clear() +{ + if (!m_usedSelections.empty()) { + const SelectionHash::iterator mend = m_usedSelections.end(); + for (SelectionHash::iterator it = m_usedSelections.begin(); it != mend; ++it) { + it.value()->setWidget(0); + } + m_usedSelections.clear(); + } +} + +void FormWindow::Selection::clearSelectionPool() +{ + clear(); + qDeleteAll(m_selectionPool); + m_selectionPool.clear(); +} + +WidgetSelection *FormWindow::Selection::addWidget(FormWindow* fw, QWidget *w) +{ + WidgetSelection *rc = m_usedSelections.value(w); + if (rc != 0) { + rc->show(); + rc->updateActive(); + return rc; + } + // find a free one in the pool + const SelectionPool::iterator pend = m_selectionPool.end(); + for (SelectionPool::iterator it = m_selectionPool.begin(); it != pend; ++it) { + if (! (*it)->isUsed()) { + rc = *it; + break; + } + } + + if (rc == 0) { + rc = new WidgetSelection(fw); + m_selectionPool.push_back(rc); + } + + m_usedSelections.insert(w, rc); + rc->setWidget(w); + return rc; +} + +QWidget* FormWindow::Selection::removeWidget(QWidget *w) +{ + WidgetSelection *s = m_usedSelections.value(w); + if (!s) + return w; + + s->setWidget(0); + m_usedSelections.remove(w); + + if (m_usedSelections.isEmpty()) + return 0; + + return (*m_usedSelections.begin())->widget(); +} + +void FormWindow::Selection::repaintSelection(QWidget *w) +{ + if (WidgetSelection *s = m_usedSelections.value(w)) + s->update(); +} + +void FormWindow::Selection::repaintSelection() +{ + const SelectionHash::iterator mend = m_usedSelections.end(); + for (SelectionHash::iterator it = m_usedSelections.begin(); it != mend; ++it) { + it.value()->update(); + } +} + +bool FormWindow::Selection::isWidgetSelected(QWidget *w) const{ + return m_usedSelections.contains(w); +} + +QWidgetList FormWindow::Selection::selectedWidgets() const +{ + return m_usedSelections.keys(); +} + +void FormWindow::Selection::raiseList(const QWidgetList& l) +{ + const SelectionHash::iterator mend = m_usedSelections.end(); + for (SelectionHash::iterator it = m_usedSelections.begin(); it != mend; ++it) { + WidgetSelection *w = it.value(); + if (l.contains(w->widget())) + w->show(); + } +} + +void FormWindow::Selection::raiseWidget(QWidget *w) +{ + if (WidgetSelection *s = m_usedSelections.value(w)) + s->show(); +} + +void FormWindow::Selection::updateGeometry(QWidget *w) +{ + if (WidgetSelection *s = m_usedSelections.value(w)) { + s->updateGeometry(); + } +} + +void FormWindow::Selection::hide(QWidget *w) +{ + if (WidgetSelection *s = m_usedSelections.value(w)) + s->hide(); +} + +void FormWindow::Selection::show(QWidget *w) +{ + if (WidgetSelection *s = m_usedSelections.value(w)) + s->show(); +} + +// ------------------------ FormWindow +FormWindow::FormWindow(FormEditor *core, QWidget *parent, Qt::WindowFlags flags) : + FormWindowBase(core, parent, flags), + m_mouseState(NoMouseState), + m_core(core), + m_selection(new Selection), + m_widgetStack(new FormWindowWidgetStack(this)), + m_contextMenuPosition(-1, -1) +{ + // Apply settings to formcontainer + deviceProfile().apply(core, m_widgetStack->formContainer(), qdesigner_internal::DeviceProfile::ApplyFormParent); + + setLayout(m_widgetStack->layout()); + init(); + + m_cursor = new FormWindowCursor(this, this); + + core->formWindowManager()->addFormWindow(this); + + setDirty(false); + setAcceptDrops(true); +} + +FormWindow::~FormWindow() +{ + Q_ASSERT(core() != 0); + Q_ASSERT(core()->metaDataBase() != 0); + Q_ASSERT(core()->formWindowManager() != 0); + + core()->formWindowManager()->removeFormWindow(this); + core()->metaDataBase()->remove(this); + + QWidgetList l = widgets(); + foreach (QWidget *w, l) + core()->metaDataBase()->remove(w); + + m_widgetStack = 0; + m_rubberBand = 0; + if (resourceSet()) + core()->resourceModel()->removeResourceSet(resourceSet()); + delete m_selection; +} + +QDesignerFormEditorInterface *FormWindow::core() const +{ + return m_core; +} + +QDesignerFormWindowCursorInterface *FormWindow::cursor() const +{ + return m_cursor; +} + +void FormWindow::updateWidgets() +{ + if (!m_mainContainer) + return; +} + +int FormWindow::widgetDepth(const QWidget *w) +{ + int d = -1; + while (w && !w->isWindow()) { + d++; + w = w->parentWidget(); + } + + return d; +} + +bool FormWindow::isChildOf(const QWidget *c, const QWidget *p) +{ + while (c) { + if (c == p) + return true; + c = c->parentWidget(); + } + return false; +} + +void FormWindow::setCursorToAll(const QCursor &c, QWidget *start) +{ +#ifndef QT_NO_CURSOR + start->setCursor(c); + const QWidgetList widgets = qFindChildren<QWidget*>(start); + foreach (QWidget *widget, widgets) { + if (!qobject_cast<WidgetHandle*>(widget)) { + widget->setCursor(c); + } + } +#endif +} + +void FormWindow::init() +{ + if (FormWindowManager *manager = qobject_cast<FormWindowManager*> (core()->formWindowManager())) { + m_commandHistory = new QUndoStack(this); + manager->undoGroup()->addStack(m_commandHistory); + } + + m_blockSelectionChanged = false; + + m_defaultMargin = INT_MIN; + m_defaultSpacing = INT_MIN; + + connect(m_widgetStack, SIGNAL(currentToolChanged(int)), this, SIGNAL(toolChanged(int))); + + m_selectionChangedTimer = new QTimer(this); + m_selectionChangedTimer->setSingleShot(true); + connect(m_selectionChangedTimer, SIGNAL(timeout()), this, SLOT(selectionChangedTimerDone())); + + m_checkSelectionTimer = new QTimer(this); + m_checkSelectionTimer->setSingleShot(true); + connect(m_checkSelectionTimer, SIGNAL(timeout()), this, SLOT(checkSelectionNow())); + + m_geometryChangedTimer = new QTimer(this); + m_geometryChangedTimer->setSingleShot(true); + connect(m_geometryChangedTimer, SIGNAL(timeout()), this, SIGNAL(geometryChanged())); + + m_rubberBand = 0; + + setFocusPolicy(Qt::StrongFocus); + + m_mainContainer = 0; + m_currentWidget = 0; + + connect(m_commandHistory, SIGNAL(indexChanged(int)), this, SLOT(updateDirty())); + connect(m_commandHistory, SIGNAL(indexChanged(int)), this, SIGNAL(changed())); + connect(m_commandHistory, SIGNAL(indexChanged(int)), this, SLOT(checkSelection())); + + core()->metaDataBase()->add(this); + + initializeCoreTools(); + + QAction *a = new QAction(this); + a->setText(tr("Edit contents")); + a->setShortcut(tr("F2")); + connect(a, SIGNAL(triggered()), this, SLOT(editContents())); + addAction(a); +} + +QWidget *FormWindow::mainContainer() const +{ + return m_mainContainer; +} + + +void FormWindow::clearMainContainer() +{ + if (m_mainContainer) { + setCurrentTool(0); + m_widgetStack->setMainContainer(0); + core()->metaDataBase()->remove(m_mainContainer); + unmanageWidget(m_mainContainer); + delete m_mainContainer; + m_mainContainer = 0; + } +} + +void FormWindow::setMainContainer(QWidget *w) +{ + if (w == m_mainContainer) { + // nothing to do + return; + } + + clearMainContainer(); + + m_mainContainer = w; + const QSize sz = m_mainContainer->size(); + + m_widgetStack->setMainContainer(m_mainContainer); + m_widgetStack->setCurrentTool(m_widgetEditor); + + setCurrentWidget(m_mainContainer); + manageWidget(m_mainContainer); + + if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), m_mainContainer)) { + sheet->setVisible(sheet->indexOf(QLatin1String("windowTitle")), true); + sheet->setVisible(sheet->indexOf(QLatin1String("windowIcon")), true); + sheet->setVisible(sheet->indexOf(QLatin1String("windowModality")), true); + sheet->setVisible(sheet->indexOf(QLatin1String("windowFilePath")), true); + // ### generalize + } + + m_mainContainer->setFocusPolicy(Qt::StrongFocus); + m_mainContainer->resize(sz); + + emit mainContainerChanged(m_mainContainer); +} + +QWidget *FormWindow::findTargetContainer(QWidget *widget) const +{ + Q_ASSERT(widget); + + while (QWidget *parentWidget = widget->parentWidget()) { + if (LayoutInfo::layoutType(m_core, parentWidget) == LayoutInfo::NoLayout && isManaged(widget)) + return widget; + + widget = parentWidget; + } + + return mainContainer(); +} + +static inline void clearObjectInspectorSelection(const QDesignerFormEditorInterface *core) +{ + if (QDesignerObjectInspector *oi = qobject_cast<QDesignerObjectInspector *>(core->objectInspector())) + oi->clearSelection(); +} + +// Find a parent of a desired selection state +static QWidget *findSelectedParent(QDesignerFormWindowInterface *fw, const QWidget *w, bool selected) +{ + const QDesignerFormWindowCursorInterface *cursor = fw->cursor(); + QWidget *mainContainer = fw->mainContainer(); + for (QWidget *p = w->parentWidget(); p && p != mainContainer; p = p->parentWidget()) + if (fw->isManaged(p)) + if (cursor->isWidgetSelected(p) == selected) + return p; + return 0; +} + +// Mouse modifiers. + +enum MouseFlags { ToggleSelectionModifier = 0x1, CycleParentModifier=0x2, CopyDragModifier=0x4 }; + +static inline unsigned mouseFlags(Qt::KeyboardModifiers mod) +{ + switch (mod) { + case Qt::ShiftModifier: + return CycleParentModifier; + break; +#ifdef Q_WS_MAC + case Qt::AltModifier: // "Alt" or "option" key on Mac means copy + return CopyDragModifier; +#endif + case Qt::ControlModifier: + return CopyDragModifier|ToggleSelectionModifier; + break; + default: + break; + } + return 0; +} + +// Handle the click selection: Do toggling/cycling +// of parents according to the modifiers. +void FormWindow::handleClickSelection(QWidget *managedWidget, unsigned mouseMode) +{ + const bool sameWidget = managedWidget == m_lastClickedWidget; + m_lastClickedWidget = managedWidget; + + const bool selected = isWidgetSelected(managedWidget); + if (debugFormWindow) + qDebug() << "handleClickSelection" << managedWidget << " same=" << sameWidget << " mouse= " << mouseMode << " selected=" << selected; + + // // toggle selection state of widget + if (mouseMode & ToggleSelectionModifier) { + selectWidget(managedWidget, !selected); + return; + } + + QWidget *selectionCandidate = 0; + // Hierarchy cycling: If the same widget clicked again: Attempt to cycle + // trough the hierarchy. Find the next currently selected parent + if (sameWidget && (mouseMode & CycleParentModifier)) + if (QWidget *currentlySelectedParent = selected ? managedWidget : findSelectedParent(this, managedWidget, true)) + selectionCandidate = findSelectedParent(this, currentlySelectedParent, false); + // Not the same widget, list wrapped over or there was no unselected parent + if (!selectionCandidate && !selected) + selectionCandidate = managedWidget; + + if (selectionCandidate) + selectSingleWidget(selectionCandidate); +} + +void FormWindow::selectSingleWidget(QWidget *w) +{ + clearSelection(false); + selectWidget(w, true); + raiseChildSelections(w); +} + +bool FormWindow::handleMousePressEvent(QWidget * widget, QWidget *managedWidget, QMouseEvent *e) +{ + m_mouseState = NoMouseState; + m_startPos = QPoint(); + e->accept(); + + BlockSelection blocker(this); + + if (core()->formWindowManager()->activeFormWindow() != this) + core()->formWindowManager()->setActiveFormWindow(this); + + const Qt::MouseButtons buttons = e->buttons(); + if (buttons != Qt::LeftButton && buttons != Qt::MidButton) + return true; + + m_startPos = mapFromGlobal(e->globalPos()); + + if (debugFormWindow) + qDebug() << "handleMousePressEvent:" << widget << ',' << managedWidget; + + if (buttons == Qt::MidButton || isMainContainer(managedWidget) == true) { // press was on the formwindow + clearObjectInspectorSelection(m_core); // We might have a toolbar or non-widget selected in the object inspector. + clearSelection(false); + + m_mouseState = MouseDrawRubber; + m_currRect = QRect(); + startRectDraw(mapFromGlobal(e->globalPos()), this, Rubber); + return true; + } + if (buttons != Qt::LeftButton) + return true; + + const unsigned mouseMode = mouseFlags(e->modifiers()); + + /* Normally, we want to be able to click /select-on-press to drag away + * the widget in the next step. However, in the case of a widget which + * itself or whose parent is selected, we defer the selection to the + * release event. + * This is to prevent children from being dragged away from layouts + * when their layouts are selected and one wants to move the layout. + * Note that toggle selection is only deferred if the widget is already + * selected, so, it is still possible to just Ctrl+Click and CopyDrag. */ + const bool deferSelection = isWidgetSelected(managedWidget) || findSelectedParent(this, managedWidget, true); + if (deferSelection) { + m_mouseState = MouseDeferredSelection; + } else { + // Cycle the parent unless we explicitly want toggle + const unsigned effectiveMouseMode = (mouseMode & ToggleSelectionModifier) ? mouseMode : static_cast<unsigned>(CycleParentModifier); + handleClickSelection(managedWidget, effectiveMouseMode); + } + return true; +} + +// We can drag widget in managed layouts except splitter. +static bool canDragWidgetInLayout(const QDesignerFormEditorInterface *core, QWidget *w) +{ + bool managed; + const LayoutInfo::Type type = LayoutInfo::laidoutWidgetType(core ,w, &managed); + if (!managed) + return false; + switch (type) { + case LayoutInfo::NoLayout: + case LayoutInfo::HSplitter: + case LayoutInfo::VSplitter: + return false; + default: + break; + } + return true; +} + +bool FormWindow::handleMouseMoveEvent(QWidget *, QWidget *, QMouseEvent *e) +{ + e->accept(); + if (m_startPos.isNull()) + return true; + + const QPoint pos = mapFromGlobal(e->globalPos()); + + switch (m_mouseState) { + case MouseDrawRubber: // Rubber band with left/middle mouse + continueRectDraw(pos, this, Rubber); + return true; + case MouseMoveDrag: // Spurious move event after drag started? + return true; + default: + break; + } + + if (e->buttons() != Qt::LeftButton) + return true; + + const bool canStartDrag = (m_startPos - pos).manhattanLength() > QApplication::startDragDistance(); + + if (canStartDrag == false) { + // nothing to do + return true; + } + + m_mouseState = MouseMoveDrag; + const bool blocked = blockSelectionChanged(true); + + QWidgetList sel = selectedWidgets(); + simplifySelection(&sel); + + QSet<QWidget*> widget_set; + + foreach (QWidget *child, sel) { // Move parent layout or container? + QWidget *current = child; + + bool done = false; + while (!isMainContainer(current) && !done) { + if (!isManaged(current)) { + current = current->parentWidget(); + continue; + } else if (LayoutInfo::isWidgetLaidout(core(), current)) { + // Go up to parent of layout if shift pressed, else do that only for splitters + if (!canDragWidgetInLayout(core(), current)) { + current = current->parentWidget(); + continue; + } + } + done = true; + } + + if (current == mainContainer()) + continue; + + widget_set.insert(current); + } + + sel = widget_set.toList(); + QDesignerFormWindowCursorInterface *c = cursor(); + QWidget *current = c->current(); + if (sel.contains(current)) { + sel.removeAll(current); + sel.prepend(current); + } + + QList<QDesignerDnDItemInterface*> item_list; + const QPoint globalPos = mapToGlobal(m_startPos); + const QDesignerDnDItemInterface::DropType dropType = (mouseFlags(e->modifiers()) & CopyDragModifier) ? + QDesignerDnDItemInterface::CopyDrop : QDesignerDnDItemInterface::MoveDrop; + foreach (QWidget *widget, sel) { + item_list.append(new FormWindowDnDItem(dropType, this, widget, globalPos)); + if (dropType == QDesignerDnDItemInterface::MoveDrop) { + m_selection->hide(widget); + widget->hide(); + } + } + + blockSelectionChanged(blocked); + + if (!sel.empty()) // reshow selection? + if (QDesignerMimeData::execDrag(item_list, core()->topLevel()) == Qt::IgnoreAction && dropType == QDesignerDnDItemInterface::MoveDrop) + foreach (QWidget *widget, sel) + m_selection->show(widget); + + m_startPos = QPoint(); + + return true; +} + +bool FormWindow::handleMouseReleaseEvent(QWidget *w, QWidget *mw, QMouseEvent *e) +{ + const MouseState oldState = m_mouseState; + m_mouseState = NoMouseState; + + if (debugFormWindow) + qDebug() << "handleMouseeleaseEvent:" << w << ',' << mw << "state=" << oldState; + + if (oldState == MouseDoubleClicked) + return true; + + e->accept(); + + switch (oldState) { + case MouseDrawRubber: { // we were drawing a rubber selection + endRectDraw(); // get rid of the rectangle + const bool blocked = blockSelectionChanged(true); + selectWidgets(); // select widgets which intersect the rect + blockSelectionChanged(blocked); + } + break; + // Deferred select: Select the child here unless the parent was moved. + case MouseDeferredSelection: + handleClickSelection(mw, mouseFlags(e->modifiers())); + break; + default: + break; + } + + m_startPos = QPoint(); + + /* Inform about selection changes (left/mid or context menu). Also triggers + * in the case of an empty rubber drag that cleared the selection in + * MousePressEvent. */ + switch (e->button()) { + case Qt::LeftButton: + case Qt::MidButton: + case Qt::RightButton: + emitSelectionChanged(); + break; + default: + break; + } + + return true; +} + +void FormWindow::checkPreviewGeometry(QRect &r) +{ + if (!rect().contains(r)) { + if (r.left() < rect().left()) + r.moveTopLeft(QPoint(0, r.top())); + if (r.right() > rect().right()) + r.moveBottomRight(QPoint(rect().right(), r.bottom())); + if (r.top() < rect().top()) + r.moveTopLeft(QPoint(r.left(), rect().top())); + if (r.bottom() > rect().bottom()) + r.moveBottomRight(QPoint(r.right(), rect().bottom())); + } +} + +void FormWindow::startRectDraw(const QPoint &pos, QWidget *, RectType t) +{ + m_rectAnchor = (t == Insert) ? designerGrid().snapPoint(pos) : pos; + + m_currRect = QRect(m_rectAnchor, QSize(0, 0)); + if (!m_rubberBand) + m_rubberBand = new QRubberBand(QRubberBand::Rectangle, this); + m_rubberBand->setGeometry(m_currRect); + m_rubberBand->show(); +} + +void FormWindow::continueRectDraw(const QPoint &pos, QWidget *, RectType t) +{ + const QPoint p2 = (t == Insert) ? designerGrid().snapPoint(pos) : pos; + + QRect r(m_rectAnchor, p2); + r = r.normalized(); + + if (m_currRect == r) + return; + + if (r.width() > 1 || r.height() > 1) { + m_currRect = r; + if (m_rubberBand) + m_rubberBand->setGeometry(m_currRect); + } +} + +void FormWindow::endRectDraw() +{ + if (m_rubberBand) { + delete m_rubberBand; + m_rubberBand = 0; + } +} + +QWidget *FormWindow::currentWidget() const +{ + return m_currentWidget; +} + +bool FormWindow::setCurrentWidget(QWidget *currentWidget) +{ + if (debugFormWindow) + qDebug() << "setCurrentWidget:" << m_currentWidget << " --> " << currentWidget; + if (currentWidget == m_currentWidget) + return false; + // repaint the old widget unless it is the main window + if (m_currentWidget && m_currentWidget != mainContainer()) { + m_selection->repaintSelection(m_currentWidget); + } + // set new and repaint + m_currentWidget = currentWidget; + if (m_currentWidget && m_currentWidget != mainContainer()) { + m_selection->repaintSelection(m_currentWidget); + } + return true; +} + +void FormWindow::selectWidget(QWidget* w, bool select) +{ + if (trySelectWidget(w, select)) + emitSelectionChanged(); +} + +// Selects a widget and determines the new current one. Returns true if a change occurs. +bool FormWindow::trySelectWidget(QWidget *w, bool select) +{ + if (debugFormWindow) + qDebug() << "trySelectWidget:" << w << select; + if (!isManaged(w) && !isCentralWidget(w)) + return false; + + if (!select && !isWidgetSelected(w)) + return false; + + if (!mainContainer()) + return false; + + if (isMainContainer(w) || isCentralWidget(w)) { + setCurrentWidget(mainContainer()); + return true; + } + + if (select) { + setCurrentWidget(w); + m_selection->addWidget(this, w); + } else { + QWidget *newCurrent = m_selection->removeWidget(w); + if (!newCurrent) + newCurrent = mainContainer(); + setCurrentWidget(newCurrent); + } + return true; +} + +void FormWindow::clearSelection(bool changePropertyDisplay) +{ + if (debugFormWindow) + qDebug() << "clearSelection(" << changePropertyDisplay << ')'; + // At all events, we need a current widget. + m_selection->clear(); + setCurrentWidget(mainContainer()); + + if (changePropertyDisplay) + emitSelectionChanged(); +} + +void FormWindow::emitSelectionChanged() +{ + if (m_blockSelectionChanged == true) { + // nothing to do + return; + } + + m_selectionChangedTimer->start(0); +} + +void FormWindow::selectionChangedTimerDone() +{ + emit selectionChanged(); +} + +bool FormWindow::isWidgetSelected(QWidget *w) const +{ + return m_selection->isWidgetSelected(w); +} + +bool FormWindow::isMainContainer(const QWidget *w) const +{ + return w && (w == this || w == mainContainer()); +} + +void FormWindow::updateChildSelections(QWidget *w) +{ + const QWidgetList l = qFindChildren<QWidget*>(w); + if (!l.empty()) { + const QWidgetList::const_iterator lcend = l.constEnd(); + for (QWidgetList::const_iterator it = l.constBegin(); it != lcend; ++it) { + QWidget *w = *it; + if (isManaged(w)) + updateSelection(w); + } + } +} + +void FormWindow::repaintSelection() +{ + m_selection->repaintSelection(); +} + +void FormWindow::raiseSelection(QWidget *w) +{ + m_selection->raiseWidget(w); +} + +void FormWindow::updateSelection(QWidget *w) +{ + if (!w->isVisibleTo(this)) { + selectWidget(w, false); + } else { + m_selection->updateGeometry(w); + } +} + +QWidget *FormWindow::designerWidget(QWidget *w) const +{ + while ((w && !isMainContainer(w) && !isManaged(w)) || isCentralWidget(w)) + w = w->parentWidget(); + + return w; +} + +bool FormWindow::isCentralWidget(QWidget *w) const +{ + if (QMainWindow *mainWindow = qobject_cast<QMainWindow*>(mainContainer())) + return w == mainWindow->centralWidget(); + + return false; +} + +void FormWindow::ensureUniqueObjectName(QObject *object) +{ + QString name = object->objectName(); + if (name.isEmpty()) { + QDesignerWidgetDataBaseInterface *db = core()->widgetDataBase(); + if (QDesignerWidgetDataBaseItemInterface *item = db->item(db->indexOfObject(object))) + name = qdesigner_internal::qtify(item->name()); + } + unify(object, name, true); + object->setObjectName(name); +} + +template <class Iterator> +static inline void insertNames(const QDesignerMetaDataBaseInterface *metaDataBase, + Iterator it, const Iterator &end, + QObject *excludedObject, QSet<QString> &nameSet) +{ + for ( ; it != end; ++it) + if (excludedObject != *it && metaDataBase->item(*it)) + nameSet.insert((*it)->objectName()); +} + +static QSet<QString> languageKeywords() +{ + static QSet<QString> keywords; + if (keywords.isEmpty()) { + // C++ keywords + keywords.insert(QLatin1String("asm")); + keywords.insert(QLatin1String("auto")); + keywords.insert(QLatin1String("bool")); + keywords.insert(QLatin1String("break")); + keywords.insert(QLatin1String("case")); + keywords.insert(QLatin1String("catch")); + keywords.insert(QLatin1String("char")); + keywords.insert(QLatin1String("class")); + keywords.insert(QLatin1String("const")); + keywords.insert(QLatin1String("const_cast")); + keywords.insert(QLatin1String("continue")); + keywords.insert(QLatin1String("default")); + keywords.insert(QLatin1String("delete")); + keywords.insert(QLatin1String("do")); + keywords.insert(QLatin1String("double")); + keywords.insert(QLatin1String("dynamic_cast")); + keywords.insert(QLatin1String("else")); + keywords.insert(QLatin1String("enum")); + keywords.insert(QLatin1String("explicit")); + keywords.insert(QLatin1String("export")); + keywords.insert(QLatin1String("extern")); + keywords.insert(QLatin1String("false")); + keywords.insert(QLatin1String("float")); + keywords.insert(QLatin1String("for")); + keywords.insert(QLatin1String("friend")); + keywords.insert(QLatin1String("goto")); + keywords.insert(QLatin1String("if")); + keywords.insert(QLatin1String("inline")); + keywords.insert(QLatin1String("int")); + keywords.insert(QLatin1String("long")); + keywords.insert(QLatin1String("mutable")); + keywords.insert(QLatin1String("namespace")); + keywords.insert(QLatin1String("new")); + keywords.insert(QLatin1String("NULL")); + keywords.insert(QLatin1String("operator")); + keywords.insert(QLatin1String("private")); + keywords.insert(QLatin1String("protected")); + keywords.insert(QLatin1String("public")); + keywords.insert(QLatin1String("register")); + keywords.insert(QLatin1String("reinterpret_cast")); + keywords.insert(QLatin1String("return")); + keywords.insert(QLatin1String("short")); + keywords.insert(QLatin1String("signed")); + keywords.insert(QLatin1String("sizeof")); + keywords.insert(QLatin1String("static")); + keywords.insert(QLatin1String("static_cast")); + keywords.insert(QLatin1String("struct")); + keywords.insert(QLatin1String("switch")); + keywords.insert(QLatin1String("template")); + keywords.insert(QLatin1String("this")); + keywords.insert(QLatin1String("throw")); + keywords.insert(QLatin1String("true")); + keywords.insert(QLatin1String("try")); + keywords.insert(QLatin1String("typedef")); + keywords.insert(QLatin1String("typeid")); + keywords.insert(QLatin1String("typename")); + keywords.insert(QLatin1String("union")); + keywords.insert(QLatin1String("unsigned")); + keywords.insert(QLatin1String("using")); + keywords.insert(QLatin1String("virtual")); + keywords.insert(QLatin1String("void")); + keywords.insert(QLatin1String("volatile")); + keywords.insert(QLatin1String("wchar_t")); + keywords.insert(QLatin1String("while")); + + // java keywords + keywords.insert(QLatin1String("abstract")); + keywords.insert(QLatin1String("assert")); + keywords.insert(QLatin1String("boolean")); + keywords.insert(QLatin1String("break")); + keywords.insert(QLatin1String("byte")); + keywords.insert(QLatin1String("case")); + keywords.insert(QLatin1String("catch")); + keywords.insert(QLatin1String("char")); + keywords.insert(QLatin1String("class")); + keywords.insert(QLatin1String("const")); + keywords.insert(QLatin1String("continue")); + keywords.insert(QLatin1String("default")); + keywords.insert(QLatin1String("do")); + keywords.insert(QLatin1String("double")); + keywords.insert(QLatin1String("else")); + keywords.insert(QLatin1String("enum")); + keywords.insert(QLatin1String("extends")); + keywords.insert(QLatin1String("false")); + keywords.insert(QLatin1String("final")); + keywords.insert(QLatin1String("finality")); + keywords.insert(QLatin1String("float")); + keywords.insert(QLatin1String("for")); + keywords.insert(QLatin1String("goto")); + keywords.insert(QLatin1String("if")); + keywords.insert(QLatin1String("implements")); + keywords.insert(QLatin1String("import")); + keywords.insert(QLatin1String("instanceof")); + keywords.insert(QLatin1String("int")); + keywords.insert(QLatin1String("interface")); + keywords.insert(QLatin1String("long")); + keywords.insert(QLatin1String("native")); + keywords.insert(QLatin1String("new")); + keywords.insert(QLatin1String("null")); + keywords.insert(QLatin1String("package")); + keywords.insert(QLatin1String("private")); + keywords.insert(QLatin1String("protected")); + keywords.insert(QLatin1String("public")); + keywords.insert(QLatin1String("return")); + keywords.insert(QLatin1String("short")); + keywords.insert(QLatin1String("static")); + keywords.insert(QLatin1String("strictfp")); + keywords.insert(QLatin1String("super")); + keywords.insert(QLatin1String("switch")); + keywords.insert(QLatin1String("synchronized")); + keywords.insert(QLatin1String("this")); + keywords.insert(QLatin1String("throw")); + keywords.insert(QLatin1String("throws")); + keywords.insert(QLatin1String("transient")); + keywords.insert(QLatin1String("true")); + keywords.insert(QLatin1String("try")); + keywords.insert(QLatin1String("void")); + keywords.insert(QLatin1String("volatile")); + keywords.insert(QLatin1String("while")); + } + return keywords; +} + +bool FormWindow::unify(QObject *w, QString &s, bool changeIt) +{ + typedef QSet<QString> StringSet; + + QWidget *main = mainContainer(); + if (!main) + return true; + + StringSet existingNames = languageKeywords(); + // build a set of existing names of other widget excluding self + if (!(w->isWidgetType() && isMainContainer(qobject_cast<QWidget*>(w)))) + existingNames.insert(main->objectName()); + + const QDesignerMetaDataBaseInterface *metaDataBase = core()->metaDataBase(); + const QWidgetList widgetChildren = qFindChildren<QWidget*>(main); + if (!widgetChildren.empty()) + insertNames(metaDataBase, widgetChildren.constBegin(), widgetChildren.constEnd(), w, existingNames); + + const QList<QLayout *> layoutChildren = qFindChildren<QLayout*>(main); + if (!layoutChildren.empty()) + insertNames(metaDataBase, layoutChildren.constBegin(), layoutChildren.constEnd(), w, existingNames); + + const QList<QAction *> actionChildren = qFindChildren<QAction*>(main); + if (!actionChildren.empty()) + insertNames(metaDataBase, actionChildren.constBegin(), actionChildren.constEnd(), w, existingNames); + + const QList<QButtonGroup *> buttonGroupChildren = qFindChildren<QButtonGroup*>(main); + if (!buttonGroupChildren.empty()) + insertNames(metaDataBase, buttonGroupChildren.constBegin(), buttonGroupChildren.constEnd(), w, existingNames); + + const StringSet::const_iterator enEnd = existingNames.constEnd(); + if (existingNames.constFind(s) == enEnd) + return true; + else + if (!changeIt) + return false; + + // split 'name_number' + qlonglong num = 0; + qlonglong factor = 1; + int idx = s.length()-1; + const ushort zeroUnicode = QLatin1Char('0').unicode(); + for ( ; idx > 0 && s.at(idx).isDigit(); --idx) { + num += (s.at(idx).unicode() - zeroUnicode) * factor; + factor *= 10; + } + // Position index past '_'. + const QChar underscore = QLatin1Char('_'); + if (idx >= 0 && s.at(idx) == underscore) { + idx++; + } else { + num = 1; + s += underscore; + idx = s.length(); + } + // try 'name_n', 'name_n+1' + for (num++ ; ;num++) { + s.truncate(idx); + s += QString::number(num); + if (existingNames.constFind(s) == enEnd) + break; + } + return false; +} +/* already_in_form is true when we are moving a widget from one parent to another inside the same + * form. All this means is that InsertWidgetCommand::undo() must not unmanage it. */ + +void FormWindow::insertWidget(QWidget *w, const QRect &rect, QWidget *container, bool already_in_form) +{ + clearSelection(false); + + beginCommand(tr("Insert widget '%1'").arg(WidgetFactory::classNameOf(m_core, w))); // ### use the WidgetDatabaseItem + + /* Reparenting into a QSplitter automatically adjusts child's geometry. We create the geometry + * command before we push the reparent command, so that the geometry command has the original + * geometry of the widget. */ + QRect r = rect; + Q_ASSERT(r.isValid()); + SetPropertyCommand *geom_cmd = new SetPropertyCommand(this); + geom_cmd->init(w, QLatin1String("geometry"), r); // ### use rc.size() + + if (w->parentWidget() != container) { + ReparentWidgetCommand *cmd = new ReparentWidgetCommand(this); + cmd->init(w, container); + m_commandHistory->push(cmd); + } + + m_commandHistory->push(geom_cmd); + + InsertWidgetCommand *cmd = new InsertWidgetCommand(this); + cmd->init(w, already_in_form); + m_commandHistory->push(cmd); + + endCommand(); + + w->show(); +} + +QWidget *FormWindow::createWidget(DomUI *ui, const QRect &rc, QWidget *target) +{ + QWidget *container = findContainer(target, false); + if (!container) + return 0; + if (isMainContainer(container)) { + if (QMainWindow *mw = qobject_cast<QMainWindow*>(container)) { + Q_ASSERT(mw->centralWidget() != 0); + container = mw->centralWidget(); + } + } + QDesignerResource resource(this); + const FormBuilderClipboard clipboard = resource.paste(ui, container); + if (clipboard.m_widgets.size() != 1) // multiple-paste from DomUI not supported yet + return 0; + QWidget *widget = clipboard.m_widgets.first(); + insertWidget(widget, rc, container); + return widget; +} + +#ifndef QT_NO_DEBUG +static bool isDescendant(const QWidget *parent, const QWidget *child) +{ + for (; child != 0; child = child->parentWidget()) { + if (child == parent) + return true; + } + return false; +} +#endif + +void FormWindow::resizeWidget(QWidget *widget, const QRect &geometry) +{ + Q_ASSERT(isDescendant(this, widget)); + + QRect r = geometry; + if (m_lastIndex > m_commandHistory->index()) + m_lastIndex = -1; + SetPropertyCommand *cmd = new SetPropertyCommand(this); + cmd->init(widget, QLatin1String("geometry"), r); + cmd->setText(tr("Resize")); + m_commandHistory->push(cmd); +} + +void FormWindow::raiseChildSelections(QWidget *w) +{ + const QWidgetList l = qFindChildren<QWidget*>(w); + if (l.isEmpty()) + return; + m_selection->raiseList(l); +} + +QWidget *FormWindow::containerAt(const QPoint &pos, QWidget *notParentOf) +{ + QWidget *container = 0; + int depth = -1; + const QWidgetList selected = selectedWidgets(); + if (rect().contains(mapFromGlobal(pos))) { + container = mainContainer(); + depth = widgetDepth(container); + } + + QListIterator<QWidget*> it(m_widgets); + while (it.hasNext()) { + QWidget *wit = it.next(); + if (qobject_cast<QLayoutWidget*>(wit) || qobject_cast<QSplitter*>(wit)) + continue; + if (!wit->isVisibleTo(this)) + continue; + if (selected.indexOf(wit) != -1) + continue; + if (!core()->widgetDataBase()->isContainer(wit) && + wit != mainContainer()) + continue; + + // the rectangles of all ancestors of the container must contain the insert position + QWidget *w = wit; + while (w && !w->isWindow()) { + if (!w->rect().contains((w->mapFromGlobal(pos)))) + break; + w = w->parentWidget(); + } + if (!(w == 0 || w->isWindow())) + continue; // we did not get through the full while loop + + int wd = widgetDepth(wit); + if (wd == depth && container) { + if (wit->parentWidget()->children().indexOf(wit) > + container->parentWidget()->children().indexOf(container)) + wd++; + } + if (wd > depth && !isChildOf(wit, notParentOf)) { + depth = wd; + container = wit; + } + } + return container; +} + +QWidgetList FormWindow::selectedWidgets() const +{ + return m_selection->selectedWidgets(); +} + +void FormWindow::selectWidgets() +{ + bool selectionChanged = false; + const QWidgetList l = qFindChildren<QWidget*>(mainContainer()); + QListIterator <QWidget*> it(l); + const QRect selRect(mapToGlobal(m_currRect.topLeft()), m_currRect.size()); + while (it.hasNext()) { + QWidget *w = it.next(); + if (w->isVisibleTo(this) && isManaged(w)) { + const QPoint p = w->mapToGlobal(QPoint(0,0)); + const QRect r(p, w->size()); + if (r.intersects(selRect) && !r.contains(selRect) && trySelectWidget(w, true)) + selectionChanged = true; + } + } + + if (selectionChanged) + emitSelectionChanged(); +} + +bool FormWindow::handleKeyPressEvent(QWidget *widget, QWidget *, QKeyEvent *e) +{ + if (qobject_cast<const FormWindow*>(widget) || qobject_cast<const QMenu*>(widget)) + return false; + + e->accept(); // we always accept! + + switch (e->key()) { + default: break; // we don't care about the other keys + + case Qt::Key_Delete: + case Qt::Key_Backspace: + if (e->modifiers() == Qt::NoModifier) + deleteWidgets(); + break; + + case Qt::Key_Tab: + if (e->modifiers() == Qt::NoModifier) + cursor()->movePosition(QDesignerFormWindowCursorInterface::Next); + break; + + case Qt::Key_Backtab: + if (e->modifiers() == Qt::NoModifier) + cursor()->movePosition(QDesignerFormWindowCursorInterface::Prev); + break; + + case Qt::Key_Left: + case Qt::Key_Right: + case Qt::Key_Up: + case Qt::Key_Down: + handleArrowKeyEvent(e->key(), e->modifiers()); + break; + } + + return true; +} + +int FormWindow::getValue(const QRect &rect, int key, bool size) const +{ + if (size) { + if (key == Qt::Key_Left || key == Qt::Key_Right) + return rect.width(); + return rect.height(); + } + if (key == Qt::Key_Left || key == Qt::Key_Right) + return rect.x(); + return rect.y(); +} + +int FormWindow::calcValue(int val, bool forward, bool snap, int snapOffset) const +{ + if (snap) { + const int rest = val % snapOffset; + if (rest) { + const int offset = forward ? snapOffset : 0; + const int newOffset = rest < 0 ? offset - snapOffset : offset; + return val + newOffset - rest; + } + return (forward ? val + snapOffset : val - snapOffset); + } + return (forward ? val + 1 : val - 1); +} + +QRect FormWindow::applyValue(const QRect &rect, int val, int key, bool size) const +{ + QRect r = rect; + if (size) { + if (key == Qt::Key_Left || key == Qt::Key_Right) + r.setWidth(val); + else + r.setHeight(val); + } else { + if (key == Qt::Key_Left || key == Qt::Key_Right) + r.moveLeft(val); + else + r.moveTop(val); + } + return r; +} + +void FormWindow::handleArrowKeyEvent(int key, Qt::KeyboardModifiers modifiers) +{ + bool startMacro = false; + const QDesignerFormWindowCursorInterface *c = cursor(); + if (!c->hasSelection()) + return; + + QWidgetList selection; + + // check if a laid out widget is selected + const int count = c->selectedWidgetCount(); + for (int index = 0; index < count; ++index) { + QWidget *w = c->selectedWidget(index); + if (!LayoutInfo::isWidgetLaidout(m_core, w)) + selection.append(w); + } + + if (selection.isEmpty()) + return; + + QWidget *current = c->current(); + if (!current || LayoutInfo::isWidgetLaidout(m_core, current)) { + current = selection.first(); + } + + const bool size = modifiers & Qt::ShiftModifier; + + const bool snap = !(modifiers & Qt::ControlModifier); + const bool forward = (key == Qt::Key_Right || key == Qt::Key_Down); + const int snapPoint = (key == Qt::Key_Left || key == Qt::Key_Right) ? grid().x() : grid().y(); + + const int oldValue = getValue(current->geometry(), key, size); + + const int newValue = calcValue(oldValue, forward, snap, snapPoint); + + const int offset = newValue - oldValue; + + const int selCount = selection.count(); + // check if selection is the same as last time + if (selCount != m_moveSelection.count() || + m_lastUndoIndex != m_commandHistory->index()) { + m_moveSelection.clear(); + startMacro = true; + } else { + for (int index = 0; index < selCount; ++index) { + if (m_moveSelection[index]->object() != selection.at(index)) { + m_moveSelection.clear(); + startMacro = true; + break; + } + } + } + + if (startMacro) + beginCommand(tr("Key Move")); + + for (int index = 0; index < selCount; ++index) { + QWidget *w = selection.at(index); + const QRect oldGeom = w->geometry(); + const QRect geom = applyValue(oldGeom, getValue(oldGeom, key, size) + offset, key, size); + + SetPropertyCommand *cmd = 0; + + if (m_moveSelection.count() > index) + cmd = m_moveSelection[index]; + + if (!cmd) { + cmd = new SetPropertyCommand(this); + cmd->init(w, QLatin1String("geometry"), geom); + cmd->setText(tr("Key Move")); + m_commandHistory->push(cmd); + + if (m_moveSelection.count() > index) + m_moveSelection.replace(index, cmd); + else + m_moveSelection.append(cmd); + } else { + cmd->setNewValue(geom); + cmd->redo(); + } + } + + if (startMacro) { + endCommand(); + m_lastUndoIndex = m_commandHistory->index(); + } +} + +bool FormWindow::handleKeyReleaseEvent(QWidget *, QWidget *, QKeyEvent *e) +{ + e->accept(); + return true; +} + +void FormWindow::selectAll() +{ + bool selectionChanged = false; + foreach (QWidget *widget, m_widgets) { + if (widget->isVisibleTo(this) && trySelectWidget(widget, true)) + selectionChanged = true; + } + if (selectionChanged) + emitSelectionChanged(); +} + +void FormWindow::createLayout(int type, QWidget *container) +{ + if (container) { + layoutContainer(container, type); + } else { + LayoutCommand *cmd = new LayoutCommand(this); + cmd->init(mainContainer(), selectedWidgets(), static_cast<LayoutInfo::Type>(type)); + commandHistory()->push(cmd); + } +} + +void FormWindow::morphLayout(QWidget *container, int newType) +{ + MorphLayoutCommand *cmd = new MorphLayoutCommand(this); + if (cmd->init(container, newType)) { + commandHistory()->push(cmd); + } else { + qDebug() << "** WARNING Unable to morph layout."; + delete cmd; + } +} + +void FormWindow::deleteWidgets() +{ + QWidgetList selection = selectedWidgets(); + simplifySelection(&selection); + + deleteWidgetList(selection); +} + +QString FormWindow::fileName() const +{ + return m_fileName; +} + +void FormWindow::setFileName(const QString &fileName) +{ + if (m_fileName == fileName) + return; + + m_fileName = fileName; + emit fileNameChanged(fileName); +} + +QString FormWindow::contents() const +{ + QBuffer b; + if (!mainContainer() || !b.open(QIODevice::WriteOnly)) + return QString(); + + QDesignerResource resource(const_cast<FormWindow*>(this)); + resource.save(&b, mainContainer()); + + return QString::fromUtf8(b.buffer()); +} + +void FormWindow::copy() +{ + QBuffer b; + if (!b.open(QIODevice::WriteOnly)) + return; + + FormBuilderClipboard clipboard; + QDesignerResource resource(this); + resource.setSaveRelative(false); + clipboard.m_widgets = selectedWidgets(); + simplifySelection(&clipboard.m_widgets); + resource.copy(&b, clipboard); + + qApp->clipboard()->setText(QString::fromUtf8(b.buffer()), QClipboard::Clipboard); +} + +void FormWindow::cut() +{ + copy(); + deleteWidgets(); +} + +// for cases like QMainWindow (central widget is an inner container) or QStackedWidget (page is an inner container) +QWidget *FormWindow::innerContainer(QWidget *outerContainer) const +{ + bool isContainer = m_core->widgetDataBase()->isContainer(outerContainer); + if (isContainer) + if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(m_core->extensionManager(), outerContainer)) + return container->widget(container->currentIndex()); + return outerContainer; +} + +QWidget *FormWindow::containerForPaste() const +{ + QWidget *w = mainContainer(); + if (!w) + return 0; + do { + // Try to find a close parent, for example a non-laid-out + // QFrame/QGroupBox when a widget within it is selected. + QWidgetList selection = selectedWidgets(); + if (selection.empty()) + break; + simplifySelection(&selection); + + QWidget *containerOfW = findContainer(selection.first(), /* exclude layouts */ true); + if (!containerOfW || containerOfW == mainContainer()) + break; + // No layouts, must be container + containerOfW = innerContainer(containerOfW); + if (LayoutInfo::layoutType(m_core, containerOfW) != LayoutInfo::NoLayout || !m_core->widgetDataBase()->isContainer(containerOfW)) + break; + w = containerOfW; + } while (false); + // First check for layout (note that it does not cover QMainWindow + // and the like as the central widget has the layout). + + w = innerContainer(w); + if (LayoutInfo::layoutType(m_core, w) != LayoutInfo::NoLayout) + return 0; + // Go up via container extension (also includes step from QMainWindow to its central widget) + w = m_core->widgetFactory()->containerOfWidget(w); + if (w == 0 || LayoutInfo::layoutType(m_core, w) != LayoutInfo::NoLayout) + return 0; + + if (debugFormWindow) + qDebug() <<"containerForPaste() " << w; + return w; +} + +void FormWindow::paste() +{ + paste(PasteAll); +} + +// Construct DomUI from clipboard (paste) and determine number of widgets/actions. +static inline DomUI *domUIFromClipboard(int *widgetCount, int *actionCount) +{ + *widgetCount = *actionCount = 0; + const QString clipboardText = qApp->clipboard()->text(); + if (clipboardText.isEmpty() || clipboardText.indexOf(QLatin1Char('<')) == -1) + return 0; + + QXmlStreamReader reader(clipboardText); + DomUI *ui = 0; + const QString uiElement = QLatin1String("ui"); + while (!reader.atEnd()) { + if (reader.readNext() == QXmlStreamReader::StartElement) { + if (reader.name().compare(uiElement, Qt::CaseInsensitive) == 0 && !ui) { + ui = new DomUI(); + ui->read(reader); + break; + } else { + reader.raiseError(QCoreApplication::translate("FormWindow", "Unexpected element <%1>").arg(reader.name().toString())); + } + } + } + if (reader.hasError()) { + delete ui; + ui = 0; + designerWarning(QCoreApplication::translate("FormWindow", "Error while pasting clipboard contents at line %1, column %2: %3"). + arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString())); + return 0; + } + + if (const DomWidget *topLevel = ui->elementWidget()) { + *widgetCount = topLevel->elementWidget().size(); + *actionCount = topLevel->elementAction().size(); + } + if (*widgetCount == 0 && *actionCount == 0) { + delete ui; + return 0; + } + return ui; +} + +static inline QString pasteCommandDescription(int widgetCount, int actionCount) +{ + if (widgetCount == 0) + return FormWindow::tr("Paste %n action(s)", 0, actionCount); + if (actionCount == 0) + return FormWindow::tr("Paste %n widget(s)", 0, widgetCount); + return FormWindow::tr("Paste (%1 widgets, %2 actions)").arg(widgetCount).arg(actionCount); +} + +static void positionPastedWidgetsAtMousePosition(FormWindow *fw, const QPoint &contextMenuPosition, QWidget *parent, const QWidgetList &l) +{ + // Try to position pasted widgets at mouse position (current mouse position for Ctrl-V or position of context menu) + // if it fits. If it is completely outside, force it to 0,0 + // If it fails, the old coordinates relative to the previous parent will be used. + QPoint currentPos = contextMenuPosition.x() >=0 ? parent->mapFrom(fw, contextMenuPosition) : parent->mapFromGlobal(QCursor::pos()); + const Grid &grid = fw->designerGrid(); + QPoint cursorPos = grid.snapPoint(currentPos); + const QRect parentGeometry = QRect(QPoint(0, 0), parent->size()); + const bool outside = !parentGeometry.contains(cursorPos); + if (outside) + cursorPos = grid.snapPoint(QPoint(0, 0)); + // Determine area of pasted widgets + QRect pasteArea; + const QWidgetList::const_iterator lcend = l.constEnd(); + for (QWidgetList::const_iterator it = l.constBegin(); it != lcend; ++it) + pasteArea =pasteArea.isNull() ? (*it)->geometry() : pasteArea.united((*it)->geometry()); + + // Mouse on some child? (try to position bottomRight on a free spot to + // get the stacked-offset effect of Designer 4.3, that is, offset by grid if Ctrl-V is pressed continuously + do { + const QPoint bottomRight = cursorPos + QPoint(pasteArea.width(), pasteArea.height()) - QPoint(1, 1); + if (bottomRight.y() > parentGeometry.bottom() || parent->childAt(bottomRight) == 0) + break; + cursorPos += QPoint(grid.deltaX(), grid.deltaY()); + } while (true); + // Move. + const QPoint offset = cursorPos - pasteArea.topLeft(); + for (QWidgetList::const_iterator it = l.constBegin(); it != lcend; ++it) + (*it)->move((*it)->pos() + offset); +} + +void FormWindow::paste(PasteMode pasteMode) +{ + // Avoid QDesignerResource constructing widgets that are not used as + // QDesignerResource manages the widgets it creates (creating havoc if one remains unused) + DomUI *ui = 0; + do { + int widgetCount; + int actionCount; + ui = domUIFromClipboard(&widgetCount, &actionCount); + if (!ui) + break; + + // Check for actions + if (pasteMode == PasteActionsOnly) + if (widgetCount != 0 || actionCount == 0) + break; + + // Check for widgets: need a container + QWidget *pasteContainer = widgetCount ? containerForPaste() : 0; + if (widgetCount && pasteContainer == 0) { + + const QString message = tr("Cannot paste widgets. Designer could not find a container " + "without a layout to paste into."); + const QString infoMessage = tr("Break the layout of the " + "container you want to paste into, select this container " + "and then paste again."); + core()->dialogGui()->message(this, QDesignerDialogGuiInterface::FormEditorMessage, QMessageBox::Information, + tr("Paste error"), message, infoMessage, QMessageBox::Ok); + break; + } + + QDesignerResource resource(this); + // Note that the widget factory must be able to locate the + // form window (us) via parent, otherwise, it will not able to construct QLayoutWidgets + // (It will then default to widgets) among other issues. + const FormBuilderClipboard clipboard = resource.paste(ui, pasteContainer, this); + + clearSelection(false); + // Create command sequence + beginCommand(pasteCommandDescription(widgetCount, actionCount)); + + if (widgetCount) { + positionPastedWidgetsAtMousePosition(this, m_contextMenuPosition, pasteContainer, clipboard.m_widgets); + foreach (QWidget *w, clipboard.m_widgets) { + InsertWidgetCommand *cmd = new InsertWidgetCommand(this); + cmd->init(w); + m_commandHistory->push(cmd); + selectWidget(w); + } + } + + if (actionCount) + foreach (QAction *a, clipboard.m_actions) { + ensureUniqueObjectName(a); + AddActionCommand *cmd = new AddActionCommand(this); + cmd->init(a); + m_commandHistory->push(cmd); + } + endCommand(); + } while (false); + delete ui; +} + +// Draw a dotted frame around containers +bool FormWindow::frameNeeded(QWidget *w) const +{ + if (!core()->widgetDataBase()->isContainer(w)) + return false; + if (qobject_cast<QGroupBox *>(w)) + return false; + if (qobject_cast<QToolBox *>(w)) + return false; + if (qobject_cast<QTabWidget *>(w)) + return false; + if (qobject_cast<QStackedWidget *>(w)) + return false; + if (qobject_cast<QDockWidget *>(w)) + return false; + if (qobject_cast<QDesignerWidget *>(w)) + return false; + if (qobject_cast<QMainWindow *>(w)) + return false; + if (qobject_cast<QDialog *>(w)) + return false; + if (qobject_cast<QLayoutWidget *>(w)) + return false; + return true; +} + +bool FormWindow::eventFilter(QObject *watched, QEvent *event) +{ + const bool ret = FormWindowBase::eventFilter(watched, event); + if (event->type() != QEvent::Paint) + return ret; + + Q_ASSERT(watched->isWidgetType()); + QWidget *w = static_cast<QWidget *>(watched); + QPaintEvent *pe = static_cast<QPaintEvent*>(event); + const QRect widgetRect = w->rect(); + const QRect paintRect = pe->rect(); + // Does the paint rectangle touch the borders of the widget rectangle + if (paintRect.x() > widgetRect.x() && paintRect.y() > widgetRect.y() && + paintRect.right() < widgetRect.right() && paintRect.bottom() < widgetRect.bottom()) + return ret; + QPainter p(w); + const QPen pen(QColor(0, 0, 0, 32), 0, Qt::DotLine); + p.setPen(pen); + p.setBrush(QBrush(Qt::NoBrush)); + p.drawRect(widgetRect.adjusted(0, 0, -1, -1)); + return ret; +} + +void FormWindow::manageWidget(QWidget *w) +{ + if (isManaged(w)) + return; + + Q_ASSERT(qobject_cast<QMenu*>(w) == 0); + + if (w->hasFocus()) + setFocus(); + + core()->metaDataBase()->add(w); + + m_insertedWidgets.insert(w); + m_widgets.append(w); + +#ifndef QT_NO_CURSOR + setCursorToAll(Qt::ArrowCursor, w); +#endif + + emit changed(); + emit widgetManaged(w); + + if (frameNeeded(w)) + w->installEventFilter(this); +} + +void FormWindow::unmanageWidget(QWidget *w) +{ + if (!isManaged(w)) + return; + + m_selection->removeWidget(w); + + emit aboutToUnmanageWidget(w); + + if (w == m_currentWidget) + setCurrentWidget(mainContainer()); + + core()->metaDataBase()->remove(w); + + m_insertedWidgets.remove(w); + m_widgets.removeAt(m_widgets.indexOf(w)); + + emit changed(); + emit widgetUnmanaged(w); + + if (frameNeeded(w)) + w->removeEventFilter(this); +} + +bool FormWindow::isManaged(QWidget *w) const +{ + return m_insertedWidgets.contains(w); +} + +void FormWindow::breakLayout(QWidget *w) +{ + if (w == this) + w = mainContainer(); + // Find the first-order managed child widgets + QWidgetList widgets; + + const QObjectList children = w->children(); + const QObjectList::const_iterator cend = children.constEnd(); + const QDesignerMetaDataBaseInterface *mdb = core()->metaDataBase(); + for (QObjectList::const_iterator it = children.constBegin(); it != cend; ++it) + if ( (*it)->isWidgetType()) { + QWidget *w = static_cast<QWidget*>(*it); + if (mdb->item(w)) + widgets.push_back(w); + } + + BreakLayoutCommand *cmd = new BreakLayoutCommand(this); + cmd->init(widgets, w); + commandHistory()->push(cmd); + clearSelection(false); +} + +void FormWindow::beginCommand(const QString &description) +{ + if (m_lastIndex > m_commandHistory->index()) + m_lastIndex = -1; + m_commandHistory->beginMacro(description); +} + +void FormWindow::endCommand() +{ + m_commandHistory->endMacro(); +} + +void FormWindow::raiseWidgets() +{ + QWidgetList widgets = selectedWidgets(); + simplifySelection(&widgets); + + if (widgets.isEmpty()) + return; + + beginCommand(tr("Raise widgets")); + foreach (QWidget *widget, widgets) { + RaiseWidgetCommand *cmd = new RaiseWidgetCommand(this); + cmd->init(widget); + m_commandHistory->push(cmd); + } + endCommand(); +} + +void FormWindow::lowerWidgets() +{ + QWidgetList widgets = selectedWidgets(); + simplifySelection(&widgets); + + if (widgets.isEmpty()) + return; + + beginCommand(tr("Lower widgets")); + foreach (QWidget *widget, widgets) { + LowerWidgetCommand *cmd = new LowerWidgetCommand(this); + cmd->init(widget); + m_commandHistory->push(cmd); + } + endCommand(); +} + +bool FormWindow::handleMouseButtonDblClickEvent(QWidget *w, QWidget *managedWidget, QMouseEvent *e) +{ + if (debugFormWindow) + qDebug() << "handleMouseButtonDblClickEvent:" << w << ',' << managedWidget << "state=" << m_mouseState; + + e->accept(); + + // Might be out of sync due cycling of the parent selection + // In that case, do nothing + if (isWidgetSelected(managedWidget)) + emit activated(managedWidget); + + m_mouseState = MouseDoubleClicked; + return true; +} + + +QMenu *FormWindow::initializePopupMenu(QWidget *managedWidget) +{ + if (!isManaged(managedWidget) || currentTool()) + return 0; + + // Make sure the managedWidget is selected and current since + // the SetPropertyCommands must use the right reference + // object obtained from the property editor for the property group + // of a multiselection to be correct. + const bool selected = isWidgetSelected(managedWidget); + bool update = false; + if (selected == false) { + clearObjectInspectorSelection(m_core); // We might have a toolbar or non-widget selected in the object inspector. + clearSelection(false); + update = trySelectWidget(managedWidget, true); + raiseChildSelections(managedWidget); // raise selections and select widget + } else { + update = setCurrentWidget(managedWidget); + } + + if (update) { + emitSelectionChanged(); + QMetaObject::invokeMethod(core()->formWindowManager(), "slotUpdateActions"); + } + + QWidget *contextMenuWidget = 0; + + if (isMainContainer(managedWidget)) { // press on a child widget + contextMenuWidget = mainContainer(); + } else { // press on a child widget + // if widget is laid out, find the first non-laid out super-widget + QWidget *realWidget = managedWidget; // but store the original one + QMainWindow *mw = qobject_cast<QMainWindow*>(mainContainer()); + + if (mw && mw->centralWidget() == realWidget) { + contextMenuWidget = managedWidget; + } else { + contextMenuWidget = realWidget; + } + } + + if (!contextMenuWidget) + return 0; + + QMenu *contextMenu = createPopupMenu(contextMenuWidget); + if (!contextMenu) + return 0; + + emit contextMenuRequested(contextMenu, contextMenuWidget); + return contextMenu; +} + +bool FormWindow::handleContextMenu(QWidget *, QWidget *managedWidget, QContextMenuEvent *e) +{ + QMenu *contextMenu = initializePopupMenu(managedWidget); + if (!contextMenu) + return false; + const QPoint globalPos = e->globalPos(); + m_contextMenuPosition = mapFromGlobal (globalPos); + contextMenu->exec(globalPos); + delete contextMenu; + e->accept(); + m_contextMenuPosition = QPoint(-1, -1); + return true; +} + +void FormWindow::setContents(QIODevice *dev) +{ + UpdateBlocker ub(this); + clearSelection(); + m_selection->clearSelectionPool(); + m_insertedWidgets.clear(); + m_widgets.clear(); + // The main container is cleared as otherwise + // the names of the newly loaded objects will be unified. + clearMainContainer(); + emit changed(); + + QDesignerResource r(this); + QWidget *w = r.load(dev, formContainer()); + setMainContainer(w); + emit changed(); +} + +void FormWindow::setContents(const QString &contents) +{ + QByteArray data = contents.toUtf8(); + QBuffer b(&data); + if (b.open(QIODevice::ReadOnly)) + setContents(&b); +} + +void FormWindow::layoutContainer(QWidget *w, int type) +{ + if (w == this) + w = mainContainer(); + + w = core()->widgetFactory()->containerOfWidget(w); + + const QObjectList l = w->children(); + if (l.isEmpty()) + return; + // find managed widget children + QWidgetList widgets; + const QObjectList::const_iterator ocend = l.constEnd(); + for (QObjectList::const_iterator it = l.constBegin(); it != l.constEnd(); ++it) + if ( (*it)->isWidgetType() ) { + QWidget *widget = static_cast<QWidget*>(*it); + if (widget->isVisibleTo(this) && isManaged(widget)) + widgets.append(widget); + } + + LayoutCommand *cmd = new LayoutCommand(this); + cmd->init(mainContainer(), widgets, static_cast<LayoutInfo::Type>(type), w); + clearSelection(false); + commandHistory()->push(cmd); +} + +bool FormWindow::hasInsertedChildren(QWidget *widget) const // ### move +{ + if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), widget)) { + widget = container->widget(container->currentIndex()); + } + + const QWidgetList l = widgets(widget); + + foreach (QWidget *child, l) { + if (isManaged(child) && !LayoutInfo::isWidgetLaidout(core(), child) && child->isVisibleTo(const_cast<FormWindow*>(this))) + return true; + } + + return false; +} + +// "Select Ancestor" sub menu code +void FormWindow::slotSelectWidget(QAction *a) +{ + if (QWidget *w = qvariant_cast<QWidget*>(a->data())) + selectSingleWidget(w); +} + +static inline QString objectNameOf(const QWidget *w) +{ + if (const QLayoutWidget *lw = qobject_cast<const QLayoutWidget *>(w)) { + const QLayout *layout = lw->layout(); + const QString rc = layout->objectName(); + if (!rc.isEmpty()) + return rc; + // Fall thru for 4.3 forms which have a name on the widget: Display the class name + return QString::fromUtf8(layout->metaObject()->className()); + } + return w->objectName(); +} + +QAction *FormWindow::createSelectAncestorSubMenu(QWidget *w) +{ + // Find the managed, unselected parents + QWidgetList parents; + QWidget *mc = mainContainer(); + for (QWidget *p = w->parentWidget(); p && p != mc; p = p->parentWidget()) + if (isManaged(p) && !isWidgetSelected(p)) + parents.push_back(p); + if (parents.empty()) + return 0; + // Create a submenu listing the managed, unselected parents + QMenu *menu = new QMenu; + QActionGroup *ag = new QActionGroup(menu); + QObject::connect(ag, SIGNAL(triggered(QAction*)), this, SLOT(slotSelectWidget(QAction*))); + const int size = parents.size(); + for (int i = 0; i < size; i++) { + QWidget *w = parents.at(i); + QAction *a = ag->addAction(objectNameOf(w)); + a->setData(qVariantFromValue(w)); + menu->addAction(a); + } + QAction *ma = new QAction(tr("Select Ancestor"), 0); + ma->setMenu(menu); + return ma; +} + +QMenu *FormWindow::createPopupMenu(QWidget *w) +{ + QMenu *popup = createExtensionTaskMenu(this, w, true); + if (!popup) + popup = new QMenu; + // if w doesn't have a QDesignerTaskMenu as a child create one and make it a child. + // insert actions from QDesignerTaskMenu + + QDesignerFormWindowManagerInterface *manager = core()->formWindowManager(); + const bool isFormWindow = qobject_cast<const FormWindow*>(w); + + // Check for special containers and obtain the page menu from them to add layout actions. + if (!isFormWindow) { + if (QStackedWidget *stackedWidget = qobject_cast<QStackedWidget*>(w)) { + QStackedWidgetEventFilter::addStackedWidgetContextMenuActions(stackedWidget, popup); + } else if (QTabWidget *tabWidget = qobject_cast<QTabWidget*>(w)) { + QTabWidgetEventFilter::addTabWidgetContextMenuActions(tabWidget, popup); + } else if (QToolBox *toolBox = qobject_cast<QToolBox*>(w)) { + QToolBoxHelper::addToolBoxContextMenuActions(toolBox, popup); + } + + popup->addAction(manager->actionCut()); + popup->addAction(manager->actionCopy()); + } + + popup->addAction(manager->actionPaste()); + + if (QAction *selectAncestorAction = createSelectAncestorSubMenu(w)) + popup->addAction(selectAncestorAction); + popup->addAction(manager->actionSelectAll()); + + if (!isFormWindow) { + popup->addAction(manager->actionDelete()); + } + + popup->addSeparator(); + QMenu *layoutMenu = popup->addMenu(tr("Lay out")); + layoutMenu->addAction(manager->actionAdjustSize()); + layoutMenu->addAction(manager->actionHorizontalLayout()); + layoutMenu->addAction(manager->actionVerticalLayout()); + layoutMenu->addAction(manager->actionGridLayout()); + layoutMenu->addAction(manager->actionFormLayout()); + if (!isFormWindow) { + layoutMenu->addAction(manager->actionSplitHorizontal()); + layoutMenu->addAction(manager->actionSplitVertical()); + } + layoutMenu->addAction(manager->actionBreakLayout()); + layoutMenu->addAction(manager->actionSimplifyLayout()); + + return popup; +} + +void FormWindow::resizeEvent(QResizeEvent *e) +{ + m_geometryChangedTimer->start(10); + + QWidget::resizeEvent(e); +} + +/*! + Maps \a pos in \a w's coordinates to the form's coordinate system. + + This is the equivalent to mapFromGlobal(w->mapToGlobal(pos)) but + avoids the two roundtrips to the X-Server on Unix/X11. + */ +QPoint FormWindow::mapToForm(const QWidget *w, const QPoint &pos) const +{ + QPoint p = pos; + const QWidget* i = w; + while (i && !i->isWindow() && !isMainContainer(i)) { + p = i->mapToParent(p); + i = i->parentWidget(); + } + + return mapFromGlobal(w->mapToGlobal(pos)); +} + +bool FormWindow::canBeBuddy(QWidget *w) const // ### rename me. +{ + if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), w)) { + const int index = sheet->indexOf(QLatin1String("focusPolicy")); + if (index != -1) { + bool ok = false; + const Qt::FocusPolicy q = static_cast<Qt::FocusPolicy>(Utils::valueOf(sheet->property(index), &ok)); + return ok && q != Qt::NoFocus; + } + } + + return false; +} + +QWidget *FormWindow::findContainer(QWidget *w, bool excludeLayout) const +{ + if (!isChildOf(w, this) + || const_cast<const QWidget *>(w) == this) + return 0; + + QDesignerWidgetFactoryInterface *widgetFactory = core()->widgetFactory(); + QDesignerWidgetDataBaseInterface *widgetDataBase = core()->widgetDataBase(); + QDesignerMetaDataBaseInterface *metaDataBase = core()->metaDataBase(); + + QWidget *container = widgetFactory->containerOfWidget(mainContainer()); // default parent for new widget is the formwindow + if (!isMainContainer(w)) { // press was not on formwindow, check if we can find another parent + while (w) { + if (qobject_cast<InvisibleWidget*>(w) || !metaDataBase->item(w)) { + w = w->parentWidget(); + continue; + } + + const bool isContainer = widgetDataBase->isContainer(w, true) || w == mainContainer(); + + if (!isContainer || (excludeLayout && qobject_cast<QLayoutWidget*>(w))) { // ### skip QSplitter + w = w->parentWidget(); + } else { + container = w; + break; + } + } + } + + return container; +} + +void FormWindow::simplifySelection(QWidgetList *sel) const +{ + if (sel->size() < 2) + return; + // Figure out which widgets should be removed from selection. + // We want to remove those whose parent widget is also in the + // selection (because the child widgets are contained by + // their parent, they shouldn't be in the selection -- + // they are "implicitly" selected). + QWidget *mainC = mainContainer(); // Quick check for main container first + if (sel->contains(mainC)) { + sel->clear(); + sel->push_back(mainC); + return; + } + typedef QVector<QWidget *> WidgetVector; + WidgetVector toBeRemoved; + toBeRemoved.reserve(sel->size()); + const QWidgetList::const_iterator scend = sel->constEnd(); + for (QWidgetList::const_iterator it = sel->constBegin(); it != scend; ++it) { + QWidget *child = *it; + for (QWidget *w = child; true ; ) { // Is any of the parents also selected? + QWidget *parent = w->parentWidget(); + if (!parent || parent == mainC) + break; + if (sel->contains(parent)) { + toBeRemoved.append(child); + break; + } + w = parent; + } + } + // Now we can actually remove the widgets that were marked + // for removal in the previous pass. + if (!toBeRemoved.isEmpty()) { + const WidgetVector::const_iterator rcend = toBeRemoved.constEnd(); + for (WidgetVector::const_iterator it = toBeRemoved.constBegin(); it != rcend; ++it) + sel->removeAll(*it); + } +} + +FormWindow *FormWindow::findFormWindow(QWidget *w) +{ + return qobject_cast<FormWindow*>(QDesignerFormWindowInterface::findFormWindow(w)); +} + +bool FormWindow::isDirty() const +{ + return m_dirty; +} + +void FormWindow::setDirty(bool dirty) +{ + m_dirty = dirty; + + if (!m_dirty) + m_lastIndex = m_commandHistory->index(); +} + +void FormWindow::updateDirty() +{ + m_dirty = m_commandHistory->index() != m_lastIndex; +} + +QWidget *FormWindow::containerAt(const QPoint &pos) +{ + QWidget *widget = widgetAt(pos); + return findContainer(widget, true); +} + +static QWidget *childAt_SkipDropLine(QWidget *w, QPoint pos) +{ + const QObjectList child_list = w->children(); + for (int i = child_list.size() - 1; i >= 0; --i) { + QObject *child_obj = child_list[i]; + if (qobject_cast<WidgetHandle*>(child_obj) != 0) + continue; + QWidget *child = qobject_cast<QWidget*>(child_obj); + if (!child || child->isWindow() || !child->isVisible() || + !child->geometry().contains(pos) || child->testAttribute(Qt::WA_TransparentForMouseEvents)) + continue; + const QPoint childPos = child->mapFromParent(pos); + if (QWidget *res = childAt_SkipDropLine(child, childPos)) + return res; + if (child->testAttribute(Qt::WA_MouseNoMask) || child->mask().contains(pos) + || child->mask().isEmpty()) + return child; + } + + return 0; +} + +QWidget *FormWindow::widgetAt(const QPoint &pos) +{ + QWidget *w = childAt(pos); + if (qobject_cast<const WidgetHandle*>(w) != 0) + w = childAt_SkipDropLine(this, pos); + return (w == 0 || w == formContainer()) ? this : w; +} + +void FormWindow::highlightWidget(QWidget *widget, const QPoint &pos, HighlightMode mode) +{ + Q_ASSERT(widget); + + if (QMainWindow *mainWindow = qobject_cast<QMainWindow*> (widget)) { + widget = mainWindow->centralWidget(); + } + + QWidget *container = findContainer(widget, false); + + if (container == 0 || core()->metaDataBase()->item(container) == 0) + return; + + if (QDesignerActionProviderExtension *g = qt_extension<QDesignerActionProviderExtension*>(core()->extensionManager(), container)) { + if (mode == Restore) { + g->adjustIndicator(QPoint()); + } else { + const QPoint pt = widget->mapTo(container, pos); + g->adjustIndicator(pt); + } + } else if (QDesignerLayoutDecorationExtension *g = qt_extension<QDesignerLayoutDecorationExtension*>(core()->extensionManager(), container)) { + if (mode == Restore) { + g->adjustIndicator(QPoint(), -1); + } else { + const QPoint pt = widget->mapTo(container, pos); + const int index = g->findItemAt(pt); + g->adjustIndicator(pt, index); + } + } + + QMainWindow *mw = qobject_cast<QMainWindow*> (container); + if (container == mainContainer() || (mw && mw->centralWidget() && mw->centralWidget() == container)) + return; + + if (mode == Restore) { + const WidgetPaletteMap::iterator pit = m_palettesBeforeHighlight.find(container); + if (pit != m_palettesBeforeHighlight.end()) { + container->setPalette(pit.value().first); + container->setAutoFillBackground(pit.value().second); + m_palettesBeforeHighlight.erase(pit); + } + } else { + QPalette p = container->palette(); + if (!m_palettesBeforeHighlight.contains(container)) { + PaletteAndFill paletteAndFill; + if (container->testAttribute(Qt::WA_SetPalette)) + paletteAndFill.first = p; + paletteAndFill.second = container->autoFillBackground(); + m_palettesBeforeHighlight.insert(container, paletteAndFill); + } + + p.setColor(backgroundRole(), p.midlight().color()); + container->setPalette(p); + container->setAutoFillBackground(true); + } +} + +QWidgetList FormWindow::widgets(QWidget *widget) const +{ + const QObjectList children = widget->children(); + if (children.empty()) + return QWidgetList(); + QWidgetList rc; + const QObjectList::const_iterator cend = children.constEnd(); + for (QObjectList::const_iterator it = children.constBegin(); it != cend; ++it) + if ((*it)->isWidgetType()) { + QWidget *w = qobject_cast<QWidget*>(*it); + if (isManaged(w)) + rc.push_back(w); + } + return rc; +} + +int FormWindow::toolCount() const +{ + return m_widgetStack->count(); +} + +QDesignerFormWindowToolInterface *FormWindow::tool(int index) const +{ + return m_widgetStack->tool(index); +} + +void FormWindow::registerTool(QDesignerFormWindowToolInterface *tool) +{ + Q_ASSERT(tool != 0); + + m_widgetStack->addTool(tool); + + if (m_mainContainer) + m_mainContainer->update(); +} + +void FormWindow::setCurrentTool(int index) +{ + m_widgetStack->setCurrentTool(index); +} + +int FormWindow::currentTool() const +{ + return m_widgetStack->currentIndex(); +} + +bool FormWindow::handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event) +{ + if (m_widgetStack == 0) + return false; + + QDesignerFormWindowToolInterface *tool = m_widgetStack->currentTool(); + if (tool == 0) + return false; + + return tool->handleEvent(widget, managedWidget, event); +} + +void FormWindow::initializeCoreTools() +{ + m_widgetEditor = new WidgetEditorTool(this); + registerTool(m_widgetEditor); +} + +void FormWindow::checkSelection() +{ + m_checkSelectionTimer->start(0); +} + +void FormWindow::checkSelectionNow() +{ + m_checkSelectionTimer->stop(); + + foreach (QWidget *widget, selectedWidgets()) { + updateSelection(widget); + + if (LayoutInfo::layoutType(core(), widget) != LayoutInfo::NoLayout) + updateChildSelections(widget); + } +} + +QString FormWindow::author() const +{ + return m_author; +} + +QString FormWindow::comment() const +{ + return m_comment; +} + +void FormWindow::setAuthor(const QString &author) +{ + m_author = author; +} + +void FormWindow::setComment(const QString &comment) +{ + m_comment = comment; +} + +void FormWindow::editWidgets() +{ + m_widgetEditor->action()->trigger(); +} + +QStringList FormWindow::resourceFiles() const +{ + return m_resourceFiles; +} + +void FormWindow::addResourceFile(const QString &path) +{ + if (!m_resourceFiles.contains(path)) { + m_resourceFiles.append(path); + setDirty(true); + emit resourceFilesChanged(); + } +} + +void FormWindow::removeResourceFile(const QString &path) +{ + if (m_resourceFiles.removeAll(path) > 0) { + setDirty(true); + emit resourceFilesChanged(); + } +} + +bool FormWindow::blockSelectionChanged(bool b) +{ + const bool blocked = m_blockSelectionChanged; + m_blockSelectionChanged = b; + return blocked; +} + +void FormWindow::editContents() +{ + const QWidgetList sel = selectedWidgets(); + if (sel.count() == 1) { + QWidget *widget = sel.first(); + + if (QAction *a = preferredEditAction(core(), widget)) + a->trigger(); + } +} + +void FormWindow::dragWidgetWithinForm(QWidget *widget, const QRect &targetGeometry, QWidget *targetContainer) +{ + const bool fromLayout = canDragWidgetInLayout(core(), widget); + const QDesignerLayoutDecorationExtension *targetDeco = qt_extension<QDesignerLayoutDecorationExtension*>(core()->extensionManager(), targetContainer); + const bool toLayout = targetDeco != 0; + + if (fromLayout) { + // Drag from Layout: We need to delete the widget properly to store the layout state + // Do not simplify the layout when dragging onto a layout + // as this might invalidate the insertion position if it is the same layout + DeleteWidgetCommand *cmd = new DeleteWidgetCommand(this); + unsigned deleteFlags = DeleteWidgetCommand::DoNotUnmanage; + if (toLayout) + deleteFlags |= DeleteWidgetCommand::DoNotSimplifyLayout; + cmd->init(widget, deleteFlags); + commandHistory()->push(cmd); + } + + if (toLayout) { + // Drag from form to layout: just insert. Do not manage + insertWidget(widget, targetGeometry, targetContainer, true); + } else { + // into container without layout + if (targetContainer != widget->parent()) { // different parent + ReparentWidgetCommand *cmd = new ReparentWidgetCommand(this); + cmd->init(widget, targetContainer ); + commandHistory()->push(cmd); + } + resizeWidget(widget, targetGeometry); + selectWidget(widget, true); + widget->show(); + } +} + +static Qt::DockWidgetArea detectDropArea(QMainWindow *mainWindow, const QRect &area, const QPoint &drop) +{ + QPoint offset = area.topLeft(); + QRect rect = area; + rect.moveTopLeft(QPoint(0, 0)); + QPoint point = drop - offset; + const int x = point.x(); + const int y = point.y(); + const int w = rect.width(); + const int h = rect.height(); + + if (rect.contains(point)) { + bool topRight = false; + bool topLeft = false; + if (w * y < h * x) // top and right, oterwise bottom and left + topRight = true; + if (w * y < h * (w - x)) // top and left, otherwise bottom and right + topLeft = true; + + if (topRight && topLeft) + return Qt::TopDockWidgetArea; + else if (topRight && !topLeft) + return Qt::RightDockWidgetArea; + else if (!topRight && topLeft) + return Qt::LeftDockWidgetArea; + return Qt::BottomDockWidgetArea; + } + + if (x < 0) { + if (y < 0) + return mainWindow->corner(Qt::TopLeftCorner); + else if (y > h) + return mainWindow->corner(Qt::BottomLeftCorner); + else + return Qt::LeftDockWidgetArea; + } else if (x > w) { + if (y < 0) + return mainWindow->corner(Qt::TopRightCorner); + else if (y > h) + return mainWindow->corner(Qt::BottomRightCorner); + else + return Qt::RightDockWidgetArea; + } else { + if (y < 0) + return Qt::TopDockWidgetArea; + else + return Qt::BottomDockWidgetArea; + } + return Qt::LeftDockWidgetArea; +} + +bool FormWindow::dropDockWidget(QDesignerDnDItemInterface *item, const QPoint &global_mouse_pos) +{ + DomUI *dom_ui = item->domUi(); + + QMainWindow *mw = qobject_cast<QMainWindow *>(mainContainer()); + if (!mw) + return false; + + QDesignerResource resource(this); + const FormBuilderClipboard clipboard = resource.paste(dom_ui, mw); + if (clipboard.m_widgets.size() != 1) // multiple-paste from DomUI not supported yet + return false; + + QWidget *centralWidget = mw->centralWidget(); + QPoint localPos = centralWidget->mapFromGlobal(global_mouse_pos); + const QRect centralWidgetAreaRect = centralWidget->rect(); + Qt::DockWidgetArea area = detectDropArea(mw, centralWidgetAreaRect, localPos); + + beginCommand(tr("Drop widget")); + + clearSelection(false); + highlightWidget(mw, QPoint(0, 0), FormWindow::Restore); + + QWidget *widget = clipboard.m_widgets.first(); + + insertWidget(widget, QRect(0, 0, 1, 1), mw); + + selectWidget(widget, true); + mw->setFocus(Qt::MouseFocusReason); // in case focus was in e.g. object inspector + + core()->formWindowManager()->setActiveFormWindow(this); + mainContainer()->activateWindow(); + + QDesignerPropertySheetExtension *propertySheet = qobject_cast<QDesignerPropertySheetExtension*>(m_core->extensionManager()->extension(widget, Q_TYPEID(QDesignerPropertySheetExtension))); + if (propertySheet) { + const QString dockWidgetAreaName = QLatin1String("dockWidgetArea"); + PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(propertySheet->property(propertySheet->indexOf(dockWidgetAreaName))); + e.value = area; + QVariant v; + qVariantSetValue(v, e); + SetPropertyCommand *cmd = new SetPropertyCommand(this); + cmd->init(widget, dockWidgetAreaName, v); + m_commandHistory->push(cmd); + } + + endCommand(); + return true; +} + +bool FormWindow::dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list, QWidget *target, + const QPoint &global_mouse_pos) +{ + + QWidget *parent = target; + if (parent == 0) + parent = mainContainer(); + // You can only drop stuff onto the central widget of a QMainWindow + // ### generalize to use container extension + if (QMainWindow *main_win = qobject_cast<QMainWindow*>(target)) { + if (!main_win->centralWidget()) { + designerWarning(tr("A QMainWindow-based form does not contain a central widget.")); + return false; + } + const QPoint main_win_pos = main_win->mapFromGlobal(global_mouse_pos); + const QRect central_wgt_geo = main_win->centralWidget()->geometry(); + if (!central_wgt_geo.contains(main_win_pos)) + return false; + } + + QWidget *container = findContainer(parent, false); + if (container == 0) + return false; + + beginCommand(tr("Drop widget")); + + clearSelection(false); + highlightWidget(target, target->mapFromGlobal(global_mouse_pos), FormWindow::Restore); + + QPoint offset; + QDesignerDnDItemInterface *current = 0; + QDesignerFormWindowCursorInterface *c = cursor(); + foreach (QDesignerDnDItemInterface *item, item_list) { + QWidget *w = item->widget(); + if (!current) + current = item; + if (c->current() == w) { + current = item; + break; + } + } + if (current) { + QRect geom = current->decoration()->geometry(); + QPoint topLeft = container->mapFromGlobal(geom.topLeft()); + offset = designerGrid().snapPoint(topLeft) - topLeft; + } + + foreach (QDesignerDnDItemInterface *item, item_list) { + DomUI *dom_ui = item->domUi(); + QRect geometry = item->decoration()->geometry(); + Q_ASSERT(dom_ui != 0); + + geometry.moveTopLeft(container->mapFromGlobal(geometry.topLeft()) + offset); + if (item->type() == QDesignerDnDItemInterface::CopyDrop) { // from widget box or CTRL + mouse move + QWidget *widget = createWidget(dom_ui, geometry, parent); + if (!widget) { + endCommand(); + return false; + } + selectWidget(widget, true); + mainContainer()->setFocus(Qt::MouseFocusReason); // in case focus was in e.g. object inspector + } else { // same form move + QWidget *widget = item->widget(); + Q_ASSERT(widget != 0); + QDesignerFormWindowInterface *dest = findFormWindow(widget); + if (dest == this) { + dragWidgetWithinForm(widget, geometry, container); + } else { // from other form + FormWindow *source = qobject_cast<FormWindow*>(item->source()); + Q_ASSERT(source != 0); + + source->deleteWidgetList(QWidgetList() << widget); + QWidget *new_widget = createWidget(dom_ui, geometry, parent); + + selectWidget(new_widget, true); + } + } + } + + core()->formWindowManager()->setActiveFormWindow(this); + mainContainer()->activateWindow(); + endCommand(); + return true; +} + +QDir FormWindow::absoluteDir() const +{ + if (fileName().isEmpty()) + return QDir::current(); + + return QFileInfo(fileName()).absoluteDir(); +} + +void FormWindow::layoutDefault(int *margin, int *spacing) +{ + *margin = m_defaultMargin; + *spacing = m_defaultSpacing; +} + +void FormWindow::setLayoutDefault(int margin, int spacing) +{ + m_defaultMargin = margin; + m_defaultSpacing = spacing; +} + +void FormWindow::layoutFunction(QString *margin, QString *spacing) +{ + *margin = m_marginFunction; + *spacing = m_spacingFunction; +} + +void FormWindow::setLayoutFunction(const QString &margin, const QString &spacing) +{ + m_marginFunction = margin; + m_spacingFunction = spacing; +} + +QString FormWindow::pixmapFunction() const +{ + return m_pixmapFunction; +} + +void FormWindow::setPixmapFunction(const QString &pixmapFunction) +{ + m_pixmapFunction = pixmapFunction; +} + +QStringList FormWindow::includeHints() const +{ + return m_includeHints; +} + +void FormWindow::setIncludeHints(const QStringList &includeHints) +{ + m_includeHints = includeHints; +} + +QString FormWindow::exportMacro() const +{ + return m_exportMacro; +} + +void FormWindow::setExportMacro(const QString &exportMacro) +{ + m_exportMacro = exportMacro; +} + +QEditorFormBuilder *FormWindow::createFormBuilder() +{ + return new QDesignerResource(this); +} + +QWidget *FormWindow::formContainer() const +{ + return m_widgetStack->formContainer(); +} + +} // namespace + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/formwindow.h b/tools/designer/src/components/formeditor/formwindow.h new file mode 100644 index 0000000..7e50ca2 --- /dev/null +++ b/tools/designer/src/components/formeditor/formwindow.h @@ -0,0 +1,385 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FORMWINDOW_H +#define FORMWINDOW_H + +#include "formeditor_global.h" +#include <formwindowbase_p.h> + +// Qt +#include <QtCore/QHash> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QSet> +#include <QtCore/QPointer> + +QT_BEGIN_NAMESPACE + +class QDesignerDnDItemInterface; +class QDesignerTaskMenuExtension; +class DomConnections; + +class QWidget; +class QAction; +class QLabel; +class QTimer; +class QAction; +class QMenu; +class QUndoStack; +class QRubberBand; + +namespace qdesigner_internal { + +class FormEditor; +class FormWindowCursor; +class WidgetEditorTool; +class FormWindowWidgetStack; +class FormWindowManager; +class FormWindowDnDItem; +class SetPropertyCommand; + +class QT_FORMEDITOR_EXPORT FormWindow: public FormWindowBase +{ + Q_OBJECT + +public: + explicit FormWindow(FormEditor *core, QWidget *parent = 0, Qt::WindowFlags flags = 0); + virtual ~FormWindow(); + + virtual QDesignerFormEditorInterface *core() const; + + virtual QDesignerFormWindowCursorInterface *cursor() const; + + // Overwritten: FormWindowBase + virtual QWidget *formContainer() const; + + virtual int toolCount() const; + virtual int currentTool() const; + virtual void setCurrentTool(int index); + virtual QDesignerFormWindowToolInterface *tool(int index) const; + virtual void registerTool(QDesignerFormWindowToolInterface *tool); + + virtual QString author() const; + virtual void setAuthor(const QString &author); + + virtual QString comment() const; + virtual void setComment(const QString &comment); + + virtual void layoutDefault(int *margin, int *spacing); + virtual void setLayoutDefault(int margin, int spacing); + + virtual void layoutFunction(QString *margin, QString *spacing); + virtual void setLayoutFunction(const QString &margin, const QString &spacing); + + virtual QString pixmapFunction() const; + virtual void setPixmapFunction(const QString &pixmapFunction); + + virtual QString exportMacro() const; + virtual void setExportMacro(const QString &exportMacro); + + virtual QStringList includeHints() const; + virtual void setIncludeHints(const QStringList &includeHints); + + virtual QString fileName() const; + virtual void setFileName(const QString &fileName); + + virtual QString contents() const; + virtual void setContents(const QString &contents); + virtual void setContents(QIODevice *dev); + + virtual QDir absoluteDir() const; + + virtual void simplifySelection(QWidgetList *sel) const; + + virtual void ensureUniqueObjectName(QObject *object); + + virtual QWidget *mainContainer() const; + void setMainContainer(QWidget *mainContainer); + bool isMainContainer(const QWidget *w) const; + + QWidget *currentWidget() const; + + bool hasInsertedChildren(QWidget *w) const; + + QList<QWidget *> selectedWidgets() const; + void clearSelection(bool changePropertyDisplay=true); + bool isWidgetSelected(QWidget *w) const; + void selectWidget(QWidget *w, bool select=true); + + void selectWidgets(); + void repaintSelection(); + void updateSelection(QWidget *w); + void updateChildSelections(QWidget *w); + void raiseChildSelections(QWidget *w); + void raiseSelection(QWidget *w); + + inline const QList<QWidget *>& widgets() const { return m_widgets; } + inline int widgetCount() const { return m_widgets.count(); } + inline QWidget *widgetAt(int index) const { return m_widgets.at(index); } + + QList<QWidget *> widgets(QWidget *widget) const; + + QWidget *createWidget(DomUI *ui, const QRect &rect, QWidget *target); + + bool isManaged(QWidget *w) const; + + void manageWidget(QWidget *w); + void unmanageWidget(QWidget *w); + + inline QUndoStack *commandHistory() const + { return m_commandHistory; } + + void beginCommand(const QString &description); + void endCommand(); + + virtual bool blockSelectionChanged(bool blocked); + virtual void emitSelectionChanged(); + + bool unify(QObject *w, QString &s, bool changeIt); + + bool isDirty() const; + void setDirty(bool dirty); + + static FormWindow *findFormWindow(QWidget *w); + + virtual QWidget *containerAt(const QPoint &pos); + virtual QWidget *widgetAt(const QPoint &pos); + virtual void highlightWidget(QWidget *w, const QPoint &pos, + HighlightMode mode = Highlight); + + void updateOrderIndicators(); + + bool handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event); + + QStringList resourceFiles() const; + void addResourceFile(const QString &path); + void removeResourceFile(const QString &path); + + void resizeWidget(QWidget *widget, const QRect &geometry); + + bool dropDockWidget(QDesignerDnDItemInterface *item, const QPoint &global_mouse_pos); + bool dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list, QWidget *target, + const QPoint &global_mouse_pos); + + virtual QWidget *findContainer(QWidget *w, bool excludeLayout) const; + // for WidgetSelection only. + QWidget *designerWidget(QWidget *w) const; + + // Initialize and return a popup menu for a managed widget + QMenu *initializePopupMenu(QWidget *managedWidget); + + virtual void paste(PasteMode pasteMode); + virtual QEditorFormBuilder *createFormBuilder(); + + bool eventFilter(QObject *watched, QEvent *event); + +signals: + void contextMenuRequested(QMenu *menu, QWidget *widget); + +public slots: + void deleteWidgets(); + void raiseWidgets(); + void lowerWidgets(); + void copy(); + void cut(); + void paste(); + void selectAll(); + + void createLayout(int type, QWidget *container = 0); + void morphLayout(QWidget *container, int newType); + void breakLayout(QWidget *w); + + void editContents(); + +protected: + virtual QMenu *createPopupMenu(QWidget *w); + virtual void resizeEvent(QResizeEvent *e); + + void insertWidget(QWidget *w, const QRect &rect, QWidget *target, bool already_in_form = false); + +private slots: + void selectionChangedTimerDone(); + void updateDirty(); + void checkSelection(); + void checkSelectionNow(); + void slotSelectWidget(QAction *); + +private: + enum MouseState { + NoMouseState, + // Double click received + MouseDoubleClicked, + // Drawing selection rubber band rectangle + MouseDrawRubber, + // Started a move operation + MouseMoveDrag, + // Click on a widget whose parent is selected. Defer selection to release + MouseDeferredSelection + }; + MouseState m_mouseState; + QPointer<QWidget> m_lastClickedWidget; + + void init(); + void initializeCoreTools(); + + int getValue(const QRect &rect, int key, bool size) const; + int calcValue(int val, bool forward, bool snap, int snapOffset) const; + QRect applyValue(const QRect &rect, int val, int key, bool size) const; + void handleClickSelection(QWidget *managedWidget, unsigned mouseFlags); + + bool frameNeeded(QWidget *w) const; + + enum RectType { Insert, Rubber }; + + void startRectDraw(const QPoint &global, QWidget *, RectType t); + void continueRectDraw(const QPoint &global, QWidget *, RectType t); + void endRectDraw(); + + QWidget *containerAt(const QPoint &pos, QWidget *notParentOf); + + void checkPreviewGeometry(QRect &r); + + void finishContextMenu(QWidget *w, QWidget *menuParent, QContextMenuEvent *e); + + bool handleContextMenu(QWidget *widget, QWidget *managedWidget, QContextMenuEvent *e); + bool handleMouseButtonDblClickEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e); + bool handleMousePressEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e); + bool handleMouseMoveEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e); + bool handleMouseReleaseEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e); + bool handleKeyPressEvent(QWidget *widget, QWidget *managedWidget, QKeyEvent *e); + bool handleKeyReleaseEvent(QWidget *widget, QWidget *managedWidget, QKeyEvent *e); + + bool isCentralWidget(QWidget *w) const; + + bool setCurrentWidget(QWidget *currentWidget); + bool trySelectWidget(QWidget *w, bool select); + + void dragWidgetWithinForm(QWidget *widget, const QRect &targetGeometry, QWidget *targetContainer); + + void setCursorToAll(const QCursor &c, QWidget *start); + + QPoint mapToForm(const QWidget *w, const QPoint &pos) const; + bool canBeBuddy(QWidget *w) const; + + QWidget *findTargetContainer(QWidget *widget) const; + + void clearMainContainer(); + + static int widgetDepth(const QWidget *w); + static bool isChildOf(const QWidget *c, const QWidget *p); + + void editWidgets(); + + void updateWidgets(); + + void handleArrowKeyEvent(int key, Qt::KeyboardModifiers modifiers); + + void layoutSelection(int type); + void layoutContainer(QWidget *w, int type); + +private: + QWidget *innerContainer(QWidget *outerContainer) const; + QWidget *containerForPaste() const; + QAction *createSelectAncestorSubMenu(QWidget *w); + void selectSingleWidget(QWidget *w); + + FormEditor *m_core; + FormWindowCursor *m_cursor; + QWidget *m_mainContainer; + QWidget *m_currentWidget; + + bool m_blockSelectionChanged; + + QPoint m_rectAnchor; + QRect m_currRect; + + QWidgetList m_widgets; + QSet<QWidget*> m_insertedWidgets; + + class Selection; + Selection *m_selection; + + QPoint m_startPos; + + QUndoStack *m_commandHistory; + + QString m_fileName; + + typedef QPair<QPalette ,bool> PaletteAndFill; + typedef QMap<QWidget*, PaletteAndFill> WidgetPaletteMap; + WidgetPaletteMap m_palettesBeforeHighlight; + + QRubberBand *m_rubberBand; + + QTimer *m_selectionChangedTimer; + QTimer *m_checkSelectionTimer; + QTimer *m_geometryChangedTimer; + + int m_dirty; + int m_lastIndex; + + FormWindowWidgetStack *m_widgetStack; + WidgetEditorTool *m_widgetEditor; + + QStringList m_resourceFiles; + + QString m_comment; + QString m_author; + QString m_pixmapFunction; + int m_defaultMargin, m_defaultSpacing; + QString m_marginFunction, m_spacingFunction; + QString m_exportMacro; + QStringList m_includeHints; + + QList<SetPropertyCommand*> m_moveSelection; + int m_lastUndoIndex; + QPoint m_contextMenuPosition; + +private: + friend class WidgetEditorTool; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // FORMWINDOW_H diff --git a/tools/designer/src/components/formeditor/formwindow_dnditem.cpp b/tools/designer/src/components/formeditor/formwindow_dnditem.cpp new file mode 100644 index 0000000..3af5343 --- /dev/null +++ b/tools/designer/src/components/formeditor/formwindow_dnditem.cpp @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "formwindow_dnditem.h" +#include "formwindow.h" + +#include <ui4_p.h> +#include <qdesigner_resource.h> +#include <qtresourcemodel_p.h> + +#include <QtDesigner/QDesignerFormEditorInterface> + +#include <QtGui/QLabel> +#include <QtGui/QPixmap> + +QT_BEGIN_NAMESPACE + +using namespace qdesigner_internal; + +static QWidget *decorationFromWidget(QWidget *w) +{ + QLabel *label = new QLabel(0, Qt::ToolTip); + QPixmap pm = QPixmap::grabWidget(w); + label->setPixmap(pm); + label->resize(pm.size()); + + return label; +} + +static DomUI *widgetToDom(QWidget *widget, FormWindow *form) +{ + QDesignerResource builder(form); + builder.setSaveRelative(false); + return builder.copy(FormBuilderClipboard(widget)); +} + +FormWindowDnDItem::FormWindowDnDItem(QDesignerDnDItemInterface::DropType type, FormWindow *form, + QWidget *widget, const QPoint &global_mouse_pos) + : QDesignerDnDItem(type, form) +{ + QWidget *decoration = decorationFromWidget(widget); + QPoint pos = widget->mapToGlobal(QPoint(0, 0)); + decoration->move(pos); + + init(0, widget, decoration, global_mouse_pos); +} + +DomUI *FormWindowDnDItem::domUi() const +{ + DomUI *result = QDesignerDnDItem::domUi(); + if (result != 0) + return result; + FormWindow *form = qobject_cast<FormWindow*>(source()); + if (widget() == 0 || form == 0) + return 0; + + QtResourceModel *resourceModel = form->core()->resourceModel(); + QtResourceSet *currentResourceSet = resourceModel->currentResourceSet(); + /* Short: + * We need to activate the original resourceSet associated with a form + * to properly generate the dom resource includes. + * Long: + * widgetToDom() calls copy() on QDesignerResource. It generates the + * Dom structure. In order to create DomResources properly we need to + * have the associated ResourceSet active (QDesignerResource::saveResources() + * queries the resource model for a qrc path for the given resource file: + * qrcFile = m_core->resourceModel()->qrcPath(ri->text()); + * This works only when the resource file comes from the active + * resourceSet */ + resourceModel->setCurrentResourceSet(form->resourceSet()); + + result = widgetToDom(widget(), form); + const_cast<FormWindowDnDItem*>(this)->setDomUi(result); + resourceModel->setCurrentResourceSet(currentResourceSet); + return result; +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/formwindow_dnditem.h b/tools/designer/src/components/formeditor/formwindow_dnditem.h new file mode 100644 index 0000000..c6e7479 --- /dev/null +++ b/tools/designer/src/components/formeditor/formwindow_dnditem.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FORMWINDOW_DNDITEM_H +#define FORMWINDOW_DNDITEM_H + +#include <qdesigner_dnditem_p.h> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +class FormWindow; + +class FormWindowDnDItem : public QDesignerDnDItem +{ +public: + FormWindowDnDItem(QDesignerDnDItemInterface::DropType type, FormWindow *form, + QWidget *widget, const QPoint &global_mouse_pos); + virtual DomUI *domUi() const; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // FORMWINDOW_DNDITEM_H diff --git a/tools/designer/src/components/formeditor/formwindow_widgetstack.cpp b/tools/designer/src/components/formeditor/formwindow_widgetstack.cpp new file mode 100644 index 0000000..7270628 --- /dev/null +++ b/tools/designer/src/components/formeditor/formwindow_widgetstack.cpp @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "formwindow_widgetstack.h" +#include <QtDesigner/QDesignerFormWindowToolInterface> + +#include <QtGui/QWidget> +#include <QtGui/qevent.h> +#include <QtGui/QAction> +#include <QtGui/QStackedLayout> +#include <QtGui/QVBoxLayout> + +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +using namespace qdesigner_internal; + +FormWindowWidgetStack::FormWindowWidgetStack(QObject *parent) : + QObject(parent), + m_formContainer(new QWidget), + m_formContainerLayout(new QVBoxLayout), + m_layout(new QStackedLayout) +{ + m_layout->setMargin(0); + m_layout->setSpacing(0); + m_layout->setStackingMode(QStackedLayout::StackAll); + + m_formContainerLayout->setMargin(0); + m_formContainer->setObjectName(QLatin1String("formContainer")); + m_formContainer->setLayout(m_formContainerLayout); + // System settings might have different background colors, autofill them + // (affects for example mainwindow status bars) + m_formContainer->setAutoFillBackground(true); +} + +FormWindowWidgetStack::~FormWindowWidgetStack() +{ +} + +int FormWindowWidgetStack::count() const +{ + return m_tools.count(); +} + +QDesignerFormWindowToolInterface *FormWindowWidgetStack::currentTool() const +{ + return tool(currentIndex()); +} + +void FormWindowWidgetStack::setCurrentTool(int index) +{ + const int cnt = count(); + if (index < 0 || index >= cnt) { + qDebug("FormWindowWidgetStack::setCurrentTool(): invalid index: %d", index); + return; + } + + const int cur = currentIndex(); + if (index == cur) + return; + + if (cur != -1) + m_tools.at(cur)->deactivated(); + + + m_layout->setCurrentIndex(index); + // Show the widget editor and the current tool + for (int i = 0; i < cnt; i++) + m_tools.at(i)->editor()->setVisible(i == 0 || i == index); + + QDesignerFormWindowToolInterface *tool = m_tools.at(index); + tool->activated(); + + emit currentToolChanged(index); +} + +void FormWindowWidgetStack::setSenderAsCurrentTool() +{ + QDesignerFormWindowToolInterface *tool = 0; + QAction *action = qobject_cast<QAction*>(sender()); + if (action == 0) { + qDebug("FormWindowWidgetStack::setSenderAsCurrentTool(): sender is not a QAction"); + return; + } + + foreach (QDesignerFormWindowToolInterface *t, m_tools) { + if (action == t->action()) { + tool = t; + break; + } + } + + if (tool == 0) { + qDebug("FormWindowWidgetStack::setSenderAsCurrentTool(): unknown tool"); + return; + } + + setCurrentTool(tool); +} + +int FormWindowWidgetStack::indexOf(QDesignerFormWindowToolInterface *tool) const +{ + return m_tools.indexOf(tool); +} + +void FormWindowWidgetStack::setCurrentTool(QDesignerFormWindowToolInterface *tool) +{ + int index = indexOf(tool); + if (index == -1) { + qDebug("FormWindowWidgetStack::setCurrentTool(): unknown tool"); + return; + } + + setCurrentTool(index); +} + +void FormWindowWidgetStack::setMainContainer(QWidget *w) +{ + // This code is triggered once by the formwindow and + // by integrations doing "revert to saved". Anything changing? + const int previousCount = m_formContainerLayout->count(); + QWidget *previousMainContainer = previousCount ? m_formContainerLayout->itemAt(0)->widget() : static_cast<QWidget*>(0); + if (previousMainContainer == w) + return; + // Swap + if (previousCount) + delete m_formContainerLayout->takeAt(0); + if (w) + m_formContainerLayout->addWidget(w); +} + +void FormWindowWidgetStack::addTool(QDesignerFormWindowToolInterface *tool) +{ + if (QWidget *w = tool->editor()) { + w->setVisible(m_layout->count() == 0); // Initially only form editor is visible + m_layout->addWidget(w); + } else { + // The form editor might not have a tool initially, use dummy. Assert on anything else + Q_ASSERT(m_tools.empty()); + m_layout->addWidget(m_formContainer); + } + + m_tools.append(tool); + + connect(tool->action(), SIGNAL(triggered()), this, SLOT(setSenderAsCurrentTool())); +} + +QDesignerFormWindowToolInterface *FormWindowWidgetStack::tool(int index) const +{ + if (index < 0 || index >= count()) + return 0; + + return m_tools.at(index); +} + +int FormWindowWidgetStack::currentIndex() const +{ + return m_layout->currentIndex(); +} + +QWidget *FormWindowWidgetStack::defaultEditor() const +{ + if (m_tools.isEmpty()) + return 0; + + return m_tools.at(0)->editor(); +} + +QLayout *FormWindowWidgetStack::layout() const +{ + return m_layout; +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/formwindow_widgetstack.h b/tools/designer/src/components/formeditor/formwindow_widgetstack.h new file mode 100644 index 0000000..92323c5 --- /dev/null +++ b/tools/designer/src/components/formeditor/formwindow_widgetstack.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FORMWINDOW_WIDGETSTACK_H +#define FORMWINDOW_WIDGETSTACK_H + +#include "formeditor_global.h" + +#include <QtGui/QWidget> + +QT_BEGIN_NAMESPACE + +class QDesignerFormWindowToolInterface; + +class QStackedLayout; +class QVBoxLayout; +class QWidget; + +namespace qdesigner_internal { + +class QT_FORMEDITOR_EXPORT FormWindowWidgetStack: public QObject +{ + Q_OBJECT +public: + FormWindowWidgetStack(QObject *parent = 0); + virtual ~FormWindowWidgetStack(); + + QLayout *layout() const; + + int count() const; + QDesignerFormWindowToolInterface *tool(int index) const; + QDesignerFormWindowToolInterface *currentTool() const; + int currentIndex() const; + int indexOf(QDesignerFormWindowToolInterface *tool) const; + + void setMainContainer(QWidget *w = 0); + + // Return the widget containing the form which can be used to apply embedded design settings to. + // These settings should not affect the other editing tools. + QWidget *formContainer() const { return m_formContainer; } + +signals: + void currentToolChanged(int index); + +public slots: + void addTool(QDesignerFormWindowToolInterface *tool); + void setCurrentTool(QDesignerFormWindowToolInterface *tool); + void setCurrentTool(int index); + void setSenderAsCurrentTool(); + +protected: + QWidget *defaultEditor() const; + +private: + QList<QDesignerFormWindowToolInterface*> m_tools; + QWidget *m_formContainer; + QVBoxLayout *m_formContainerLayout; + QStackedLayout *m_layout; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // FORMWINDOW_WIDGETSTACK_H diff --git a/tools/designer/src/components/formeditor/formwindowcursor.cpp b/tools/designer/src/components/formeditor/formwindowcursor.cpp new file mode 100644 index 0000000..fb30885 --- /dev/null +++ b/tools/designer/src/components/formeditor/formwindowcursor.cpp @@ -0,0 +1,211 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "formwindowcursor.h" +#include "formwindow.h" + +// sdk +#include <QtDesigner/propertysheet.h> +#include <QtDesigner/QExtensionManager> +#include <qdesigner_propertycommand_p.h> + +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +FormWindowCursor::FormWindowCursor(FormWindow *fw, QObject *parent) + : QObject(parent), + m_formWindow(fw) +{ + update(); + connect(fw, SIGNAL(changed()), this, SLOT(update())); +} + +FormWindowCursor::~FormWindowCursor() +{ +} + +QDesignerFormWindowInterface *FormWindowCursor::formWindow() const +{ + return m_formWindow; +} + +bool FormWindowCursor::movePosition(MoveOperation op, MoveMode mode) +{ + if (widgetCount() == 0) + return false; + + int iterator = position(); + + if (mode == MoveAnchor) + m_formWindow->clearSelection(false); + + switch (op) { + case Next: + ++iterator; + if (iterator >= widgetCount()) + iterator = 0; + + m_formWindow->selectWidget(m_formWindow->widgetAt(iterator), true); + return true; + + case Prev: + --iterator; + if (iterator < 0) + iterator = widgetCount() - 1; + + if (iterator < 0) + return false; + + m_formWindow->selectWidget(m_formWindow->widgetAt(iterator), true); + return true; + + default: + return false; + } +} + +int FormWindowCursor::position() const +{ + const int index = m_formWindow->widgets().indexOf(current()); + return index == -1 ? 0 : index; +} + +void FormWindowCursor::setPosition(int pos, MoveMode mode) +{ + if (!widgetCount()) + return; + + if (mode == MoveAnchor) + m_formWindow->clearSelection(false); + + if (pos >= widgetCount()) + pos = 0; + + m_formWindow->selectWidget(m_formWindow->widgetAt(pos), true); +} + +QWidget *FormWindowCursor::current() const +{ + return m_formWindow->currentWidget(); +} + +bool FormWindowCursor::hasSelection() const +{ + return !m_formWindow->selectedWidgets().isEmpty(); +} + +int FormWindowCursor::selectedWidgetCount() const +{ + int N = m_formWindow->selectedWidgets().count(); + return N ? N : 1; +} + +QWidget *FormWindowCursor::selectedWidget(int index) const +{ + return hasSelection() + ? m_formWindow->selectedWidgets().at(index) + : m_formWindow->mainContainer(); +} + +void FormWindowCursor::update() +{ + // ### todo +} + +int FormWindowCursor::widgetCount() const +{ + return m_formWindow->widgetCount(); +} + +QWidget *FormWindowCursor::widget(int index) const +{ + return m_formWindow->widgetAt(index); +} + +void FormWindowCursor::setProperty(const QString &name, const QVariant &value) +{ + + // build selection + const int N = selectedWidgetCount(); + Q_ASSERT(N); + + SetPropertyCommand::ObjectList selection; + for (int i=0; i<N; ++i) + selection.push_back(selectedWidget(i)); + + + SetPropertyCommand* setPropertyCommand = new SetPropertyCommand(m_formWindow); + if (setPropertyCommand->init(selection, name, value, current())) { + m_formWindow->commandHistory()->push(setPropertyCommand); + } else { + delete setPropertyCommand; + qDebug() << "Unable to set property " << name << '.'; + } +} + +void FormWindowCursor::setWidgetProperty(QWidget *widget, const QString &name, const QVariant &value) +{ + SetPropertyCommand *cmd = new SetPropertyCommand(m_formWindow); + if (cmd->init(widget, name, value)) { + m_formWindow->commandHistory()->push(cmd); + } else { + delete cmd; + qDebug() << "Unable to set property " << name << '.'; + } +} + +void FormWindowCursor::resetWidgetProperty(QWidget *widget, const QString &name) +{ + ResetPropertyCommand *cmd = new ResetPropertyCommand(m_formWindow); + if (cmd->init(widget, name)) { + m_formWindow->commandHistory()->push(cmd); + } else { + delete cmd; + qDebug() << "Unable to reset property " << name << '.'; + } +} + +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/formwindowcursor.h b/tools/designer/src/components/formeditor/formwindowcursor.h new file mode 100644 index 0000000..7167432 --- /dev/null +++ b/tools/designer/src/components/formeditor/formwindowcursor.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FORMWINDOWCURSOR_H +#define FORMWINDOWCURSOR_H + +#include "formeditor_global.h" +#include "formwindow.h" +#include <QtDesigner/QDesignerFormWindowCursorInterface> + +#include <QtCore/QObject> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +class QT_FORMEDITOR_EXPORT FormWindowCursor: public QObject, public QDesignerFormWindowCursorInterface +{ + Q_OBJECT +public: + explicit FormWindowCursor(FormWindow *fw, QObject *parent = 0); + virtual ~FormWindowCursor(); + + virtual QDesignerFormWindowInterface *formWindow() const; + + virtual bool movePosition(MoveOperation op, MoveMode mode); + + virtual int position() const; + virtual void setPosition(int pos, MoveMode mode); + + virtual QWidget *current() const; + + virtual int widgetCount() const; + virtual QWidget *widget(int index) const; + + virtual bool hasSelection() const; + virtual int selectedWidgetCount() const; + virtual QWidget *selectedWidget(int index) const; + + virtual void setProperty(const QString &name, const QVariant &value); + virtual void setWidgetProperty(QWidget *widget, const QString &name, const QVariant &value); + virtual void resetWidgetProperty(QWidget *widget, const QString &name); + +public slots: + void update(); + +private: + FormWindow *m_formWindow; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // FORMWINDOWCURSOR_H diff --git a/tools/designer/src/components/formeditor/formwindowmanager.cpp b/tools/designer/src/components/formeditor/formwindowmanager.cpp new file mode 100644 index 0000000..ea8d128 --- /dev/null +++ b/tools/designer/src/components/formeditor/formwindowmanager.cpp @@ -0,0 +1,1016 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// components/formeditor +#include "formwindowmanager.h" +#include "formwindow_dnditem.h" +#include "formwindow.h" +#include "formeditor.h" +#include "widgetselection.h" +#include "previewactiongroup.h" +#include "formwindowsettings.h" + +// shared +#include <widgetdatabase_p.h> +#include <iconloader_p.h> +#include <connectionedit_p.h> +#include <qtresourcemodel_p.h> +#include <qdesigner_dnditem_p.h> +#include <qdesigner_command_p.h> +#include <qdesigner_command2_p.h> +#include <layoutinfo_p.h> +#include <qlayout_widget_p.h> +#include <qdesigner_objectinspector_p.h> +#include <actioneditor_p.h> +#include <shared_settings_p.h> +#include <previewmanager_p.h> +#include <abstractdialoggui_p.h> +#include <widgetfactory_p.h> +#include <spacer_widget_p.h> + +// SDK +#include <QtDesigner/QExtensionManager> +#include <QtDesigner/QDesignerLanguageExtension> +#include <QtDesigner/QDesignerContainerExtension> +#include <QtDesigner/QDesignerWidgetBoxInterface> +#include <QtDesigner/QDesignerIntegrationInterface> + +#include <QtGui/QUndoGroup> +#include <QtGui/QAction> +#include <QtGui/QSplitter> +#include <QtGui/QMouseEvent> +#include <QtGui/QApplication> +#include <QtGui/QSizeGrip> +#include <QtGui/QClipboard> +#include <QtGui/QMdiArea> +#include <QtGui/QMdiSubWindow> +#include <QtGui/QDesktopWidget> +#include <QtGui/QMessageBox> + +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +namespace { + enum { debugFWM = 0 }; +} + +static inline QString whatsThisFrom(const QString &str) { /// ### implement me! + return str; +} + +// find the first child of w in a sequence +template <class Iterator> +static inline Iterator findFirstChildOf(Iterator it,Iterator end, const QWidget *w) +{ + for (;it != end; ++it) { + if (w->isAncestorOf(*it)) + return it; + } + return it; +} + +namespace qdesigner_internal { + +FormWindowManager::FormWindowManager(QDesignerFormEditorInterface *core, QObject *parent) : + QDesignerFormWindowManager(parent), + m_core(core), + m_activeFormWindow(0), + m_previewManager(new PreviewManager(PreviewManager::SingleFormNonModalPreview, this)), + m_createLayoutContext(LayoutContainer), + m_morphLayoutContainer(0), + m_actionGroupPreviewInStyle(0), + m_actionShowFormWindowSettingsDialog(0) +{ + setupActions(); + qApp->installEventFilter(this); +} + +FormWindowManager::~FormWindowManager() +{ + qDeleteAll(m_formWindows); +} + +QDesignerFormEditorInterface *FormWindowManager::core() const +{ + return m_core; +} + +QDesignerFormWindowInterface *FormWindowManager::activeFormWindow() const +{ + return m_activeFormWindow; +} + +int FormWindowManager::formWindowCount() const +{ + return m_formWindows.size(); +} + +QDesignerFormWindowInterface *FormWindowManager::formWindow(int index) const +{ + return m_formWindows.at(index); +} + +bool FormWindowManager::eventFilter(QObject *o, QEvent *e) +{ + if (!o->isWidgetType()) + return false; + + // If we don't have an active form, we only listen for WindowActivate to speed up integrations + const QEvent::Type eventType = e->type(); + if (m_activeFormWindow == 0 && eventType != QEvent::WindowActivate) + return false; + + switch (eventType) { // Uninteresting events + case QEvent::Create: + case QEvent::Destroy: + case QEvent::AccessibilityDescription: + case QEvent::AccessibilityHelp: + case QEvent::AccessibilityPrepare: + case QEvent::ActionAdded: + case QEvent::ActionChanged: + case QEvent::ActionRemoved: + case QEvent::ChildAdded: + case QEvent::ChildPolished: + case QEvent::ChildRemoved: + case QEvent::Clipboard: + case QEvent::ContentsRectChange: + case QEvent::DeferredDelete: + case QEvent::FileOpen: + case QEvent::LanguageChange: + case QEvent::MetaCall: + case QEvent::ModifiedChange: + case QEvent::Paint: + case QEvent::PaletteChange: + case QEvent::ParentAboutToChange: + case QEvent::ParentChange: + case QEvent::Polish: + case QEvent::PolishRequest: + case QEvent::QueryWhatsThis: + case QEvent::StatusTip: + case QEvent::StyleChange: + case QEvent::Timer: + case QEvent::ToolBarChange: + case QEvent::ToolTip: + case QEvent::WhatsThis: + case QEvent::WhatsThisClicked: + case QEvent::DynamicPropertyChange: + case QEvent::HoverEnter: + case QEvent::HoverLeave: + case QEvent::HoverMove: + return false; + default: + break; + } + + QWidget *widget = static_cast<QWidget*>(o); + + if (qobject_cast<WidgetHandle*>(widget)) { // ### remove me + return false; + } + + FormWindow *fw = FormWindow::findFormWindow(widget); + if (fw == 0) { + return false; + } + + if (QWidget *managedWidget = findManagedWidget(fw, widget)) { + // Prevent MDI and QWorkspace subwindows from being closed by clicking at the title bar + if (managedWidget != widget && eventType == QEvent::Close) { + e->ignore(); + return true; + } + switch (eventType) { + + case QEvent::WindowActivate: { + if (fw->parentWidget()->isWindow() && fw->isMainContainer(managedWidget) && activeFormWindow() != fw) { + setActiveFormWindow(fw); + } + } break; + + case QEvent::WindowDeactivate: { + if (o == fw && o == activeFormWindow()) + fw->repaintSelection(); + } break; + + case QEvent::KeyPress: { + QKeyEvent *ke = static_cast<QKeyEvent*>(e); + if (ke->key() == Qt::Key_Escape) { + ke->accept(); + return true; + } + } + // don't break... + // Embedded Design: Drop on different form: Make sure the right form + // window/device is active before having the widget created by the factory + case QEvent::Drop: + if (activeFormWindow() != fw) + setActiveFormWindow(fw); + // don't break... + default: { + if (fw->handleEvent(widget, managedWidget, e)) { + return true; + } + } break; + + } // end switch + } + + return false; +} + +void FormWindowManager::addFormWindow(QDesignerFormWindowInterface *w) +{ + FormWindow *formWindow = qobject_cast<FormWindow*>(w); + if (!formWindow || m_formWindows.contains(formWindow)) + return; + + connect(formWindow, SIGNAL(selectionChanged()), this, SLOT(slotUpdateActions())); + connect(formWindow->commandHistory(), SIGNAL(indexChanged(int)), this, SLOT(slotUpdateActions())); + connect(formWindow, SIGNAL(toolChanged(int)), this, SLOT(slotUpdateActions())); + + if (ActionEditor *ae = qobject_cast<ActionEditor *>(m_core->actionEditor())) + connect(w, SIGNAL(mainContainerChanged(QWidget*)), ae, SLOT(mainContainerChanged())); + if (QDesignerObjectInspector *oi = qobject_cast<QDesignerObjectInspector *>(m_core->objectInspector())) + connect(w, SIGNAL(mainContainerChanged(QWidget*)), oi, SLOT(mainContainerChanged())); + + m_formWindows.append(formWindow); + emit formWindowAdded(formWindow); +} + +void FormWindowManager::removeFormWindow(QDesignerFormWindowInterface *w) +{ + FormWindow *formWindow = qobject_cast<FormWindow*>(w); + + int idx = m_formWindows.indexOf(formWindow); + if (!formWindow || idx == -1) + return; + + formWindow->disconnect(this); + m_formWindows.removeAt(idx); + emit formWindowRemoved(formWindow); + + if (formWindow == m_activeFormWindow) + setActiveFormWindow(0); + + if (m_formWindows.size() == 0 + && m_core->widgetBox()) { + // Make sure that widget box is enabled by default + m_core->widgetBox()->setEnabled(true); + } + +} + +void FormWindowManager::setActiveFormWindow(QDesignerFormWindowInterface *w) +{ + FormWindow *formWindow = qobject_cast<FormWindow*>(w); + + if (formWindow == m_activeFormWindow) + return; + + FormWindow *old = m_activeFormWindow; + + m_activeFormWindow = formWindow; + + QtResourceSet *resourceSet = 0; + if (formWindow) + resourceSet = formWindow->resourceSet(); + m_core->resourceModel()->setCurrentResourceSet(resourceSet); + + slotUpdateActions(); + + if (m_activeFormWindow) { + m_activeFormWindow->repaintSelection(); + if (old) + old->repaintSelection(); + } + + emit activeFormWindowChanged(m_activeFormWindow); + + if (m_activeFormWindow) { + m_activeFormWindow->emitSelectionChanged(); + m_activeFormWindow->commandHistory()->setActive(); + // Trigger setActiveSubWindow on mdi area unless we are in toplevel mode + QMdiSubWindow *mdiSubWindow = 0; + if (QWidget *formwindow = m_activeFormWindow->parentWidget()) { + mdiSubWindow = qobject_cast<QMdiSubWindow *>(formwindow->parentWidget()); + } + if (mdiSubWindow) { + for (QWidget *parent = mdiSubWindow->parentWidget(); parent; parent = parent->parentWidget()) { + if (QMdiArea *mdiArea = qobject_cast<QMdiArea*>(parent)) { + mdiArea->setActiveSubWindow(mdiSubWindow); + break; + } + } + } + } +} + +void FormWindowManager::closeAllPreviews() +{ + m_previewManager->closeAllPreviews(); +} + +QWidget *FormWindowManager::findManagedWidget(FormWindow *fw, QWidget *w) +{ + while (w && w != fw) { + if (fw->isManaged(w)) + break; + w = w->parentWidget(); + } + return w; +} + +void FormWindowManager::setupActions() +{ + m_actionCut = new QAction(createIconSet(QLatin1String("editcut.png")), tr("Cu&t"), this); + m_actionCut->setObjectName(QLatin1String("__qt_cut_action")); + m_actionCut->setShortcut(QKeySequence::Cut); + m_actionCut->setStatusTip(tr("Cuts the selected widgets and puts them on the clipboard")); + m_actionCut->setWhatsThis(whatsThisFrom(QLatin1String("Edit|Cut"))); + connect(m_actionCut, SIGNAL(triggered()), this, SLOT(slotActionCutActivated())); + m_actionCut->setEnabled(false); + + m_actionCopy = new QAction(createIconSet(QLatin1String("editcopy.png")), tr("&Copy"), this); + m_actionCopy->setObjectName(QLatin1String("__qt_copy_action")); + m_actionCopy->setShortcut(QKeySequence::Copy); + m_actionCopy->setStatusTip(tr("Copies the selected widgets to the clipboard")); + m_actionCopy->setWhatsThis(whatsThisFrom(QLatin1String("Edit|Copy"))); + connect(m_actionCopy, SIGNAL(triggered()), this, SLOT(slotActionCopyActivated())); + m_actionCopy->setEnabled(false); + + m_actionPaste = new QAction(createIconSet(QLatin1String("editpaste.png")), tr("&Paste"), this); + m_actionPaste->setObjectName(QLatin1String("__qt_paste_action")); + m_actionPaste->setShortcut(QKeySequence::Paste); + m_actionPaste->setStatusTip(tr("Pastes the clipboard's contents")); + m_actionPaste->setWhatsThis(whatsThisFrom(QLatin1String("Edit|Paste"))); + connect(m_actionPaste, SIGNAL(triggered()), this, SLOT(slotActionPasteActivated())); + m_actionPaste->setEnabled(false); + + m_actionDelete = new QAction(tr("&Delete"), this); + m_actionDelete->setObjectName(QLatin1String("__qt_delete_action")); + m_actionDelete->setStatusTip(tr("Deletes the selected widgets")); + m_actionDelete->setWhatsThis(whatsThisFrom(QLatin1String("Edit|Delete"))); + connect(m_actionDelete, SIGNAL(triggered()), this, SLOT(slotActionDeleteActivated())); + m_actionDelete->setEnabled(false); + + m_actionSelectAll = new QAction(tr("Select &All"), this); + m_actionSelectAll->setObjectName(QLatin1String("__qt_select_all_action")); + m_actionSelectAll->setShortcut(QKeySequence::SelectAll); + m_actionSelectAll->setStatusTip(tr("Selects all widgets")); + m_actionSelectAll->setWhatsThis(whatsThisFrom(QLatin1String("Edit|Select All"))); + connect(m_actionSelectAll, SIGNAL(triggered()), this, SLOT(slotActionSelectAllActivated())); + m_actionSelectAll->setEnabled(false); + + m_actionRaise = new QAction(createIconSet(QLatin1String("editraise.png")), tr("Bring to &Front"), this); + m_actionRaise->setObjectName(QLatin1String("__qt_raise_action")); + m_actionRaise->setShortcut(Qt::CTRL + Qt::Key_L); + m_actionRaise->setStatusTip(tr("Raises the selected widgets")); + m_actionRaise->setWhatsThis(tr("Raises the selected widgets")); + connect(m_actionRaise, SIGNAL(triggered()), this, SLOT(slotActionRaiseActivated())); + m_actionRaise->setEnabled(false); + + m_actionLower = new QAction(createIconSet(QLatin1String("editlower.png")), tr("Send to &Back"), this); + m_actionLower->setObjectName(QLatin1String("__qt_lower_action")); + m_actionLower->setShortcut(Qt::CTRL + Qt::Key_K); + m_actionLower->setStatusTip(tr("Lowers the selected widgets")); + m_actionLower->setWhatsThis(tr("Lowers the selected widgets")); + connect(m_actionLower, SIGNAL(triggered()), this, SLOT(slotActionLowerActivated())); + m_actionLower->setEnabled(false); + + m_actionAdjustSize = new QAction(createIconSet(QLatin1String("adjustsize.png")), tr("Adjust &Size"), this); + m_actionAdjustSize->setObjectName(QLatin1String("__qt_adjust_size_action")); + m_actionAdjustSize->setShortcut(Qt::CTRL + Qt::Key_J); + m_actionAdjustSize->setStatusTip(tr("Adjusts the size of the selected widget")); + m_actionAdjustSize->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Adjust Size"))); + connect(m_actionAdjustSize, SIGNAL(triggered()), this, SLOT(slotActionAdjustSizeActivated())); + m_actionAdjustSize->setEnabled(false); + + + m_actionHorizontalLayout = new QAction(createIconSet(QLatin1String("edithlayout.png")), tr("Lay Out &Horizontally"), this); + m_actionHorizontalLayout->setObjectName(QLatin1String("__qt_horizontal_layout_action")); + m_actionHorizontalLayout->setShortcut(Qt::CTRL + Qt::Key_1); + m_actionHorizontalLayout->setStatusTip(tr("Lays out the selected widgets horizontally")); + m_actionHorizontalLayout->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Lay Out Horizontally"))); + m_actionHorizontalLayout->setData(LayoutInfo::HBox); + m_actionHorizontalLayout->setEnabled(false); + connect(m_actionHorizontalLayout, SIGNAL(triggered()), this, SLOT(createLayout())); + + m_actionVerticalLayout = new QAction(createIconSet(QLatin1String("editvlayout.png")), tr("Lay Out &Vertically"), this); + m_actionVerticalLayout->setObjectName(QLatin1String("__qt_vertical_layout_action")); + m_actionVerticalLayout->setShortcut(Qt::CTRL + Qt::Key_2); + m_actionVerticalLayout->setStatusTip(tr("Lays out the selected widgets vertically")); + m_actionVerticalLayout->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Lay Out Vertically"))); + m_actionVerticalLayout->setData(LayoutInfo::VBox); + m_actionVerticalLayout->setEnabled(false); + connect(m_actionVerticalLayout, SIGNAL(triggered()), this, SLOT(createLayout())); + + QAction *actionFormLayout = new QAction(createIconSet(QLatin1String("editform.png")), tr("Lay Out in a &Form Layout"), this); + actionFormLayout->setObjectName(QLatin1String("__qt_form_layout_action")); + actionFormLayout->setShortcut(Qt::CTRL + Qt::Key_6); + actionFormLayout->setStatusTip(tr("Lays out the selected widgets in a form layout")); + actionFormLayout->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Lay Out in a Form"))); + actionFormLayout->setData(LayoutInfo::Form); + actionFormLayout->setEnabled(false); + setActionFormLayout(actionFormLayout); + connect(actionFormLayout, SIGNAL(triggered()), this, SLOT(createLayout())); + + m_actionGridLayout = new QAction(createIconSet(QLatin1String("editgrid.png")), tr("Lay Out in a &Grid"), this); + m_actionGridLayout->setObjectName(QLatin1String("__qt_grid_layout_action")); + m_actionGridLayout->setShortcut(Qt::CTRL + Qt::Key_5); + m_actionGridLayout->setStatusTip(tr("Lays out the selected widgets in a grid")); + m_actionGridLayout->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Lay Out in a Grid"))); + m_actionGridLayout->setData(LayoutInfo::Grid); + m_actionGridLayout->setEnabled(false); + connect(m_actionGridLayout, SIGNAL(triggered()), this, SLOT(createLayout())); + + m_actionSplitHorizontal = new QAction(createIconSet(QLatin1String("edithlayoutsplit.png")), + tr("Lay Out Horizontally in S&plitter"), this); + m_actionSplitHorizontal->setObjectName(QLatin1String("__qt_split_horizontal_action")); + m_actionSplitHorizontal->setShortcut(Qt::CTRL + Qt::Key_3); + m_actionSplitHorizontal->setStatusTip(tr("Lays out the selected widgets horizontally in a splitter")); + m_actionSplitHorizontal->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Lay Out Horizontally in Splitter"))); + m_actionSplitHorizontal->setData(LayoutInfo::HSplitter); + m_actionSplitHorizontal->setEnabled(false); + connect(m_actionSplitHorizontal, SIGNAL(triggered()), this, SLOT(createLayout())); + + m_actionSplitVertical = new QAction(createIconSet(QLatin1String("editvlayoutsplit.png")), + tr("Lay Out Vertically in Sp&litter"), this); + m_actionSplitVertical->setObjectName(QLatin1String("__qt_split_vertical_action")); + m_actionSplitVertical->setShortcut(Qt::CTRL + Qt::Key_4); + m_actionSplitVertical->setStatusTip(tr("Lays out the selected widgets vertically in a splitter")); + m_actionSplitVertical->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Lay Out Vertically in Splitter"))); + connect(m_actionSplitVertical, SIGNAL(triggered()), this, SLOT(createLayout())); + m_actionSplitVertical->setData(LayoutInfo::VSplitter); + + m_actionSplitVertical->setEnabled(false); + + m_actionBreakLayout = new QAction(createIconSet(QLatin1String("editbreaklayout.png")), tr("&Break Layout"), this); + m_actionBreakLayout->setObjectName(QLatin1String("__qt_break_layout_action")); + m_actionBreakLayout->setShortcut(Qt::CTRL + Qt::Key_0); + m_actionBreakLayout->setStatusTip(tr("Breaks the selected layout")); + m_actionBreakLayout->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Break Layout"))); + connect(m_actionBreakLayout, SIGNAL(triggered()), this, SLOT(slotActionBreakLayoutActivated())); + m_actionBreakLayout->setEnabled(false); + + QAction *simplifyLayoutAction = new QAction(tr("Si&mplify Grid Layout"), this); + simplifyLayoutAction->setObjectName(QLatin1String("__qt_simplify_layout_action")); + simplifyLayoutAction->setStatusTip(tr("Removes empty columns and rows")); + simplifyLayoutAction->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Simplify Layout"))); + connect(simplifyLayoutAction, SIGNAL(triggered()), this, SLOT(slotActionSimplifyLayoutActivated())); + simplifyLayoutAction->setEnabled(false); + setActionSimplifyLayout(simplifyLayoutAction); + + m_actionDefaultPreview = new QAction(tr("&Preview..."), this); + m_actionDefaultPreview->setObjectName(QLatin1String("__qt_default_preview_action")); + m_actionDefaultPreview->setStatusTip(tr("Preview current form")); + m_actionDefaultPreview->setWhatsThis(whatsThisFrom(QLatin1String("Form|Preview"))); + connect(m_actionDefaultPreview, SIGNAL(triggered()), + this, SLOT(slotActionDefaultPreviewActivated())); + + m_undoGroup = new QUndoGroup(this); + + m_actionUndo = m_undoGroup->createUndoAction(this); + m_actionUndo->setEnabled(false); + m_actionUndo->setIcon(createIconSet(QLatin1String("undo.png"))); + m_actionRedo = m_undoGroup->createRedoAction(this); + m_actionRedo->setEnabled(false); + m_actionRedo->setIcon(createIconSet(QLatin1String("redo.png"))); + + m_actionShowFormWindowSettingsDialog = new QAction(tr("Form &Settings..."), this); + m_actionShowFormWindowSettingsDialog->setObjectName(QLatin1String("__qt_form_settings_action")); + connect(m_actionShowFormWindowSettingsDialog, SIGNAL(triggered()), this, SLOT(slotActionShowFormWindowSettingsDialog())); + m_actionShowFormWindowSettingsDialog->setEnabled(false); +} + +void FormWindowManager::slotActionCutActivated() +{ + m_activeFormWindow->cut(); +} + +void FormWindowManager::slotActionCopyActivated() +{ + m_activeFormWindow->copy(); + slotUpdateActions(); +} + +void FormWindowManager::slotActionPasteActivated() +{ + m_activeFormWindow->paste(); +} + +void FormWindowManager::slotActionDeleteActivated() +{ + m_activeFormWindow->deleteWidgets(); +} + +void FormWindowManager::slotActionLowerActivated() +{ + m_activeFormWindow->lowerWidgets(); +} + +void FormWindowManager::slotActionRaiseActivated() +{ + m_activeFormWindow->raiseWidgets(); +} + +static inline QWidget *findLayoutContainer(const FormWindow *fw) +{ + QList<QWidget*> l(fw->selectedWidgets()); + fw->simplifySelection(&l); + return l.empty() ? fw->mainContainer() : l.front(); +} + +void FormWindowManager::createLayout() +{ + QAction *a = qobject_cast<QAction *>(sender()); + if (!a) + return; + const int type = a->data().toInt(); + switch (m_createLayoutContext) { + case LayoutContainer: + // Cannot create a splitter on a container + if (type != LayoutInfo::HSplitter && type != LayoutInfo::VSplitter) + m_activeFormWindow->createLayout(type, findLayoutContainer(m_activeFormWindow)); + break; + case LayoutSelection: + m_activeFormWindow->createLayout(type); + break; + case MorphLayout: + m_activeFormWindow->morphLayout(m_morphLayoutContainer, type); + break; + } +} + +void FormWindowManager::slotActionBreakLayoutActivated() +{ + const QList<QWidget *> layouts = layoutsToBeBroken(); + if (layouts.isEmpty()) + return; + + if (debugFWM) { + qDebug() << "slotActionBreakLayoutActivated: " << layouts.size(); + foreach (QWidget *w, layouts) { + qDebug() << w; + } + } + + m_activeFormWindow->beginCommand(tr("Break Layout")); + foreach (QWidget *layout, layouts) { + m_activeFormWindow->breakLayout(layout); + } + m_activeFormWindow->endCommand(); +} + +void FormWindowManager::slotActionSimplifyLayoutActivated() +{ + Q_ASSERT(m_activeFormWindow != 0); + QWidgetList selectedWidgets = m_activeFormWindow->selectedWidgets(); + m_activeFormWindow->simplifySelection(&selectedWidgets); + if (selectedWidgets.size() != 1) + return; + SimplifyLayoutCommand *cmd = new SimplifyLayoutCommand(m_activeFormWindow); + if (cmd->init(selectedWidgets.front())) { + m_activeFormWindow->commandHistory()->push(cmd); + } else { + delete cmd; + } +} + +void FormWindowManager::slotActionAdjustSizeActivated() +{ + Q_ASSERT(m_activeFormWindow != 0); + + m_activeFormWindow->beginCommand(tr("Adjust Size")); + + QList<QWidget*> selectedWidgets = m_activeFormWindow->selectedWidgets(); + m_activeFormWindow->simplifySelection(&selectedWidgets); + + if (selectedWidgets.isEmpty()) { + Q_ASSERT(m_activeFormWindow->mainContainer() != 0); + selectedWidgets.append(m_activeFormWindow->mainContainer()); + } + + // Always count the main container as unlaid-out + foreach (QWidget *widget, selectedWidgets) { + bool unlaidout = LayoutInfo::layoutType(core(), widget->parentWidget()) == LayoutInfo::NoLayout; + bool isMainContainer = m_activeFormWindow->isMainContainer(widget); + + if (unlaidout || isMainContainer) { + AdjustWidgetSizeCommand *cmd = new AdjustWidgetSizeCommand(m_activeFormWindow); + cmd->init(widget); + m_activeFormWindow->commandHistory()->push(cmd); + } + } + + m_activeFormWindow->endCommand(); +} + +void FormWindowManager::slotActionSelectAllActivated() +{ + m_activeFormWindow->selectAll(); +} + +void FormWindowManager::slotActionDefaultPreviewActivated() +{ + slotActionGroupPreviewInStyle(QString(), -1); +} + +void FormWindowManager::slotActionGroupPreviewInStyle(const QString &style, int deviceProfileIndex) +{ + QDesignerFormWindowInterface *fw = activeFormWindow(); + if (!fw) + return; + + QString errorMessage; + if (!m_previewManager->showPreview(fw, style, deviceProfileIndex, &errorMessage)) { + const QString title = tr("Could not create form preview", "Title of warning message box"); + core()->dialogGui()->message(fw, QDesignerDialogGuiInterface::FormEditorMessage, QMessageBox::Warning, + title, errorMessage); + } +} + +// The user might click on a layout child or the actual layout container. +QWidgetList FormWindowManager::layoutsToBeBroken(QWidget *w) const +{ + if (!w) + return QList<QWidget *>(); + + if (debugFWM) + qDebug() << "layoutsToBeBroken: " << w; + + QWidget *parent = w->parentWidget(); + if (m_activeFormWindow->isMainContainer(w)) + parent = 0; + + QWidget *widget = core()->widgetFactory()->containerOfWidget(w); + + // maybe we want to remove following block + const QDesignerWidgetDataBaseInterface *db = m_core->widgetDataBase(); + const QDesignerWidgetDataBaseItemInterface *item = db->item(db->indexOfObject(widget)); + if (!item) { + if (debugFWM) + qDebug() << "layoutsToBeBroken: Don't have an item, recursing for parent"; + return layoutsToBeBroken(parent); + } + + const bool layoutContainer = (item->isContainer() || m_activeFormWindow->isMainContainer(widget)); + + if (!layoutContainer) { + if (debugFWM) + qDebug() << "layoutsToBeBroken: Not a container, recursing for parent"; + return layoutsToBeBroken(parent); + } + + QLayout *widgetLayout = widget->layout(); + QLayout *managedLayout = LayoutInfo::managedLayout(m_core, widgetLayout); + if (!managedLayout) { + if (qobject_cast<const QSplitter *>(widget)) { + if (debugFWM) + qDebug() << "layoutsToBeBroken: Splitter special"; + QList<QWidget *> list = layoutsToBeBroken(parent); + list.append(widget); + return list; + } + if (debugFWM) + qDebug() << "layoutsToBeBroken: Is a container but doesn't have a managed layout (has an internal layout), returning 0"; + return QList<QWidget *>(); + } + + if (managedLayout) { + QList<QWidget *> list; + if (debugFWM) + qDebug() << "layoutsToBeBroken: Is a container and has a layout"; + if (qobject_cast<const QLayoutWidget *>(widget)) { + if (debugFWM) + qDebug() << "layoutsToBeBroken: red layout special case"; + list = layoutsToBeBroken(parent); + } + list.append(widget); + return list; + } + if (debugFWM) + qDebug() << "layoutsToBeBroken: Is a container but doesn't have a layout at all, returning 0"; + return QList<QWidget *>(); + +} + +QMap<QWidget *, bool> FormWindowManager::getUnsortedLayoutsToBeBroken(bool firstOnly) const +{ + // Return a set of layouts to be broken. + QMap<QWidget *, bool> layouts; + + QList<QWidget *> selection = m_activeFormWindow->selectedWidgets(); + if (selection.isEmpty() && m_activeFormWindow->mainContainer()) + selection.append(m_activeFormWindow->mainContainer()); + + const QList<QWidget *>::const_iterator scend = selection.constEnd(); + for (QList<QWidget *>::const_iterator sit = selection.constBegin(); sit != scend; ++sit) { + // find all layouts + const QList<QWidget *> list = layoutsToBeBroken(*sit); + if (!list.empty()) { + const QList<QWidget *>::const_iterator lbcend = list.constEnd(); + for (QList<QWidget *>::const_iterator lbit = list.constBegin(); lbit != lbcend; ++lbit) { + layouts.insert(*lbit, true); + } + if (firstOnly) + return layouts; + } + } + return layouts; +} + +bool FormWindowManager::hasLayoutsToBeBroken() const +{ + // Quick check for layouts to be broken + return !getUnsortedLayoutsToBeBroken(true).isEmpty(); +} + +QWidgetList FormWindowManager::layoutsToBeBroken() const +{ + // Get all layouts. This is a list of all 'red' layouts (QLayoutWidgets) + // up to the first 'real' widget with a layout in hierarchy order. + QMap<QWidget *, bool> unsortedLayouts = getUnsortedLayoutsToBeBroken(false); + // Sort in order of hierarchy + QList<QWidget *> orderedLayoutList; + const QMap<QWidget *, bool>::const_iterator lscend = unsortedLayouts.constEnd(); + for (QMap<QWidget *, bool>::const_iterator itLay = unsortedLayouts.constBegin(); itLay != lscend; ++itLay) { + QWidget *wToBeInserted = itLay.key(); + if (!orderedLayoutList.contains(wToBeInserted)) { + // try to find first child, use as insertion position, else append + const QList<QWidget *>::iterator firstChildPos = findFirstChildOf(orderedLayoutList.begin(), orderedLayoutList.end(), wToBeInserted); + if (firstChildPos == orderedLayoutList.end()) { + orderedLayoutList.push_back(wToBeInserted); + } else { + orderedLayoutList.insert(firstChildPos, wToBeInserted); + } + } + } + return orderedLayoutList; +} + +static inline bool hasManagedLayoutItems(const QDesignerFormEditorInterface *core, QWidget *w) +{ + if (const QLayout *ml = LayoutInfo::managedLayout(core, w)) { + // Try to find managed items, ignore dummy grid spacers + const int count = ml->count(); + for (int i = 0; i < count; i++) + if (!LayoutInfo::isEmptyItem(ml->itemAt(i))) + return true; + } + return false; +} + +void FormWindowManager::slotUpdateActions() +{ + m_createLayoutContext = LayoutSelection; + m_morphLayoutContainer = 0; + bool canMorphIntoVBoxLayout = false; + bool canMorphIntoHBoxLayout = false; + bool canMorphIntoGridLayout = false; + bool canMorphIntoFormLayout = false; + int selectedWidgetCount = 0; + int laidoutWidgetCount = 0; + int unlaidoutWidgetCount = 0; + bool pasteAvailable = false; + bool layoutAvailable = false; + bool breakAvailable = false; + bool simplifyAvailable = false; + bool layoutContainer = false; + bool canChangeZOrder = true; + + do { + if (m_activeFormWindow == 0 || m_activeFormWindow->currentTool() != 0) + break; + + breakAvailable = hasLayoutsToBeBroken(); + + QWidgetList simplifiedSelection = m_activeFormWindow->selectedWidgets(); + + selectedWidgetCount = simplifiedSelection.count(); + pasteAvailable = qApp->clipboard()->mimeData() && qApp->clipboard()->mimeData()->hasText(); + + m_activeFormWindow->simplifySelection(&simplifiedSelection); + QWidget *mainContainer = m_activeFormWindow->mainContainer(); + if (simplifiedSelection.isEmpty() && mainContainer) + simplifiedSelection.append(mainContainer); + + // Always count the main container as unlaid-out + const QWidgetList::const_iterator cend = simplifiedSelection.constEnd(); + for (QWidgetList::const_iterator it = simplifiedSelection.constBegin(); it != cend; ++it) { + if (*it != mainContainer && LayoutInfo::isWidgetLaidout(m_core, *it)) { + ++laidoutWidgetCount; + } else { + ++unlaidoutWidgetCount; + } + if (qobject_cast<const QLayoutWidget *>(*it) || qobject_cast<const Spacer *>(*it)) + canChangeZOrder = false; + } + + // Figure out layouts: Looking at a group of dangling widgets + if (simplifiedSelection.count() != 1) { + layoutAvailable = unlaidoutWidgetCount > 1; + //breakAvailable = false; + break; + } + // Manipulate layout of a single widget + m_createLayoutContext = LayoutSelection; + QWidget *widget = core()->widgetFactory()->containerOfWidget(simplifiedSelection.first()); + if (widget == 0) // We are looking at a page-based container with 0 pages + break; + + const QDesignerWidgetDataBaseInterface *db = m_core->widgetDataBase(); + const QDesignerWidgetDataBaseItemInterface *item = db->item(db->indexOfObject(widget)); + if (!item) + break; + + QLayout *widgetLayout = LayoutInfo::internalLayout(widget); + QLayout *managedLayout = LayoutInfo::managedLayout(m_core, widgetLayout); + // We don't touch a layout createds by a custom widget + if (widgetLayout && !managedLayout) + break; + + layoutContainer = (item->isContainer() || m_activeFormWindow->isMainContainer(widget)); + + layoutAvailable = layoutContainer && m_activeFormWindow->hasInsertedChildren(widget) && managedLayout == 0; + simplifyAvailable = SimplifyLayoutCommand::canSimplify(m_core, widget); + if (layoutAvailable) { + m_createLayoutContext = LayoutContainer; + } else { + /* Cannot create a layout, have some layouts to be broken and + * exactly one, non-empty layout with selected: check the morph layout options + * (Note that there might be > 1 layouts to broken if the selection + * is a red layout, however, we want the inner-most layout here). */ + if (breakAvailable && simplifiedSelection.size() == 1 + && hasManagedLayoutItems(m_core, widget)) { + int type; + m_morphLayoutContainer = widget; // Was: page of first selected + m_createLayoutContext = MorphLayout; + if (MorphLayoutCommand::canMorph(m_activeFormWindow, m_morphLayoutContainer, &type)) { + canMorphIntoVBoxLayout = type != LayoutInfo::VBox; + canMorphIntoHBoxLayout = type != LayoutInfo::HBox; + canMorphIntoGridLayout = type != LayoutInfo::Grid; + canMorphIntoFormLayout = type != LayoutInfo::Form; + } + } + } + } while(false); + + m_actionCut->setEnabled(selectedWidgetCount > 0); + m_actionCopy->setEnabled(selectedWidgetCount > 0); + m_actionDelete->setEnabled(selectedWidgetCount > 0); + m_actionLower->setEnabled(canChangeZOrder && selectedWidgetCount > 0); + m_actionRaise->setEnabled(canChangeZOrder && selectedWidgetCount > 0); + + m_actionPaste->setEnabled(pasteAvailable); + + m_actionSelectAll->setEnabled(m_activeFormWindow != 0); + + m_actionAdjustSize->setEnabled(unlaidoutWidgetCount > 0); + + m_actionHorizontalLayout->setEnabled(layoutAvailable || canMorphIntoHBoxLayout); + m_actionVerticalLayout->setEnabled(layoutAvailable || canMorphIntoVBoxLayout); + m_actionSplitHorizontal->setEnabled(layoutAvailable && !layoutContainer); + m_actionSplitVertical->setEnabled(layoutAvailable && !layoutContainer); + actionFormLayout()->setEnabled(layoutAvailable || canMorphIntoFormLayout); + m_actionGridLayout->setEnabled(layoutAvailable || canMorphIntoGridLayout); + + m_actionBreakLayout->setEnabled(breakAvailable); + actionSimplifyLayout()->setEnabled(simplifyAvailable); + m_actionShowFormWindowSettingsDialog->setEnabled(m_activeFormWindow != 0); +} + +QDesignerFormWindowInterface *FormWindowManager::createFormWindow(QWidget *parentWidget, Qt::WindowFlags flags) +{ + FormWindow *formWindow = new FormWindow(qobject_cast<FormEditor*>(core()), parentWidget, flags); + formWindow->setProperty(WidgetFactory::disableStyleCustomPaintingPropertyC, QVariant(true)); + addFormWindow(formWindow); + return formWindow; +} + +QPixmap FormWindowManager::createPreviewPixmap(QString *errorMessage) +{ + QPixmap pixmap; + QDesignerFormWindowInterface *fw = activeFormWindow(); + if (!fw) + return pixmap; + + pixmap = m_previewManager->createPreviewPixmap(fw, QString(), errorMessage); + return pixmap; +} + +QAction *FormWindowManager::actionUndo() const +{ + return m_actionUndo; +} + +QAction *FormWindowManager::actionRedo() const +{ + return m_actionRedo; +} + +QActionGroup *FormWindowManager::actionGroupPreviewInStyle() const +{ + if (m_actionGroupPreviewInStyle == 0) { + // Wish we could make the 'this' pointer mutable ;-) + QObject *parent = const_cast<FormWindowManager*>(this); + m_actionGroupPreviewInStyle = new PreviewActionGroup(m_core, parent); + connect(m_actionGroupPreviewInStyle, SIGNAL(preview(QString,int)), + this, SLOT(slotActionGroupPreviewInStyle(QString,int))); + } + return m_actionGroupPreviewInStyle; +} + +void FormWindowManager::deviceProfilesChanged() +{ + if (m_actionGroupPreviewInStyle) + m_actionGroupPreviewInStyle->updateDeviceProfiles(); +} + +// DnD stuff + +void FormWindowManager::dragItems(const QList<QDesignerDnDItemInterface*> &item_list) +{ + QDesignerMimeData::execDrag(item_list, m_core->topLevel()); +} + +QUndoGroup *FormWindowManager::undoGroup() const +{ + return m_undoGroup; +} + +QAction *FormWindowManager::actionShowFormWindowSettingsDialog() const +{ + return m_actionShowFormWindowSettingsDialog; +} + +void FormWindowManager::slotActionShowFormWindowSettingsDialog() +{ + QDesignerFormWindowInterface *fw = activeFormWindow(); + if (!fw) + return; + + QDialog *settingsDialog = 0; + const bool wasDirty = fw->isDirty(); + + // Ask the language extension for a dialog. If not, create our own + if (QDesignerLanguageExtension *lang = qt_extension<QDesignerLanguageExtension*>(m_core->extensionManager(), m_core)) + settingsDialog = lang->createFormWindowSettingsDialog(fw, /*parent=*/ 0); + + if (!settingsDialog) + settingsDialog = new FormWindowSettings(fw); + + QString title = QFileInfo(fw->fileName()).fileName(); + if (title.isEmpty()) // Grab the title from the outer window if no filename + if (const QWidget *window = m_core->integration()->containerWindow(fw)) + title = window->windowTitle(); + + settingsDialog->setWindowTitle(tr("Form Settings - %1").arg(title)); + if (settingsDialog->exec()) + if (fw->isDirty() != wasDirty) + emit formWindowSettingsChanged(fw); + + delete settingsDialog; +} + +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/formwindowmanager.h b/tools/designer/src/components/formeditor/formwindowmanager.h new file mode 100644 index 0000000..d81ec2d --- /dev/null +++ b/tools/designer/src/components/formeditor/formwindowmanager.h @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FORMWINDOWMANAGER_H +#define FORMWINDOWMANAGER_H + +#include "formeditor_global.h" + +#include <QtDesigner/private/qdesigner_formwindowmanager_p.h> + +#include <QtCore/QObject> +#include <QtCore/QList> +#include <QtCore/QPointer> +#include <QtCore/QMap> + +QT_BEGIN_NAMESPACE + +class QAction; +class QActionGroup; +class QUndoGroup; +class QDesignerFormEditorInterface; +class QDesignerWidgetBoxInterface; + +namespace qdesigner_internal { + +class FormWindow; +class PreviewManager; +class PreviewActionGroup; + +class QT_FORMEDITOR_EXPORT FormWindowManager + : public QDesignerFormWindowManager +{ + Q_OBJECT +public: + explicit FormWindowManager(QDesignerFormEditorInterface *core, QObject *parent = 0); + virtual ~FormWindowManager(); + + virtual QDesignerFormEditorInterface *core() const; + + inline QAction *actionCut() const { return m_actionCut; } + inline QAction *actionCopy() const { return m_actionCopy; } + inline QAction *actionPaste() const { return m_actionPaste; } + inline QAction *actionDelete() const { return m_actionDelete; } + inline QAction *actionSelectAll() const { return m_actionSelectAll; } + inline QAction *actionLower() const { return m_actionLower; } + inline QAction *actionRaise() const { return m_actionRaise; } + QAction *actionUndo() const; + QAction *actionRedo() const; + + inline QAction *actionHorizontalLayout() const { return m_actionHorizontalLayout; } + inline QAction *actionVerticalLayout() const { return m_actionVerticalLayout; } + inline QAction *actionSplitHorizontal() const { return m_actionSplitHorizontal; } + inline QAction *actionSplitVertical() const { return m_actionSplitVertical; } + inline QAction *actionGridLayout() const { return m_actionGridLayout; } + inline QAction *actionBreakLayout() const { return m_actionBreakLayout; } + inline QAction *actionAdjustSize() const { return m_actionAdjustSize; } + + inline QAction *actionDefaultPreview() const { return m_actionDefaultPreview; } + QActionGroup *actionGroupPreviewInStyle() const; + virtual QAction *actionShowFormWindowSettingsDialog() const; + + QDesignerFormWindowInterface *activeFormWindow() const; + + int formWindowCount() const; + QDesignerFormWindowInterface *formWindow(int index) const; + + QDesignerFormWindowInterface *createFormWindow(QWidget *parentWidget = 0, Qt::WindowFlags flags = 0); + + QPixmap createPreviewPixmap(QString *errorMessage); + + bool eventFilter(QObject *o, QEvent *e); + + void dragItems(const QList<QDesignerDnDItemInterface*> &item_list); + + QUndoGroup *undoGroup() const; + + virtual PreviewManager *previewManager() const { return m_previewManager; } + +public slots: + void addFormWindow(QDesignerFormWindowInterface *formWindow); + void removeFormWindow(QDesignerFormWindowInterface *formWindow); + void setActiveFormWindow(QDesignerFormWindowInterface *formWindow); + void closeAllPreviews(); + void deviceProfilesChanged(); + +private slots: + void slotActionCutActivated(); + void slotActionCopyActivated(); + void slotActionPasteActivated(); + void slotActionDeleteActivated(); + void slotActionSelectAllActivated(); + void slotActionLowerActivated(); + void slotActionRaiseActivated(); + void createLayout(); + void slotActionBreakLayoutActivated(); + void slotActionAdjustSizeActivated(); + void slotActionSimplifyLayoutActivated(); + void slotActionDefaultPreviewActivated(); + void slotActionGroupPreviewInStyle(const QString &style, int deviceProfileIndex); + void slotActionShowFormWindowSettingsDialog(); + + void slotUpdateActions(); + +private: + void setupActions(); + FormWindow *findFormWindow(QWidget *w); + QWidget *findManagedWidget(FormWindow *fw, QWidget *w); + + void setCurrentUndoStack(QUndoStack *stack); + +private: + enum CreateLayoutContext { LayoutContainer, LayoutSelection, MorphLayout }; + + QDesignerFormEditorInterface *m_core; + FormWindow *m_activeFormWindow; + QList<FormWindow*> m_formWindows; + + PreviewManager *m_previewManager; + + /* Context of the layout actions and base for morphing layouts. Determined + * in slotUpdateActions() and used later on in the action slots. */ + CreateLayoutContext m_createLayoutContext; + QWidget *m_morphLayoutContainer; + + // edit actions + QAction *m_actionCut; + QAction *m_actionCopy; + QAction *m_actionPaste; + QAction *m_actionSelectAll; + QAction *m_actionDelete; + QAction *m_actionLower; + QAction *m_actionRaise; + // layout actions + QAction *m_actionHorizontalLayout; + QAction *m_actionVerticalLayout; + QAction *m_actionSplitHorizontal; + QAction *m_actionSplitVertical; + QAction *m_actionGridLayout; + QAction *m_actionBreakLayout; + QAction *m_actionAdjustSize; + // preview actions + QAction *m_actionDefaultPreview; + mutable PreviewActionGroup *m_actionGroupPreviewInStyle; + QAction *m_actionShowFormWindowSettingsDialog; + + QAction *m_actionUndo; + QAction *m_actionRedo; + + QMap<QWidget *,bool> getUnsortedLayoutsToBeBroken(bool firstOnly) const; + bool hasLayoutsToBeBroken() const; + QWidgetList layoutsToBeBroken(QWidget *w) const; + QWidgetList layoutsToBeBroken() const; + + QUndoGroup *m_undoGroup; + +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // FORMWINDOWMANAGER_H diff --git a/tools/designer/src/components/formeditor/formwindowsettings.cpp b/tools/designer/src/components/formeditor/formwindowsettings.cpp new file mode 100644 index 0000000..1f6d5dd --- /dev/null +++ b/tools/designer/src/components/formeditor/formwindowsettings.cpp @@ -0,0 +1,282 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "formwindowsettings.h" +#include "ui_formwindowsettings.h" + +#include <formwindowbase_p.h> +#include <grid_p.h> + +#include <QtGui/QStyle> + +#include <QtCore/QRegExp> +#include <QtCore/QDebug> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +// Data structure containing form dialog data providing comparison +struct FormWindowData { + FormWindowData(); + + bool equals(const FormWindowData&) const; + + void fromFormWindow(FormWindowBase* fw); + void applyToFormWindow(FormWindowBase* fw) const; + + bool layoutDefaultEnabled; + int defaultMargin; + int defaultSpacing; + + bool layoutFunctionsEnabled; + QString marginFunction; + QString spacingFunction; + + QString pixFunction; + + QString author; + + QStringList includeHints; + + bool hasFormGrid; + Grid grid; +}; + +inline bool operator==(const FormWindowData &fd1, const FormWindowData &fd2) { return fd1.equals(fd2); } +inline bool operator!=(const FormWindowData &fd1, const FormWindowData &fd2) { return !fd1.equals(fd2); } + +QDebug operator<<(QDebug str, const FormWindowData &d) +{ + str.nospace() << "LayoutDefault=" << d.layoutDefaultEnabled << ',' << d.defaultMargin + << ',' << d.defaultSpacing << " LayoutFunctions=" << d.layoutFunctionsEnabled << ',' + << d.marginFunction << ',' << d.spacingFunction << " PixFunction=" + << d.pixFunction << " Author=" << d.author << " Hints=" << d.includeHints + << " Grid=" << d.hasFormGrid << d.grid.deltaX() << d.grid.deltaY() << '\n'; + return str; +} + +FormWindowData::FormWindowData() : + layoutDefaultEnabled(false), + defaultMargin(0), + defaultSpacing(0), + layoutFunctionsEnabled(false), + hasFormGrid(false) +{ +} + +bool FormWindowData::equals(const FormWindowData &rhs) const +{ + return layoutDefaultEnabled == rhs.layoutDefaultEnabled && + defaultMargin == rhs.defaultMargin && + defaultSpacing == rhs.defaultSpacing && + layoutFunctionsEnabled == rhs.layoutFunctionsEnabled && + marginFunction == rhs.marginFunction && + spacingFunction == rhs.spacingFunction && + pixFunction == rhs.pixFunction && + author == rhs.author && + includeHints == rhs.includeHints && + hasFormGrid == rhs.hasFormGrid && + grid == rhs.grid; +} + +void FormWindowData::fromFormWindow(FormWindowBase* fw) +{ + defaultMargin = defaultSpacing = INT_MIN; + fw->layoutDefault(&defaultMargin, &defaultSpacing); + + QStyle *style = fw->formContainer()->style(); + layoutDefaultEnabled = defaultMargin != INT_MIN || defaultMargin != INT_MIN; + if (defaultMargin == INT_MIN) + defaultMargin = style->pixelMetric(QStyle::PM_DefaultChildMargin, 0); + if (defaultSpacing == INT_MIN) + defaultSpacing = style->pixelMetric(QStyle::PM_DefaultLayoutSpacing, 0); + + + marginFunction.clear(); + spacingFunction.clear(); + fw->layoutFunction(&marginFunction, &spacingFunction); + layoutFunctionsEnabled = !marginFunction.isEmpty() || !spacingFunction.isEmpty(); + + pixFunction = fw->pixmapFunction(); + + author = fw->author(); + + includeHints = fw->includeHints(); + includeHints.removeAll(QString()); + + hasFormGrid = fw->hasFormGrid(); + grid = hasFormGrid ? fw->designerGrid() : FormWindowBase::defaultDesignerGrid(); +} + +void FormWindowData::applyToFormWindow(FormWindowBase* fw) const +{ + fw->setAuthor(author); + fw->setPixmapFunction(pixFunction); + + if (layoutDefaultEnabled) { + fw->setLayoutDefault(defaultMargin, defaultSpacing); + } else { + fw->setLayoutDefault(INT_MIN, INT_MIN); + } + + if (layoutFunctionsEnabled) { + fw->setLayoutFunction(marginFunction, spacingFunction); + } else { + fw->setLayoutFunction(QString(), QString()); + } + + fw->setIncludeHints(includeHints); + + const bool hadFormGrid = fw->hasFormGrid(); + fw->setHasFormGrid(hasFormGrid); + if (hasFormGrid || hadFormGrid != hasFormGrid) + fw->setDesignerGrid(hasFormGrid ? grid : FormWindowBase::defaultDesignerGrid()); +} + +// -------------------------- FormWindowSettings + +FormWindowSettings::FormWindowSettings(QDesignerFormWindowInterface *parent) : + QDialog(parent), + m_ui(new ::Ui::FormWindowSettings), + m_formWindow(qobject_cast<FormWindowBase*>(parent)), + m_oldData(new FormWindowData) +{ + Q_ASSERT(m_formWindow); + + m_ui->setupUi(this); + m_ui->gridPanel->setCheckable(true); + m_ui->gridPanel->setResetButtonVisible(false); + + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + + QString deviceProfileName = m_formWindow->deviceProfileName(); + if (deviceProfileName.isEmpty()) + deviceProfileName = tr("None"); + m_ui->deviceProfileLabel->setText(tr("Device Profile: %1").arg(deviceProfileName)); + + m_oldData->fromFormWindow(m_formWindow); + setData(*m_oldData); +} + +FormWindowSettings::~FormWindowSettings() +{ + delete m_oldData; + delete m_ui; +} + +FormWindowData FormWindowSettings::data() const +{ + FormWindowData rc; + rc.author = m_ui->authorLineEdit->text(); + + if (m_ui->pixmapFunctionGroupBox->isChecked()) { + rc.pixFunction = m_ui->pixmapFunctionLineEdit->text(); + } else { + rc.pixFunction.clear(); + } + + rc.layoutDefaultEnabled = m_ui->layoutDefaultGroupBox->isChecked(); + rc.defaultMargin = m_ui->defaultMarginSpinBox->value(); + rc.defaultSpacing = m_ui->defaultSpacingSpinBox->value(); + + rc.layoutFunctionsEnabled = m_ui->layoutFunctionGroupBox->isChecked(); + rc.marginFunction = m_ui->marginFunctionLineEdit->text(); + rc.spacingFunction = m_ui->spacingFunctionLineEdit->text(); + + const QString hints = m_ui->includeHintsTextEdit->toPlainText(); + if (!hints.isEmpty()) { + rc.includeHints = hints.split(QString(QLatin1Char('\n'))); + // Purge out any lines consisting of blanks only + const QRegExp blankLine = QRegExp(QLatin1String("^\\s*$")); + Q_ASSERT(blankLine.isValid()); + for (QStringList::iterator it = rc.includeHints.begin(); it != rc.includeHints.end(); ) + if (blankLine.exactMatch(*it)) { + it = rc.includeHints.erase(it); + } else { + ++it; + } + rc.includeHints.removeAll(QString()); + } + + rc.hasFormGrid = m_ui->gridPanel->isChecked(); + rc.grid = m_ui->gridPanel->grid(); + return rc; +} + +void FormWindowSettings::setData(const FormWindowData &data) +{ + m_ui->layoutDefaultGroupBox->setChecked(data.layoutDefaultEnabled); + m_ui->defaultMarginSpinBox->setValue(data.defaultMargin); + m_ui->defaultSpacingSpinBox->setValue(data.defaultSpacing); + + m_ui->layoutFunctionGroupBox->setChecked(data.layoutFunctionsEnabled); + m_ui->marginFunctionLineEdit->setText(data.marginFunction); + m_ui->spacingFunctionLineEdit->setText(data.spacingFunction); + + m_ui->pixmapFunctionLineEdit->setText(data.pixFunction); + m_ui->pixmapFunctionGroupBox->setChecked(!data.pixFunction.isEmpty()); + + m_ui->authorLineEdit->setText(data.author); + + if (data.includeHints.empty()) { + m_ui->includeHintsTextEdit->clear(); + } else { + m_ui->includeHintsTextEdit->setText(data.includeHints.join(QLatin1String("\n"))); + } + + m_ui->gridPanel->setChecked(data.hasFormGrid); + m_ui->gridPanel->setGrid(data.grid); +} + +void FormWindowSettings::accept() +{ + // Anything changed? -> Apply and set dirty + const FormWindowData newData = data(); + if (newData != *m_oldData) { + newData.applyToFormWindow(m_formWindow); + m_formWindow->setDirty(true); + } + + QDialog::accept(); +} +} +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/formwindowsettings.h b/tools/designer/src/components/formeditor/formwindowsettings.h new file mode 100644 index 0000000..4289f42 --- /dev/null +++ b/tools/designer/src/components/formeditor/formwindowsettings.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FORMWINDOWSETTINGS_H +#define FORMWINDOWSETTINGS_H + +#include <QDialog> + +QT_BEGIN_NAMESPACE + +namespace Ui { + class FormWindowSettings; +} + +class QDesignerFormWindowInterface; + +namespace qdesigner_internal { + +struct FormWindowData; +class FormWindowBase; + +/* Dialog to edit the settings of a QDesignerFormWindowInterface. + * It sets the dirty flag on the form window if something was changed. */ + +class FormWindowSettings: public QDialog +{ + Q_DISABLE_COPY(FormWindowSettings) + Q_OBJECT +public: + explicit FormWindowSettings(QDesignerFormWindowInterface *formWindow); + virtual ~FormWindowSettings(); + + virtual void accept(); + +private: + FormWindowData data() const; + void setData(const FormWindowData&); + + Ui::FormWindowSettings *m_ui; + FormWindowBase *m_formWindow; + FormWindowData *m_oldData; +}; +} + +QT_END_NAMESPACE + +#endif // FORMWINDOWSETTINGS_H diff --git a/tools/designer/src/components/formeditor/formwindowsettings.ui b/tools/designer/src/components/formeditor/formwindowsettings.ui new file mode 100644 index 0000000..4e56365 --- /dev/null +++ b/tools/designer/src/components/formeditor/formwindowsettings.ui @@ -0,0 +1,328 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <comment>********************************************************************* +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +*********************************************************************</comment> + <class>FormWindowSettings</class> + <widget class="QDialog" name="FormWindowSettings"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>470</width> + <height>466</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form Settings</string> + </property> + <layout class="QGridLayout"> + <item row="3" column="0" colspan="2"> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QGroupBox" name="layoutDefaultGroupBox"> + <property name="title"> + <string>Layout &Default</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <layout class="QGridLayout"> + <property name="margin"> + <number>8</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>&Spacing:</string> + </property> + <property name="buddy"> + <cstring>defaultSpacingSpinBox</cstring> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>&Margin:</string> + </property> + <property name="buddy"> + <cstring>defaultMarginSpinBox</cstring> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="defaultSpacingSpinBox"/> + </item> + <item row="0" column="1"> + <widget class="QSpinBox" name="defaultMarginSpinBox"/> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="layoutFunctionGroupBox"> + <property name="title"> + <string>&Layout Function</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <layout class="QGridLayout"> + <property name="margin"> + <number>8</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <item row="1" column="1"> + <widget class="QLineEdit" name="spacingFunctionLineEdit"/> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="marginFunctionLineEdit"/> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Ma&rgin:</string> + </property> + <property name="buddy"> + <cstring>marginFunctionLineEdit</cstring> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_3_2"> + <property name="text"> + <string>Spa&cing:</string> + </property> + <property name="buddy"> + <cstring>spacingFunctionLineEdit</cstring> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + <item row="4" column="1"> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QGroupBox" name="pixmapFunctionGroupBox"> + <property name="title"> + <string>&Pixmap Function</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>8</number> + </property> + <item> + <widget class="QLineEdit" name="pixmapFunctionLineEdit"/> + </item> + </layout> + </widget> + </item> + </layout> + </item> + <item row="5" column="1"> + <spacer> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>111</width> + <height>115</height> + </size> + </property> + </spacer> + </item> + <item row="7" column="0" colspan="2"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + <item row="6" column="0" colspan="2"> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="4" column="0" rowspan="2"> + <widget class="QGroupBox" name="includeHintsGroupBox"> + <property name="title"> + <string>&Include Hints</string> + </property> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>8</number> + </property> + <item> + <widget class="QTextEdit" name="includeHintsTextEdit"/> + </item> + </layout> + </widget> + </item> + <item row="2" column="0" colspan="2"> + <widget class="qdesigner_internal::GridPanel" name="gridPanel"> + <property name="title"> + <string>Grid</string> + </property> + </widget> + </item> + <item row="0" column="0" colspan="2"> + <widget class="QGroupBox" name="embeddedGroupBox"> + <property name="title"> + <string>Embedded Design</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="deviceProfileLabel"> + <property name="text"> + <string notr="true">TextLabel</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="1" column="0" colspan="2"> + <widget class="QGroupBox" name="pixmapFunctionGroupBox_2"> + <property name="title"> + <string>&Author</string> + </property> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>8</number> + </property> + <item> + <widget class="QLineEdit" name="authorLineEdit"/> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>qdesigner_internal::GridPanel</class> + <extends>QGroupBox</extends> + <header location="global">gridpanel_p.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <tabstops> + <tabstop>authorLineEdit</tabstop> + <tabstop>defaultMarginSpinBox</tabstop> + <tabstop>defaultSpacingSpinBox</tabstop> + <tabstop>marginFunctionLineEdit</tabstop> + <tabstop>spacingFunctionLineEdit</tabstop> + <tabstop>pixmapFunctionLineEdit</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>FormWindowSettings</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>294</x> + <y>442</y> + </hint> + <hint type="destinationlabel"> + <x>150</x> + <y>459</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>FormWindowSettings</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>373</x> + <y>444</y> + </hint> + <hint type="destinationlabel"> + <x>357</x> + <y>461</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/tools/designer/src/components/formeditor/iconcache.cpp b/tools/designer/src/components/formeditor/iconcache.cpp new file mode 100644 index 0000000..a256bf8 --- /dev/null +++ b/tools/designer/src/components/formeditor/iconcache.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "iconcache.h" +#include <QtGui/QPixmap> +#include <QtGui/QIcon> +#include <QtCore/QDebug> + +QT_BEGIN_NAMESPACE + +using namespace qdesigner_internal; + +IconCache::IconCache(QObject *parent) + : QDesignerIconCacheInterface(parent) +{ +} + +QIcon IconCache::nameToIcon(const QString &path, const QString &resourcePath) +{ + Q_UNUSED(path) + Q_UNUSED(resourcePath) + qWarning() << "IconCache::nameToIcon(): IconCache is obsoleted"; + return QIcon(); +} + +QString IconCache::iconToFilePath(const QIcon &pm) const +{ + Q_UNUSED(pm) + qWarning() << "IconCache::iconToFilePath(): IconCache is obsoleted"; + return QString(); +} + +QString IconCache::iconToQrcPath(const QIcon &pm) const +{ + Q_UNUSED(pm) + qWarning() << "IconCache::iconToQrcPath(): IconCache is obsoleted"; + return QString(); +} + +QPixmap IconCache::nameToPixmap(const QString &path, const QString &resourcePath) +{ + Q_UNUSED(path) + Q_UNUSED(resourcePath) + qWarning() << "IconCache::nameToPixmap(): IconCache is obsoleted"; + return QPixmap(); +} + +QString IconCache::pixmapToFilePath(const QPixmap &pm) const +{ + Q_UNUSED(pm) + qWarning() << "IconCache::pixmapToFilePath(): IconCache is obsoleted"; + return QString(); +} + +QString IconCache::pixmapToQrcPath(const QPixmap &pm) const +{ + Q_UNUSED(pm) + qWarning() << "IconCache::pixmapToQrcPath(): IconCache is obsoleted"; + return QString(); +} + +QList<QPixmap> IconCache::pixmapList() const +{ + qWarning() << "IconCache::pixmapList(): IconCache is obsoleted"; + return QList<QPixmap>(); +} + +QList<QIcon> IconCache::iconList() const +{ + qWarning() << "IconCache::iconList(): IconCache is obsoleted"; + return QList<QIcon>(); +} + +QString IconCache::resolveQrcPath(const QString &filePath, const QString &qrcPath, const QString &wd) const +{ + Q_UNUSED(filePath) + Q_UNUSED(qrcPath) + Q_UNUSED(wd) + qWarning() << "IconCache::resolveQrcPath(): IconCache is obsoleted"; + return QString(); +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/iconcache.h b/tools/designer/src/components/formeditor/iconcache.h new file mode 100644 index 0000000..24d36e2 --- /dev/null +++ b/tools/designer/src/components/formeditor/iconcache.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ICONCACHE_H +#define ICONCACHE_H + +#include "formeditor_global.h" + +#include <QtDesigner/QDesignerIconCacheInterface> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +class QT_FORMEDITOR_EXPORT IconCache : public QDesignerIconCacheInterface +{ + Q_OBJECT +public: + explicit IconCache(QObject *parent); + + virtual QIcon nameToIcon(const QString &path, const QString &resourcePath = QString()); + virtual QString iconToFilePath(const QIcon &pm) const; + virtual QString iconToQrcPath(const QIcon &pm) const; + virtual QPixmap nameToPixmap(const QString &path, const QString &resourcePath = QString()); + virtual QString pixmapToFilePath(const QPixmap &pm) const; + virtual QString pixmapToQrcPath(const QPixmap &pm) const; + + virtual QList<QPixmap> pixmapList() const; + virtual QList<QIcon> iconList() const; + + virtual QString resolveQrcPath(const QString &filePath, const QString &qrcPath, const QString &workingDirectory = QString()) const; + +private: +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // ICONCACHE_H diff --git a/tools/designer/src/components/formeditor/images/color.png b/tools/designer/src/components/formeditor/images/color.png Binary files differnew file mode 100644 index 0000000..54b7ebc --- /dev/null +++ b/tools/designer/src/components/formeditor/images/color.png diff --git a/tools/designer/src/components/formeditor/images/configure.png b/tools/designer/src/components/formeditor/images/configure.png Binary files differnew file mode 100644 index 0000000..d9f2fd8 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/configure.png diff --git a/tools/designer/src/components/formeditor/images/cursors/arrow.png b/tools/designer/src/components/formeditor/images/cursors/arrow.png Binary files differnew file mode 100644 index 0000000..a69ef4e --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/arrow.png diff --git a/tools/designer/src/components/formeditor/images/cursors/busy.png b/tools/designer/src/components/formeditor/images/cursors/busy.png Binary files differnew file mode 100644 index 0000000..53717e4 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/busy.png diff --git a/tools/designer/src/components/formeditor/images/cursors/closedhand.png b/tools/designer/src/components/formeditor/images/cursors/closedhand.png Binary files differnew file mode 100644 index 0000000..b78dd1d --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/closedhand.png diff --git a/tools/designer/src/components/formeditor/images/cursors/cross.png b/tools/designer/src/components/formeditor/images/cursors/cross.png Binary files differnew file mode 100644 index 0000000..fe38e74 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/cross.png diff --git a/tools/designer/src/components/formeditor/images/cursors/hand.png b/tools/designer/src/components/formeditor/images/cursors/hand.png Binary files differnew file mode 100644 index 0000000..d2004ae --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/hand.png diff --git a/tools/designer/src/components/formeditor/images/cursors/hsplit.png b/tools/designer/src/components/formeditor/images/cursors/hsplit.png Binary files differnew file mode 100644 index 0000000..a5667e3 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/hsplit.png diff --git a/tools/designer/src/components/formeditor/images/cursors/ibeam.png b/tools/designer/src/components/formeditor/images/cursors/ibeam.png Binary files differnew file mode 100644 index 0000000..097fc5f --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/ibeam.png diff --git a/tools/designer/src/components/formeditor/images/cursors/no.png b/tools/designer/src/components/formeditor/images/cursors/no.png Binary files differnew file mode 100644 index 0000000..2b08c4e --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/no.png diff --git a/tools/designer/src/components/formeditor/images/cursors/openhand.png b/tools/designer/src/components/formeditor/images/cursors/openhand.png Binary files differnew file mode 100644 index 0000000..9181c85 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/openhand.png diff --git a/tools/designer/src/components/formeditor/images/cursors/sizeall.png b/tools/designer/src/components/formeditor/images/cursors/sizeall.png Binary files differnew file mode 100644 index 0000000..69f13eb --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/sizeall.png diff --git a/tools/designer/src/components/formeditor/images/cursors/sizeb.png b/tools/designer/src/components/formeditor/images/cursors/sizeb.png Binary files differnew file mode 100644 index 0000000..3b127a0 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/sizeb.png diff --git a/tools/designer/src/components/formeditor/images/cursors/sizef.png b/tools/designer/src/components/formeditor/images/cursors/sizef.png Binary files differnew file mode 100644 index 0000000..f37d7b9 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/sizef.png diff --git a/tools/designer/src/components/formeditor/images/cursors/sizeh.png b/tools/designer/src/components/formeditor/images/cursors/sizeh.png Binary files differnew file mode 100644 index 0000000..a9f40cb --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/sizeh.png diff --git a/tools/designer/src/components/formeditor/images/cursors/sizev.png b/tools/designer/src/components/formeditor/images/cursors/sizev.png Binary files differnew file mode 100644 index 0000000..1edbab2 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/sizev.png diff --git a/tools/designer/src/components/formeditor/images/cursors/uparrow.png b/tools/designer/src/components/formeditor/images/cursors/uparrow.png Binary files differnew file mode 100644 index 0000000..d3e70ef --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/uparrow.png diff --git a/tools/designer/src/components/formeditor/images/cursors/vsplit.png b/tools/designer/src/components/formeditor/images/cursors/vsplit.png Binary files differnew file mode 100644 index 0000000..1beda25 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/vsplit.png diff --git a/tools/designer/src/components/formeditor/images/cursors/wait.png b/tools/designer/src/components/formeditor/images/cursors/wait.png Binary files differnew file mode 100644 index 0000000..69056c4 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/wait.png diff --git a/tools/designer/src/components/formeditor/images/cursors/whatsthis.png b/tools/designer/src/components/formeditor/images/cursors/whatsthis.png Binary files differnew file mode 100644 index 0000000..b47601c --- /dev/null +++ b/tools/designer/src/components/formeditor/images/cursors/whatsthis.png diff --git a/tools/designer/src/components/formeditor/images/downplus.png b/tools/designer/src/components/formeditor/images/downplus.png Binary files differnew file mode 100644 index 0000000..1e384a7 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/downplus.png diff --git a/tools/designer/src/components/formeditor/images/dropdownbutton.png b/tools/designer/src/components/formeditor/images/dropdownbutton.png Binary files differnew file mode 100644 index 0000000..5dd9649 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/dropdownbutton.png diff --git a/tools/designer/src/components/formeditor/images/edit.png b/tools/designer/src/components/formeditor/images/edit.png Binary files differnew file mode 100644 index 0000000..a5e49ad --- /dev/null +++ b/tools/designer/src/components/formeditor/images/edit.png diff --git a/tools/designer/src/components/formeditor/images/editdelete-16.png b/tools/designer/src/components/formeditor/images/editdelete-16.png Binary files differnew file mode 100644 index 0000000..ef5c799 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/editdelete-16.png diff --git a/tools/designer/src/components/formeditor/images/emptyicon.png b/tools/designer/src/components/formeditor/images/emptyicon.png Binary files differnew file mode 100644 index 0000000..897220e --- /dev/null +++ b/tools/designer/src/components/formeditor/images/emptyicon.png diff --git a/tools/designer/src/components/formeditor/images/filenew-16.png b/tools/designer/src/components/formeditor/images/filenew-16.png Binary files differnew file mode 100644 index 0000000..eefb3c5 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/filenew-16.png diff --git a/tools/designer/src/components/formeditor/images/fileopen-16.png b/tools/designer/src/components/formeditor/images/fileopen-16.png Binary files differnew file mode 100644 index 0000000..d832c62 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/fileopen-16.png diff --git a/tools/designer/src/components/formeditor/images/leveldown.png b/tools/designer/src/components/formeditor/images/leveldown.png Binary files differnew file mode 100644 index 0000000..742b7fb --- /dev/null +++ b/tools/designer/src/components/formeditor/images/leveldown.png diff --git a/tools/designer/src/components/formeditor/images/levelup.png b/tools/designer/src/components/formeditor/images/levelup.png Binary files differnew file mode 100644 index 0000000..48b3e89 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/levelup.png diff --git a/tools/designer/src/components/formeditor/images/mac/adjustsize.png b/tools/designer/src/components/formeditor/images/mac/adjustsize.png Binary files differnew file mode 100644 index 0000000..c4d884c --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/adjustsize.png diff --git a/tools/designer/src/components/formeditor/images/mac/back.png b/tools/designer/src/components/formeditor/images/mac/back.png Binary files differnew file mode 100644 index 0000000..e58177f --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/back.png diff --git a/tools/designer/src/components/formeditor/images/mac/buddytool.png b/tools/designer/src/components/formeditor/images/mac/buddytool.png Binary files differnew file mode 100644 index 0000000..2a42870 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/buddytool.png diff --git a/tools/designer/src/components/formeditor/images/mac/down.png b/tools/designer/src/components/formeditor/images/mac/down.png Binary files differnew file mode 100644 index 0000000..29d1d44 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/down.png diff --git a/tools/designer/src/components/formeditor/images/mac/editbreaklayout.png b/tools/designer/src/components/formeditor/images/mac/editbreaklayout.png Binary files differnew file mode 100644 index 0000000..dc00559 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/editbreaklayout.png diff --git a/tools/designer/src/components/formeditor/images/mac/editcopy.png b/tools/designer/src/components/formeditor/images/mac/editcopy.png Binary files differnew file mode 100644 index 0000000..f551364 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/editcopy.png diff --git a/tools/designer/src/components/formeditor/images/mac/editcut.png b/tools/designer/src/components/formeditor/images/mac/editcut.png Binary files differnew file mode 100644 index 0000000..a784fd5 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/editcut.png diff --git a/tools/designer/src/components/formeditor/images/mac/editdelete.png b/tools/designer/src/components/formeditor/images/mac/editdelete.png Binary files differnew file mode 100644 index 0000000..201b31c --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/editdelete.png diff --git a/tools/designer/src/components/formeditor/images/mac/editform.png b/tools/designer/src/components/formeditor/images/mac/editform.png Binary files differnew file mode 100644 index 0000000..4fc2e40 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/editform.png diff --git a/tools/designer/src/components/formeditor/images/mac/editgrid.png b/tools/designer/src/components/formeditor/images/mac/editgrid.png Binary files differnew file mode 100644 index 0000000..bba4a69 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/editgrid.png diff --git a/tools/designer/src/components/formeditor/images/mac/edithlayout.png b/tools/designer/src/components/formeditor/images/mac/edithlayout.png Binary files differnew file mode 100644 index 0000000..ec880bb --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/edithlayout.png diff --git a/tools/designer/src/components/formeditor/images/mac/edithlayoutsplit.png b/tools/designer/src/components/formeditor/images/mac/edithlayoutsplit.png Binary files differnew file mode 100644 index 0000000..227d011 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/edithlayoutsplit.png diff --git a/tools/designer/src/components/formeditor/images/mac/editlower.png b/tools/designer/src/components/formeditor/images/mac/editlower.png Binary files differnew file mode 100644 index 0000000..347806f --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/editlower.png diff --git a/tools/designer/src/components/formeditor/images/mac/editpaste.png b/tools/designer/src/components/formeditor/images/mac/editpaste.png Binary files differnew file mode 100644 index 0000000..64c0b2d --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/editpaste.png diff --git a/tools/designer/src/components/formeditor/images/mac/editraise.png b/tools/designer/src/components/formeditor/images/mac/editraise.png Binary files differnew file mode 100644 index 0000000..09cbbd7 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/editraise.png diff --git a/tools/designer/src/components/formeditor/images/mac/editvlayout.png b/tools/designer/src/components/formeditor/images/mac/editvlayout.png Binary files differnew file mode 100644 index 0000000..63b26cd --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/editvlayout.png diff --git a/tools/designer/src/components/formeditor/images/mac/editvlayoutsplit.png b/tools/designer/src/components/formeditor/images/mac/editvlayoutsplit.png Binary files differnew file mode 100644 index 0000000..5a02c94 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/editvlayoutsplit.png diff --git a/tools/designer/src/components/formeditor/images/mac/filenew.png b/tools/designer/src/components/formeditor/images/mac/filenew.png Binary files differnew file mode 100644 index 0000000..9dcba42 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/filenew.png diff --git a/tools/designer/src/components/formeditor/images/mac/fileopen.png b/tools/designer/src/components/formeditor/images/mac/fileopen.png Binary files differnew file mode 100644 index 0000000..c12bcd5 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/fileopen.png diff --git a/tools/designer/src/components/formeditor/images/mac/filesave.png b/tools/designer/src/components/formeditor/images/mac/filesave.png Binary files differnew file mode 100644 index 0000000..b41ecf5 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/filesave.png diff --git a/tools/designer/src/components/formeditor/images/mac/forward.png b/tools/designer/src/components/formeditor/images/mac/forward.png Binary files differnew file mode 100644 index 0000000..34b91f0 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/forward.png diff --git a/tools/designer/src/components/formeditor/images/mac/insertimage.png b/tools/designer/src/components/formeditor/images/mac/insertimage.png Binary files differnew file mode 100644 index 0000000..b8673e1 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/insertimage.png diff --git a/tools/designer/src/components/formeditor/images/mac/minus.png b/tools/designer/src/components/formeditor/images/mac/minus.png Binary files differnew file mode 100644 index 0000000..8d2eaed --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/minus.png diff --git a/tools/designer/src/components/formeditor/images/mac/plus.png b/tools/designer/src/components/formeditor/images/mac/plus.png Binary files differnew file mode 100644 index 0000000..1ee4542 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/plus.png diff --git a/tools/designer/src/components/formeditor/images/mac/redo.png b/tools/designer/src/components/formeditor/images/mac/redo.png Binary files differnew file mode 100644 index 0000000..8875bf2 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/redo.png diff --git a/tools/designer/src/components/formeditor/images/mac/resetproperty.png b/tools/designer/src/components/formeditor/images/mac/resetproperty.png Binary files differnew file mode 100644 index 0000000..9048252 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/resetproperty.png diff --git a/tools/designer/src/components/formeditor/images/mac/resourceeditortool.png b/tools/designer/src/components/formeditor/images/mac/resourceeditortool.png Binary files differnew file mode 100644 index 0000000..7ef511c --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/resourceeditortool.png diff --git a/tools/designer/src/components/formeditor/images/mac/signalslottool.png b/tools/designer/src/components/formeditor/images/mac/signalslottool.png Binary files differnew file mode 100644 index 0000000..71c9b07 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/signalslottool.png diff --git a/tools/designer/src/components/formeditor/images/mac/tabordertool.png b/tools/designer/src/components/formeditor/images/mac/tabordertool.png Binary files differnew file mode 100644 index 0000000..f54faf9 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/tabordertool.png diff --git a/tools/designer/src/components/formeditor/images/mac/textanchor.png b/tools/designer/src/components/formeditor/images/mac/textanchor.png Binary files differnew file mode 100644 index 0000000..baa9dda --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/textanchor.png diff --git a/tools/designer/src/components/formeditor/images/mac/textbold.png b/tools/designer/src/components/formeditor/images/mac/textbold.png Binary files differnew file mode 100644 index 0000000..38400bd --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/textbold.png diff --git a/tools/designer/src/components/formeditor/images/mac/textcenter.png b/tools/designer/src/components/formeditor/images/mac/textcenter.png Binary files differnew file mode 100644 index 0000000..2ef5b2e --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/textcenter.png diff --git a/tools/designer/src/components/formeditor/images/mac/textitalic.png b/tools/designer/src/components/formeditor/images/mac/textitalic.png Binary files differnew file mode 100644 index 0000000..0170ee2 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/textitalic.png diff --git a/tools/designer/src/components/formeditor/images/mac/textjustify.png b/tools/designer/src/components/formeditor/images/mac/textjustify.png Binary files differnew file mode 100644 index 0000000..39cd6c1 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/textjustify.png diff --git a/tools/designer/src/components/formeditor/images/mac/textleft.png b/tools/designer/src/components/formeditor/images/mac/textleft.png Binary files differnew file mode 100644 index 0000000..83a66d5 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/textleft.png diff --git a/tools/designer/src/components/formeditor/images/mac/textright.png b/tools/designer/src/components/formeditor/images/mac/textright.png Binary files differnew file mode 100644 index 0000000..e7c0464 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/textright.png diff --git a/tools/designer/src/components/formeditor/images/mac/textsubscript.png b/tools/designer/src/components/formeditor/images/mac/textsubscript.png Binary files differnew file mode 100644 index 0000000..ff431f3 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/textsubscript.png diff --git a/tools/designer/src/components/formeditor/images/mac/textsuperscript.png b/tools/designer/src/components/formeditor/images/mac/textsuperscript.png Binary files differnew file mode 100644 index 0000000..cb67a33 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/textsuperscript.png diff --git a/tools/designer/src/components/formeditor/images/mac/textunder.png b/tools/designer/src/components/formeditor/images/mac/textunder.png Binary files differnew file mode 100644 index 0000000..968bac5 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/textunder.png diff --git a/tools/designer/src/components/formeditor/images/mac/undo.png b/tools/designer/src/components/formeditor/images/mac/undo.png Binary files differnew file mode 100644 index 0000000..a3bd5e0 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/undo.png diff --git a/tools/designer/src/components/formeditor/images/mac/up.png b/tools/designer/src/components/formeditor/images/mac/up.png Binary files differnew file mode 100644 index 0000000..e437312 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/up.png diff --git a/tools/designer/src/components/formeditor/images/mac/widgettool.png b/tools/designer/src/components/formeditor/images/mac/widgettool.png Binary files differnew file mode 100644 index 0000000..e1aa353 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/mac/widgettool.png diff --git a/tools/designer/src/components/formeditor/images/minus-16.png b/tools/designer/src/components/formeditor/images/minus-16.png Binary files differnew file mode 100644 index 0000000..745b445 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/minus-16.png diff --git a/tools/designer/src/components/formeditor/images/plus-16.png b/tools/designer/src/components/formeditor/images/plus-16.png Binary files differnew file mode 100644 index 0000000..ef43788 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/plus-16.png diff --git a/tools/designer/src/components/formeditor/images/prefix-add.png b/tools/designer/src/components/formeditor/images/prefix-add.png Binary files differnew file mode 100644 index 0000000..cfbb053 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/prefix-add.png diff --git a/tools/designer/src/components/formeditor/images/qt3logo.png b/tools/designer/src/components/formeditor/images/qt3logo.png Binary files differnew file mode 100644 index 0000000..7202850 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/qt3logo.png diff --git a/tools/designer/src/components/formeditor/images/qtlogo.png b/tools/designer/src/components/formeditor/images/qtlogo.png Binary files differnew file mode 100644 index 0000000..038fa2c --- /dev/null +++ b/tools/designer/src/components/formeditor/images/qtlogo.png diff --git a/tools/designer/src/components/formeditor/images/reload.png b/tools/designer/src/components/formeditor/images/reload.png Binary files differnew file mode 100644 index 0000000..18c752e --- /dev/null +++ b/tools/designer/src/components/formeditor/images/reload.png diff --git a/tools/designer/src/components/formeditor/images/resetproperty.png b/tools/designer/src/components/formeditor/images/resetproperty.png Binary files differnew file mode 100644 index 0000000..9048252 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/resetproperty.png diff --git a/tools/designer/src/components/formeditor/images/sort.png b/tools/designer/src/components/formeditor/images/sort.png Binary files differnew file mode 100644 index 0000000..883bfa9 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/sort.png diff --git a/tools/designer/src/components/formeditor/images/submenu.png b/tools/designer/src/components/formeditor/images/submenu.png Binary files differnew file mode 100644 index 0000000..3deb28e --- /dev/null +++ b/tools/designer/src/components/formeditor/images/submenu.png diff --git a/tools/designer/src/components/formeditor/images/widgets/calendarwidget.png b/tools/designer/src/components/formeditor/images/widgets/calendarwidget.png Binary files differnew file mode 100644 index 0000000..26737b8 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/calendarwidget.png diff --git a/tools/designer/src/components/formeditor/images/widgets/checkbox.png b/tools/designer/src/components/formeditor/images/widgets/checkbox.png Binary files differnew file mode 100644 index 0000000..ab6f53e --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/checkbox.png diff --git a/tools/designer/src/components/formeditor/images/widgets/columnview.png b/tools/designer/src/components/formeditor/images/widgets/columnview.png Binary files differnew file mode 100644 index 0000000..4132ee6 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/columnview.png diff --git a/tools/designer/src/components/formeditor/images/widgets/combobox.png b/tools/designer/src/components/formeditor/images/widgets/combobox.png Binary files differnew file mode 100644 index 0000000..bf3ed79 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/combobox.png diff --git a/tools/designer/src/components/formeditor/images/widgets/commandlinkbutton.png b/tools/designer/src/components/formeditor/images/widgets/commandlinkbutton.png Binary files differnew file mode 100644 index 0000000..6bbd84a --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/commandlinkbutton.png diff --git a/tools/designer/src/components/formeditor/images/widgets/dateedit.png b/tools/designer/src/components/formeditor/images/widgets/dateedit.png Binary files differnew file mode 100644 index 0000000..6827fa7 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/dateedit.png diff --git a/tools/designer/src/components/formeditor/images/widgets/datetimeedit.png b/tools/designer/src/components/formeditor/images/widgets/datetimeedit.png Binary files differnew file mode 100644 index 0000000..7d8e6fe --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/datetimeedit.png diff --git a/tools/designer/src/components/formeditor/images/widgets/dial.png b/tools/designer/src/components/formeditor/images/widgets/dial.png Binary files differnew file mode 100644 index 0000000..050d1db --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/dial.png diff --git a/tools/designer/src/components/formeditor/images/widgets/dialogbuttonbox.png b/tools/designer/src/components/formeditor/images/widgets/dialogbuttonbox.png Binary files differnew file mode 100644 index 0000000..b1f89fb --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/dialogbuttonbox.png diff --git a/tools/designer/src/components/formeditor/images/widgets/dockwidget.png b/tools/designer/src/components/formeditor/images/widgets/dockwidget.png Binary files differnew file mode 100644 index 0000000..9eee04f --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/dockwidget.png diff --git a/tools/designer/src/components/formeditor/images/widgets/doublespinbox.png b/tools/designer/src/components/formeditor/images/widgets/doublespinbox.png Binary files differnew file mode 100644 index 0000000..5686ac8 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/doublespinbox.png diff --git a/tools/designer/src/components/formeditor/images/widgets/fontcombobox.png b/tools/designer/src/components/formeditor/images/widgets/fontcombobox.png Binary files differnew file mode 100644 index 0000000..6848f15 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/fontcombobox.png diff --git a/tools/designer/src/components/formeditor/images/widgets/frame.png b/tools/designer/src/components/formeditor/images/widgets/frame.png Binary files differnew file mode 100644 index 0000000..68f5da0 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/frame.png diff --git a/tools/designer/src/components/formeditor/images/widgets/graphicsview.png b/tools/designer/src/components/formeditor/images/widgets/graphicsview.png Binary files differnew file mode 100644 index 0000000..93fe760 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/graphicsview.png diff --git a/tools/designer/src/components/formeditor/images/widgets/groupbox.png b/tools/designer/src/components/formeditor/images/widgets/groupbox.png Binary files differnew file mode 100644 index 0000000..4025b4d --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/groupbox.png diff --git a/tools/designer/src/components/formeditor/images/widgets/groupboxcollapsible.png b/tools/designer/src/components/formeditor/images/widgets/groupboxcollapsible.png Binary files differnew file mode 100644 index 0000000..62fd1ad --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/groupboxcollapsible.png diff --git a/tools/designer/src/components/formeditor/images/widgets/hscrollbar.png b/tools/designer/src/components/formeditor/images/widgets/hscrollbar.png Binary files differnew file mode 100644 index 0000000..466c58d --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/hscrollbar.png diff --git a/tools/designer/src/components/formeditor/images/widgets/hslider.png b/tools/designer/src/components/formeditor/images/widgets/hslider.png Binary files differnew file mode 100644 index 0000000..525bd1c --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/hslider.png diff --git a/tools/designer/src/components/formeditor/images/widgets/hsplit.png b/tools/designer/src/components/formeditor/images/widgets/hsplit.png Binary files differnew file mode 100644 index 0000000..1ea8f2a --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/hsplit.png diff --git a/tools/designer/src/components/formeditor/images/widgets/label.png b/tools/designer/src/components/formeditor/images/widgets/label.png Binary files differnew file mode 100644 index 0000000..5d7d7b4 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/label.png diff --git a/tools/designer/src/components/formeditor/images/widgets/lcdnumber.png b/tools/designer/src/components/formeditor/images/widgets/lcdnumber.png Binary files differnew file mode 100644 index 0000000..c3cac18 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/lcdnumber.png diff --git a/tools/designer/src/components/formeditor/images/widgets/line.png b/tools/designer/src/components/formeditor/images/widgets/line.png Binary files differnew file mode 100644 index 0000000..5c64dfb --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/line.png diff --git a/tools/designer/src/components/formeditor/images/widgets/lineedit.png b/tools/designer/src/components/formeditor/images/widgets/lineedit.png Binary files differnew file mode 100644 index 0000000..75fc890 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/lineedit.png diff --git a/tools/designer/src/components/formeditor/images/widgets/listbox.png b/tools/designer/src/components/formeditor/images/widgets/listbox.png Binary files differnew file mode 100644 index 0000000..367e67f --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/listbox.png diff --git a/tools/designer/src/components/formeditor/images/widgets/listview.png b/tools/designer/src/components/formeditor/images/widgets/listview.png Binary files differnew file mode 100644 index 0000000..d1308d5 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/listview.png diff --git a/tools/designer/src/components/formeditor/images/widgets/mdiarea.png b/tools/designer/src/components/formeditor/images/widgets/mdiarea.png Binary files differnew file mode 100644 index 0000000..7783dd5 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/mdiarea.png diff --git a/tools/designer/src/components/formeditor/images/widgets/plaintextedit.png b/tools/designer/src/components/formeditor/images/widgets/plaintextedit.png Binary files differnew file mode 100644 index 0000000..077bf16 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/plaintextedit.png diff --git a/tools/designer/src/components/formeditor/images/widgets/progress.png b/tools/designer/src/components/formeditor/images/widgets/progress.png Binary files differnew file mode 100644 index 0000000..44ae094 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/progress.png diff --git a/tools/designer/src/components/formeditor/images/widgets/pushbutton.png b/tools/designer/src/components/formeditor/images/widgets/pushbutton.png Binary files differnew file mode 100644 index 0000000..61f779c --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/pushbutton.png diff --git a/tools/designer/src/components/formeditor/images/widgets/radiobutton.png b/tools/designer/src/components/formeditor/images/widgets/radiobutton.png Binary files differnew file mode 100644 index 0000000..10c1d8c --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/radiobutton.png diff --git a/tools/designer/src/components/formeditor/images/widgets/scrollarea.png b/tools/designer/src/components/formeditor/images/widgets/scrollarea.png Binary files differnew file mode 100644 index 0000000..651ea24 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/scrollarea.png diff --git a/tools/designer/src/components/formeditor/images/widgets/spacer.png b/tools/designer/src/components/formeditor/images/widgets/spacer.png Binary files differnew file mode 100644 index 0000000..8a0931b --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/spacer.png diff --git a/tools/designer/src/components/formeditor/images/widgets/spinbox.png b/tools/designer/src/components/formeditor/images/widgets/spinbox.png Binary files differnew file mode 100644 index 0000000..cdd9fe1 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/spinbox.png diff --git a/tools/designer/src/components/formeditor/images/widgets/tabbar.png b/tools/designer/src/components/formeditor/images/widgets/tabbar.png Binary files differnew file mode 100644 index 0000000..d5d3783 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/tabbar.png diff --git a/tools/designer/src/components/formeditor/images/widgets/table.png b/tools/designer/src/components/formeditor/images/widgets/table.png Binary files differnew file mode 100644 index 0000000..4bbd9c2 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/table.png diff --git a/tools/designer/src/components/formeditor/images/widgets/tabwidget.png b/tools/designer/src/components/formeditor/images/widgets/tabwidget.png Binary files differnew file mode 100644 index 0000000..1254bb6 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/tabwidget.png diff --git a/tools/designer/src/components/formeditor/images/widgets/textedit.png b/tools/designer/src/components/formeditor/images/widgets/textedit.png Binary files differnew file mode 100644 index 0000000..32e897d --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/textedit.png diff --git a/tools/designer/src/components/formeditor/images/widgets/timeedit.png b/tools/designer/src/components/formeditor/images/widgets/timeedit.png Binary files differnew file mode 100644 index 0000000..c66d91b --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/timeedit.png diff --git a/tools/designer/src/components/formeditor/images/widgets/toolbox.png b/tools/designer/src/components/formeditor/images/widgets/toolbox.png Binary files differnew file mode 100644 index 0000000..2ab71dc --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/toolbox.png diff --git a/tools/designer/src/components/formeditor/images/widgets/toolbutton.png b/tools/designer/src/components/formeditor/images/widgets/toolbutton.png Binary files differnew file mode 100644 index 0000000..0bff069 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/toolbutton.png diff --git a/tools/designer/src/components/formeditor/images/widgets/vline.png b/tools/designer/src/components/formeditor/images/widgets/vline.png Binary files differnew file mode 100644 index 0000000..35a7300 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/vline.png diff --git a/tools/designer/src/components/formeditor/images/widgets/vscrollbar.png b/tools/designer/src/components/formeditor/images/widgets/vscrollbar.png Binary files differnew file mode 100644 index 0000000..28b7c40 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/vscrollbar.png diff --git a/tools/designer/src/components/formeditor/images/widgets/vslider.png b/tools/designer/src/components/formeditor/images/widgets/vslider.png Binary files differnew file mode 100644 index 0000000..59f06ba --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/vslider.png diff --git a/tools/designer/src/components/formeditor/images/widgets/vspacer.png b/tools/designer/src/components/formeditor/images/widgets/vspacer.png Binary files differnew file mode 100644 index 0000000..ce5e8bd --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/vspacer.png diff --git a/tools/designer/src/components/formeditor/images/widgets/widget.png b/tools/designer/src/components/formeditor/images/widgets/widget.png Binary files differnew file mode 100644 index 0000000..1cf960e --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/widget.png diff --git a/tools/designer/src/components/formeditor/images/widgets/widgetstack.png b/tools/designer/src/components/formeditor/images/widgets/widgetstack.png Binary files differnew file mode 100644 index 0000000..2c6964e --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/widgetstack.png diff --git a/tools/designer/src/components/formeditor/images/widgets/wizard.png b/tools/designer/src/components/formeditor/images/widgets/wizard.png Binary files differnew file mode 100644 index 0000000..7c0e107 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/widgets/wizard.png diff --git a/tools/designer/src/components/formeditor/images/win/adjustsize.png b/tools/designer/src/components/formeditor/images/win/adjustsize.png Binary files differnew file mode 100644 index 0000000..3cda333 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/adjustsize.png diff --git a/tools/designer/src/components/formeditor/images/win/back.png b/tools/designer/src/components/formeditor/images/win/back.png Binary files differnew file mode 100644 index 0000000..e58177f --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/back.png diff --git a/tools/designer/src/components/formeditor/images/win/buddytool.png b/tools/designer/src/components/formeditor/images/win/buddytool.png Binary files differnew file mode 100644 index 0000000..4cd968b --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/buddytool.png diff --git a/tools/designer/src/components/formeditor/images/win/down.png b/tools/designer/src/components/formeditor/images/win/down.png Binary files differnew file mode 100644 index 0000000..29d1d44 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/down.png diff --git a/tools/designer/src/components/formeditor/images/win/editbreaklayout.png b/tools/designer/src/components/formeditor/images/win/editbreaklayout.png Binary files differnew file mode 100644 index 0000000..07c5fae --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/editbreaklayout.png diff --git a/tools/designer/src/components/formeditor/images/win/editcopy.png b/tools/designer/src/components/formeditor/images/win/editcopy.png Binary files differnew file mode 100644 index 0000000..1121b47 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/editcopy.png diff --git a/tools/designer/src/components/formeditor/images/win/editcut.png b/tools/designer/src/components/formeditor/images/win/editcut.png Binary files differnew file mode 100644 index 0000000..4b6c82c --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/editcut.png diff --git a/tools/designer/src/components/formeditor/images/win/editdelete.png b/tools/designer/src/components/formeditor/images/win/editdelete.png Binary files differnew file mode 100644 index 0000000..5a42514 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/editdelete.png diff --git a/tools/designer/src/components/formeditor/images/win/editform.png b/tools/designer/src/components/formeditor/images/win/editform.png Binary files differnew file mode 100644 index 0000000..452fcd8 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/editform.png diff --git a/tools/designer/src/components/formeditor/images/win/editgrid.png b/tools/designer/src/components/formeditor/images/win/editgrid.png Binary files differnew file mode 100644 index 0000000..789bf7d --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/editgrid.png diff --git a/tools/designer/src/components/formeditor/images/win/edithlayout.png b/tools/designer/src/components/formeditor/images/win/edithlayout.png Binary files differnew file mode 100644 index 0000000..4dd3f0c --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/edithlayout.png diff --git a/tools/designer/src/components/formeditor/images/win/edithlayoutsplit.png b/tools/designer/src/components/formeditor/images/win/edithlayoutsplit.png Binary files differnew file mode 100644 index 0000000..2dcc690 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/edithlayoutsplit.png diff --git a/tools/designer/src/components/formeditor/images/win/editlower.png b/tools/designer/src/components/formeditor/images/win/editlower.png Binary files differnew file mode 100644 index 0000000..ba63094 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/editlower.png diff --git a/tools/designer/src/components/formeditor/images/win/editpaste.png b/tools/designer/src/components/formeditor/images/win/editpaste.png Binary files differnew file mode 100644 index 0000000..ffab15a --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/editpaste.png diff --git a/tools/designer/src/components/formeditor/images/win/editraise.png b/tools/designer/src/components/formeditor/images/win/editraise.png Binary files differnew file mode 100644 index 0000000..bb8362c --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/editraise.png diff --git a/tools/designer/src/components/formeditor/images/win/editvlayout.png b/tools/designer/src/components/formeditor/images/win/editvlayout.png Binary files differnew file mode 100644 index 0000000..7ad28fd --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/editvlayout.png diff --git a/tools/designer/src/components/formeditor/images/win/editvlayoutsplit.png b/tools/designer/src/components/formeditor/images/win/editvlayoutsplit.png Binary files differnew file mode 100644 index 0000000..720e18b --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/editvlayoutsplit.png diff --git a/tools/designer/src/components/formeditor/images/win/filenew.png b/tools/designer/src/components/formeditor/images/win/filenew.png Binary files differnew file mode 100644 index 0000000..af5d122 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/filenew.png diff --git a/tools/designer/src/components/formeditor/images/win/fileopen.png b/tools/designer/src/components/formeditor/images/win/fileopen.png Binary files differnew file mode 100644 index 0000000..fc6f17e --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/fileopen.png diff --git a/tools/designer/src/components/formeditor/images/win/filesave.png b/tools/designer/src/components/formeditor/images/win/filesave.png Binary files differnew file mode 100644 index 0000000..8feec99 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/filesave.png diff --git a/tools/designer/src/components/formeditor/images/win/forward.png b/tools/designer/src/components/formeditor/images/win/forward.png Binary files differnew file mode 100644 index 0000000..34b91f0 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/forward.png diff --git a/tools/designer/src/components/formeditor/images/win/insertimage.png b/tools/designer/src/components/formeditor/images/win/insertimage.png Binary files differnew file mode 100644 index 0000000..cfab637 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/insertimage.png diff --git a/tools/designer/src/components/formeditor/images/win/minus.png b/tools/designer/src/components/formeditor/images/win/minus.png Binary files differnew file mode 100644 index 0000000..c0dc274 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/minus.png diff --git a/tools/designer/src/components/formeditor/images/win/plus.png b/tools/designer/src/components/formeditor/images/win/plus.png Binary files differnew file mode 100644 index 0000000..ecf0589 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/plus.png diff --git a/tools/designer/src/components/formeditor/images/win/redo.png b/tools/designer/src/components/formeditor/images/win/redo.png Binary files differnew file mode 100644 index 0000000..686ad14 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/redo.png diff --git a/tools/designer/src/components/formeditor/images/win/resourceeditortool.png b/tools/designer/src/components/formeditor/images/win/resourceeditortool.png Binary files differnew file mode 100644 index 0000000..cc9cb58 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/resourceeditortool.png diff --git a/tools/designer/src/components/formeditor/images/win/signalslottool.png b/tools/designer/src/components/formeditor/images/win/signalslottool.png Binary files differnew file mode 100644 index 0000000..e80fd1c --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/signalslottool.png diff --git a/tools/designer/src/components/formeditor/images/win/tabordertool.png b/tools/designer/src/components/formeditor/images/win/tabordertool.png Binary files differnew file mode 100644 index 0000000..7e6e2de --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/tabordertool.png diff --git a/tools/designer/src/components/formeditor/images/win/textanchor.png b/tools/designer/src/components/formeditor/images/win/textanchor.png Binary files differnew file mode 100644 index 0000000..1911ab0 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/textanchor.png diff --git a/tools/designer/src/components/formeditor/images/win/textbold.png b/tools/designer/src/components/formeditor/images/win/textbold.png Binary files differnew file mode 100644 index 0000000..9cbc713 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/textbold.png diff --git a/tools/designer/src/components/formeditor/images/win/textcenter.png b/tools/designer/src/components/formeditor/images/win/textcenter.png Binary files differnew file mode 100644 index 0000000..11efb4b --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/textcenter.png diff --git a/tools/designer/src/components/formeditor/images/win/textitalic.png b/tools/designer/src/components/formeditor/images/win/textitalic.png Binary files differnew file mode 100644 index 0000000..b30ce14 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/textitalic.png diff --git a/tools/designer/src/components/formeditor/images/win/textjustify.png b/tools/designer/src/components/formeditor/images/win/textjustify.png Binary files differnew file mode 100644 index 0000000..9de0c88 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/textjustify.png diff --git a/tools/designer/src/components/formeditor/images/win/textleft.png b/tools/designer/src/components/formeditor/images/win/textleft.png Binary files differnew file mode 100644 index 0000000..16f80bc --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/textleft.png diff --git a/tools/designer/src/components/formeditor/images/win/textright.png b/tools/designer/src/components/formeditor/images/win/textright.png Binary files differnew file mode 100644 index 0000000..16872df --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/textright.png diff --git a/tools/designer/src/components/formeditor/images/win/textsubscript.png b/tools/designer/src/components/formeditor/images/win/textsubscript.png Binary files differnew file mode 100644 index 0000000..d86347d --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/textsubscript.png diff --git a/tools/designer/src/components/formeditor/images/win/textsuperscript.png b/tools/designer/src/components/formeditor/images/win/textsuperscript.png Binary files differnew file mode 100644 index 0000000..9109965 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/textsuperscript.png diff --git a/tools/designer/src/components/formeditor/images/win/textunder.png b/tools/designer/src/components/formeditor/images/win/textunder.png Binary files differnew file mode 100644 index 0000000..c72eff5 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/textunder.png diff --git a/tools/designer/src/components/formeditor/images/win/undo.png b/tools/designer/src/components/formeditor/images/win/undo.png Binary files differnew file mode 100644 index 0000000..c3b8c513 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/undo.png diff --git a/tools/designer/src/components/formeditor/images/win/up.png b/tools/designer/src/components/formeditor/images/win/up.png Binary files differnew file mode 100644 index 0000000..e437312 --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/up.png diff --git a/tools/designer/src/components/formeditor/images/win/widgettool.png b/tools/designer/src/components/formeditor/images/win/widgettool.png Binary files differnew file mode 100644 index 0000000..a52224e --- /dev/null +++ b/tools/designer/src/components/formeditor/images/win/widgettool.png diff --git a/tools/designer/src/components/formeditor/itemview_propertysheet.cpp b/tools/designer/src/components/formeditor/itemview_propertysheet.cpp new file mode 100644 index 0000000..609ce84 --- /dev/null +++ b/tools/designer/src/components/formeditor/itemview_propertysheet.cpp @@ -0,0 +1,291 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "itemview_propertysheet.h" + +#include <QtDesigner/QDesignerFormEditorInterface> + +#include <QtGui/QAbstractItemView> +#include <QtGui/QHeaderView> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +struct Property { + Property() : m_sheet(0),m_id(-1) {} + Property(QDesignerPropertySheetExtension *sheet, int id) + : m_sheet(sheet), m_id(id) {} + bool operator==(const Property &p) { return m_sheet == p.m_sheet && m_id == p.m_id; } + uint qHash() { + return ((int)(m_sheet-(QDesignerPropertySheetExtension*)(0))) & m_id; + } + + QDesignerPropertySheetExtension *m_sheet; + int m_id; +}; + +class ItemViewPropertySheetPrivate { + +public: + ItemViewPropertySheetPrivate(QHeaderView *horizontalHeader, + QHeaderView *verticalHeader, + QObject *parent); + + inline void createMapping(int fakeId, QHeaderView *header, const QString &headerName); + inline QStringList realPropertyNames(); + inline QString fakePropertyName(const QString &prefix, const QString &realName); + + QDesignerFormEditorInterface *m_core; + + // Maps index of fake property + // to index of real property in respective sheet + QHash<int, Property> m_propertyIdMap; + + // Maps name of fake property + // to name of real property + QHash<QString, QString> m_propertyNameMap; + +private: + static QDesignerFormEditorInterface *formEditorForObject(QObject *o); + + QHeaderView *m_hHeader; + QHeaderView *m_vHeader; + QHash<QHeaderView *, QDesignerPropertySheetExtension *> m_propertySheet; + QStringList m_realPropertyNames; +}; + +// Name of the fake group +static const char *headerGroup = "Header"; + +// Name of the real properties +static const char *visibleProperty = "visible"; +static const char *cascadingSectionResizesProperty = "cascadingSectionResizes"; +static const char *defaultSectionSizeProperty = "defaultSectionSize"; +static const char *highlightSectionsProperty = "highlightSections"; +static const char *minimumSectionSizeProperty = "minimumSectionSize"; +static const char *showSortIndicatorProperty = "showSortIndicator"; +static const char *stretchLastSectionProperty = "stretchLastSection"; +} // namespace qdesigner_internal + +using namespace qdesigner_internal; + + +/***************** ItemViewPropertySheetPrivate *********************/ + +ItemViewPropertySheetPrivate::ItemViewPropertySheetPrivate(QHeaderView *horizontalHeader, + QHeaderView *verticalHeader, + QObject *parent) + : m_core(formEditorForObject(parent)), + m_hHeader(horizontalHeader), + m_vHeader(verticalHeader) +{ + if (horizontalHeader) + m_propertySheet.insert(horizontalHeader, + qt_extension<QDesignerPropertySheetExtension*> + (m_core->extensionManager(), horizontalHeader)); + if (verticalHeader) + m_propertySheet.insert(verticalHeader, + qt_extension<QDesignerPropertySheetExtension*> + (m_core->extensionManager(), verticalHeader)); +} + +// Find the form editor in the hierarchy. +// We know that the parent of the sheet is the extension manager +// whose parent is the core. +QDesignerFormEditorInterface *ItemViewPropertySheetPrivate::formEditorForObject(QObject *o) +{ + do { + if (QDesignerFormEditorInterface* core = qobject_cast<QDesignerFormEditorInterface*>(o)) + return core; + o = o->parent(); + } while(o); + Q_ASSERT(o); + return 0; +} + +void ItemViewPropertySheetPrivate::createMapping(int fakeId, QHeaderView *header, + const QString &headerName) +{ + const int realPropertyId = m_propertySheet.value(header)->indexOf(headerName); + QDesignerPropertySheetExtension *propertySheet = m_propertySheet.value(header); + m_propertyIdMap.insert(fakeId, Property(propertySheet, realPropertyId)); +} + +QStringList ItemViewPropertySheetPrivate::realPropertyNames() +{ + if (m_realPropertyNames.isEmpty()) + m_realPropertyNames + << QLatin1String(visibleProperty) + << QLatin1String(cascadingSectionResizesProperty) + << QLatin1String(defaultSectionSizeProperty) + << QLatin1String(highlightSectionsProperty) + << QLatin1String(minimumSectionSizeProperty) + << QLatin1String(showSortIndicatorProperty) + << QLatin1String(stretchLastSectionProperty); + return m_realPropertyNames; +} + +QString ItemViewPropertySheetPrivate::fakePropertyName(const QString &prefix, + const QString &realName) +{ + // prefix = "header", realPropertyName = "isVisible" returns "headerIsVisible" + QString fakeName = prefix + realName.at(0).toUpper() + realName.mid(1); + m_propertyNameMap.insert(fakeName, realName); + return fakeName; +} + +/***************** ItemViewPropertySheet *********************/ + +/*! + \class qdesigner_internal::ItemViewPropertySheet + + \brief + Adds header fake properties to QTreeView and QTableView objects + + QHeaderView objects are currently not shown in the object inspector. + This class adds some fake properties to the property sheet + of QTreeView and QTableView objects that nevertheless allow the manipulation + of the headers attached to the item view object. + + Currently the defaultAlignment property is not shown because the property sheet + would only show integers, instead of the Qt::Alignment enumeration. + + The fake properties here need special handling in QDesignerResource, uiloader and uic. + */ + +ItemViewPropertySheet::ItemViewPropertySheet(QTreeView *treeViewObject, QObject *parent) + : QDesignerPropertySheet(treeViewObject, parent), + d(new ItemViewPropertySheetPrivate(treeViewObject->header(), 0, parent)) +{ + QHeaderView *hHeader = treeViewObject->header(); + + foreach (const QString &realPropertyName, d->realPropertyNames()) { + const QString fakePropertyName + = d->fakePropertyName(QLatin1String("header"), realPropertyName); + d->createMapping(createFakeProperty(fakePropertyName, 0), hHeader, realPropertyName); + } + + foreach (int id, d->m_propertyIdMap.keys()) { + setAttribute(id, true); + setPropertyGroup(id, QLatin1String(headerGroup)); + } +} + + +ItemViewPropertySheet::ItemViewPropertySheet(QTableView *tableViewObject, QObject *parent) + : QDesignerPropertySheet(tableViewObject, parent), + d(new ItemViewPropertySheetPrivate(tableViewObject->horizontalHeader(), + tableViewObject->verticalHeader(), parent)) +{ + QHeaderView *hHeader = tableViewObject->horizontalHeader(); + QHeaderView *vHeader = tableViewObject->verticalHeader(); + + foreach (const QString &realPropertyName, d->realPropertyNames()) { + const QString fakePropertyName + = d->fakePropertyName(QLatin1String("horizontalHeader"), realPropertyName); + d->createMapping(createFakeProperty(fakePropertyName, 0), hHeader, realPropertyName); + } + foreach (const QString &realPropertyName, d->realPropertyNames()) { + const QString fakePropertyName + = d->fakePropertyName(QLatin1String("verticalHeader"), realPropertyName); + d->createMapping(createFakeProperty(fakePropertyName, 0), vHeader, realPropertyName); + } + + foreach (int id, d->m_propertyIdMap.keys()) { + setAttribute(id, true); + setPropertyGroup(id, QLatin1String(headerGroup)); + } +} + +ItemViewPropertySheet::~ItemViewPropertySheet() +{ + delete d; +} + +/*! + Returns the mapping of fake property names to real property names + */ +QHash<QString,QString> ItemViewPropertySheet::propertyNameMap() const +{ + return d->m_propertyNameMap; +} + +QVariant ItemViewPropertySheet::property(int index) const +{ + if (d->m_propertyIdMap.contains(index)) { + Property realProperty = d->m_propertyIdMap.value(index); + return realProperty.m_sheet->property(realProperty.m_id); + } else { + return QDesignerPropertySheet::property(index); + } +} + +void ItemViewPropertySheet::setProperty(int index, const QVariant &value) +{ + if (d->m_propertyIdMap.contains(index)) { + Property realProperty = d->m_propertyIdMap.value(index); + realProperty.m_sheet->setProperty(realProperty.m_id, value); + } else { + QDesignerPropertySheet::setProperty(index, value); + } +} + +void ItemViewPropertySheet::setChanged(int index, bool changed) +{ + if (d->m_propertyIdMap.contains(index)) { + Property realProperty = d->m_propertyIdMap.value(index); + realProperty.m_sheet->setChanged(realProperty.m_id, changed); + } + QDesignerPropertySheet::setChanged(index, changed); +} + +bool ItemViewPropertySheet::reset(int index) +{ + if (d->m_propertyIdMap.contains(index)) { + Property realProperty = d->m_propertyIdMap.value(index); + return realProperty.m_sheet->reset(realProperty.m_id); + } else { + return QDesignerPropertySheet::reset(index); + } +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/itemview_propertysheet.h b/tools/designer/src/components/formeditor/itemview_propertysheet.h new file mode 100644 index 0000000..e4c80dd --- /dev/null +++ b/tools/designer/src/components/formeditor/itemview_propertysheet.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ITEMVIEW_PROPERTYSHEET_H +#define ITEMVIEW_PROPERTYSHEET_H + +#include <qdesigner_propertysheet_p.h> +#include <extensionfactory_p.h> + +#include <QtGui/QTreeView> +#include <QtGui/QTableView> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +class ItemViewPropertySheetPrivate; + +class ItemViewPropertySheet: public QDesignerPropertySheet +{ + Q_OBJECT + Q_INTERFACES(QDesignerPropertySheetExtension) +public: + explicit ItemViewPropertySheet(QTreeView *treeViewObject, QObject *parent = 0); + explicit ItemViewPropertySheet(QTableView *tableViewObject, QObject *parent = 0); + ~ItemViewPropertySheet(); + + QHash<QString,QString> propertyNameMap() const; + + // QDesignerPropertySheet + QVariant property(int index) const; + void setProperty(int index, const QVariant &value); + + void setChanged(int index, bool changed); + + bool reset(int index); + +private: + ItemViewPropertySheetPrivate *d; +}; + +typedef QDesignerPropertySheetFactory<QTreeView, ItemViewPropertySheet> + QTreeViewPropertySheetFactory; +typedef QDesignerPropertySheetFactory<QTableView, ItemViewPropertySheet> + QTableViewPropertySheetFactory; +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // ITEMVIEW_PROPERTYSHEET_H diff --git a/tools/designer/src/components/formeditor/layout_propertysheet.cpp b/tools/designer/src/components/formeditor/layout_propertysheet.cpp new file mode 100644 index 0000000..a304c6a --- /dev/null +++ b/tools/designer/src/components/formeditor/layout_propertysheet.cpp @@ -0,0 +1,546 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "layout_propertysheet.h" + +// sdk +#include <QtDesigner/QExtensionManager> +#include <QtDesigner/QDesignerFormEditorInterface> + +// shared +#include <ui4_p.h> +#include <qlayout_widget_p.h> +#include <formbuilderextra_p.h> + +#include <QtGui/QFormLayout> + +#include <QtCore/QHash> +#include <QtCore/QDebug> +#include <QtCore/QTextStream> +#include <QtCore/QByteArray> +#include <QtCore/QRegExp> // Remove once there is an editor for lists + +QT_BEGIN_NAMESPACE + +#define USE_LAYOUT_SIZE_CONSTRAINT + +static const char *leftMargin = "leftMargin"; +static const char *topMargin = "topMargin"; +static const char *rightMargin = "rightMargin"; +static const char *bottomMargin = "bottomMargin"; +static const char *horizontalSpacing = "horizontalSpacing"; +static const char *verticalSpacing = "verticalSpacing"; +static const char *spacing = "spacing"; +static const char *margin = "margin"; +static const char *sizeConstraint = "sizeConstraint"; +static const char *boxStretchPropertyC = "stretch"; +static const char *gridRowStretchPropertyC = "rowStretch"; +static const char *gridColumnStretchPropertyC = "columnStretch"; +static const char *gridRowMinimumHeightPropertyC = "rowMinimumHeight"; +static const char *gridColumnMinimumWidthPropertyC = "columnMinimumWidth"; + +namespace { + enum LayoutPropertyType { + LayoutPropertyNone, + LayoutPropertyMargin, // Deprecated + LayoutPropertyLeftMargin, + LayoutPropertyTopMargin, + LayoutPropertyRightMargin, + LayoutPropertyBottomMargin, + LayoutPropertySpacing, + LayoutPropertyHorizontalSpacing, + LayoutPropertyVerticalSpacing, + LayoutPropertySizeConstraint, + LayoutPropertyBoxStretch, + LayoutPropertyGridRowStretch, + LayoutPropertyGridColumnStretch, + LayoutPropertyGridRowMinimumHeight, + LayoutPropertyGridColumnMinimumWidth + }; +} + +// Check for a comma-separated list of integers. Used for +// per-cell stretch properties and grid per row/column properties. +// As it works now, they are passed as QByteArray strings. The +// property sheet refuses all invalid values. This could be +// replaced by lists once the property editor can handle them. + +static bool isIntegerList(const QString &s) +{ + // Check for empty string or comma-separated list of integers + static const QRegExp re(QLatin1String("[0-9]+(,[0-9]+)+")); + Q_ASSERT(re.isValid()); + return s.isEmpty() || re.exactMatch(s); +} + +// Quick lookup by name +static LayoutPropertyType layoutPropertyType(const QString &name) +{ + static QHash<QString, LayoutPropertyType> namePropertyMap; + if (namePropertyMap.empty()) { + namePropertyMap.insert(QLatin1String(leftMargin), LayoutPropertyLeftMargin); + namePropertyMap.insert(QLatin1String(topMargin), LayoutPropertyTopMargin); + namePropertyMap.insert(QLatin1String(rightMargin), LayoutPropertyRightMargin); + namePropertyMap.insert(QLatin1String(bottomMargin), LayoutPropertyBottomMargin); + namePropertyMap.insert(QLatin1String(horizontalSpacing), LayoutPropertyHorizontalSpacing); + namePropertyMap.insert(QLatin1String(verticalSpacing), LayoutPropertyVerticalSpacing); + namePropertyMap.insert(QLatin1String(spacing), LayoutPropertySpacing); + namePropertyMap.insert(QLatin1String(margin), LayoutPropertyMargin); + namePropertyMap.insert(QLatin1String(sizeConstraint), LayoutPropertySizeConstraint); + namePropertyMap.insert(QLatin1String(boxStretchPropertyC ), LayoutPropertyBoxStretch); + namePropertyMap.insert(QLatin1String(gridRowStretchPropertyC), LayoutPropertyGridRowStretch); + namePropertyMap.insert(QLatin1String(gridColumnStretchPropertyC), LayoutPropertyGridColumnStretch); + namePropertyMap.insert(QLatin1String(gridRowMinimumHeightPropertyC), LayoutPropertyGridRowMinimumHeight); + namePropertyMap.insert(QLatin1String(gridColumnMinimumWidthPropertyC), LayoutPropertyGridColumnMinimumWidth); + } + return namePropertyMap.value(name, LayoutPropertyNone); +} + +// return the layout margin if it is margin +static int getLayoutMargin(const QLayout *l, LayoutPropertyType type) +{ + int left, top, right, bottom; + l->getContentsMargins(&left, &top, &right, &bottom); + switch (type) { + case LayoutPropertyLeftMargin: + return left; + case LayoutPropertyTopMargin: + return top; + case LayoutPropertyRightMargin: + return right; + case LayoutPropertyBottomMargin: + return bottom; + default: + Q_ASSERT(0); + break; + } + return 0; +} + +// return the layout margin if it is margin +static void setLayoutMargin(QLayout *l, LayoutPropertyType type, int margin) +{ + int left, top, right, bottom; + l->getContentsMargins(&left, &top, &right, &bottom); + switch (type) { + case LayoutPropertyLeftMargin: + left = margin; + break; + case LayoutPropertyTopMargin: + top = margin; + break; + case LayoutPropertyRightMargin: + right = margin; + break; + case LayoutPropertyBottomMargin: + bottom = margin; + break; + default: + Q_ASSERT(0); + break; + } + l->setContentsMargins(left, top, right, bottom); +} + +namespace qdesigner_internal { + +// ---------- LayoutPropertySheet: This sheet is never visible in +// the property editor. Rather, the sheet pulled for QLayoutWidget +// forwards all properties to it. Some properties (grid spacings) must be handled +// manually, as they are QDOC_PROPERTY only and not visible to introspection. Ditto +// for the 4 margins. + +LayoutPropertySheet::LayoutPropertySheet(QLayout *l, QObject *parent) + : QDesignerPropertySheet(l, parent), m_layout(l) +{ + const QString layoutGroup = QLatin1String("Layout"); + int pindex = createFakeProperty(QLatin1String(leftMargin), 0); + setPropertyGroup(pindex, layoutGroup); + + pindex = createFakeProperty(QLatin1String(topMargin), 0); + setPropertyGroup(pindex, layoutGroup); + + pindex = createFakeProperty(QLatin1String(rightMargin), 0); + setPropertyGroup(pindex, layoutGroup); + + pindex = createFakeProperty(QLatin1String(bottomMargin), 0); + setPropertyGroup(pindex, layoutGroup); + + const int visibleMask = LayoutProperties::visibleProperties(m_layout); + if (visibleMask & LayoutProperties::HorizSpacingProperty) { + pindex = createFakeProperty(QLatin1String(horizontalSpacing), 0); + setPropertyGroup(pindex, layoutGroup); + + pindex = createFakeProperty(QLatin1String(verticalSpacing), 0); + setPropertyGroup(pindex, layoutGroup); + + setAttribute(indexOf(QLatin1String(spacing)), true); + } + + setAttribute(indexOf(QLatin1String(margin)), true); + // Stretch + if (visibleMask & LayoutProperties::BoxStretchProperty) { + pindex = createFakeProperty(QLatin1String(boxStretchPropertyC), QByteArray()); + setPropertyGroup(pindex, layoutGroup); + setAttribute(pindex, true); + } else { + // Add the grid per-row/column stretch and size limits + if (visibleMask & LayoutProperties::GridColumnStretchProperty) { + const QByteArray empty; + pindex = createFakeProperty(QLatin1String(gridRowStretchPropertyC), empty); + setPropertyGroup(pindex, layoutGroup); + setAttribute(pindex, true); + pindex = createFakeProperty(QLatin1String(gridColumnStretchPropertyC), empty); + setPropertyGroup(pindex, layoutGroup); + setAttribute(pindex, true); + pindex = createFakeProperty(QLatin1String(gridRowMinimumHeightPropertyC), empty); + setPropertyGroup(pindex, layoutGroup); + setAttribute(pindex, true); + pindex = createFakeProperty(QLatin1String(gridColumnMinimumWidthPropertyC), empty); + setPropertyGroup(pindex, layoutGroup); + setAttribute(pindex, true); + } + } +#ifdef USE_LAYOUT_SIZE_CONSTRAINT + // SizeConstraint cannot possibly be handled as a real property + // as it affects the layout parent widget and thus + // conflicts with Designer's special layout widget. + // It will take effect on the preview only. + pindex = createFakeProperty(QLatin1String(sizeConstraint)); + setPropertyGroup(pindex, layoutGroup); +#endif +} + +LayoutPropertySheet::~LayoutPropertySheet() +{ +} + +void LayoutPropertySheet::setProperty(int index, const QVariant &value) +{ + const LayoutPropertyType type = layoutPropertyType(propertyName(index)); + if (QLayoutWidget *lw = qobject_cast<QLayoutWidget *>(m_layout->parent())) { + switch (type) { + case LayoutPropertyLeftMargin: + lw->setLayoutLeftMargin(value.toInt()); + return; + case LayoutPropertyTopMargin: + lw->setLayoutTopMargin(value.toInt()); + return; + case LayoutPropertyRightMargin: + lw->setLayoutRightMargin(value.toInt()); + return; + case LayoutPropertyBottomMargin: + lw->setLayoutBottomMargin(value.toInt()); + return; + case LayoutPropertyMargin: { + const int v = value.toInt(); + lw->setLayoutLeftMargin(v); + lw->setLayoutTopMargin(v); + lw->setLayoutRightMargin(v); + lw->setLayoutBottomMargin(v); + } + return; + default: + break; + } + } + switch (type) { + case LayoutPropertyLeftMargin: + case LayoutPropertyTopMargin: + case LayoutPropertyRightMargin: + case LayoutPropertyBottomMargin: + setLayoutMargin(m_layout, type, value.toInt()); + return; + case LayoutPropertyHorizontalSpacing: + if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) { + grid->setHorizontalSpacing(value.toInt()); + return; + } + if (QFormLayout *form = qobject_cast<QFormLayout *>(m_layout)) { + form->setHorizontalSpacing(value.toInt()); + return; + } + break; + case LayoutPropertyVerticalSpacing: + if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) { + grid->setVerticalSpacing(value.toInt()); + return; + } + if (QFormLayout *form = qobject_cast<QFormLayout *>(m_layout)) { + form->setVerticalSpacing(value.toInt()); + return; + } + break; + case LayoutPropertyBoxStretch: + // TODO: Remove the regexp check once a proper editor for integer + // lists is in place? + if (QBoxLayout *box = qobject_cast<QBoxLayout *>(m_layout)) { + const QString stretch = value.toString(); + if (isIntegerList(stretch)) + QFormBuilderExtra::setBoxLayoutStretch(value.toString(), box); + } + break; + case LayoutPropertyGridRowStretch: + if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) { + const QString stretch = value.toString(); + if (isIntegerList(stretch)) + QFormBuilderExtra::setGridLayoutRowStretch(stretch, grid); + } + break; + case LayoutPropertyGridColumnStretch: + if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) { + const QString stretch = value.toString(); + if (isIntegerList(stretch)) + QFormBuilderExtra::setGridLayoutColumnStretch(value.toString(), grid); + } + break; + case LayoutPropertyGridRowMinimumHeight: + if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) { + const QString minSize = value.toString(); + if (isIntegerList(minSize)) + QFormBuilderExtra::setGridLayoutRowMinimumHeight(minSize, grid); + } + break; + case LayoutPropertyGridColumnMinimumWidth: + if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) { + const QString minSize = value.toString(); + if (isIntegerList(minSize)) + QFormBuilderExtra::setGridLayoutColumnMinimumWidth(minSize, grid); + } + break; + default: + break; + } + QDesignerPropertySheet::setProperty(index, value); +} + +QVariant LayoutPropertySheet::property(int index) const +{ + const LayoutPropertyType type = layoutPropertyType(propertyName(index)); + if (const QLayoutWidget *lw = qobject_cast<QLayoutWidget *>(m_layout->parent())) { + switch (type) { + case LayoutPropertyLeftMargin: + return lw->layoutLeftMargin(); + case LayoutPropertyTopMargin: + return lw->layoutTopMargin(); + case LayoutPropertyRightMargin: + return lw->layoutRightMargin(); + case LayoutPropertyBottomMargin: + return lw->layoutBottomMargin(); + default: + break; + } + } + switch (type) { + case LayoutPropertyLeftMargin: + case LayoutPropertyTopMargin: + case LayoutPropertyRightMargin: + case LayoutPropertyBottomMargin: + return getLayoutMargin(m_layout, type); + case LayoutPropertyHorizontalSpacing: + if (const QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) + return grid->horizontalSpacing(); + if (const QFormLayout *form = qobject_cast<QFormLayout *>(m_layout)) + return form->horizontalSpacing(); + break; + case LayoutPropertyVerticalSpacing: + if (const QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) + return grid->verticalSpacing(); + if (const QFormLayout *form = qobject_cast<QFormLayout *>(m_layout)) + return form->verticalSpacing(); + case LayoutPropertyBoxStretch: + if (const QBoxLayout *box = qobject_cast<QBoxLayout *>(m_layout)) + return QVariant(QByteArray(QFormBuilderExtra::boxLayoutStretch(box).toUtf8())); + break; + case LayoutPropertyGridRowStretch: + if (const QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) + return QVariant(QByteArray(QFormBuilderExtra::gridLayoutRowStretch(grid).toUtf8())); + break; + case LayoutPropertyGridColumnStretch: + if (const QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) + return QVariant(QByteArray(QFormBuilderExtra::gridLayoutColumnStretch(grid).toUtf8())); + break; + case LayoutPropertyGridRowMinimumHeight: + if (const QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) + return QVariant(QByteArray(QFormBuilderExtra::gridLayoutRowMinimumHeight(grid).toUtf8())); + break; + case LayoutPropertyGridColumnMinimumWidth: + if (const QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) + return QVariant(QByteArray(QFormBuilderExtra::gridLayoutColumnMinimumWidth(grid).toUtf8())); + break; + default: + break; + } + return QDesignerPropertySheet::property(index); +} + +bool LayoutPropertySheet::reset(int index) +{ + int left, top, right, bottom; + m_layout->getContentsMargins(&left, &top, &right, &bottom); + const LayoutPropertyType type = layoutPropertyType(propertyName(index)); + bool rc = true; + switch (type) { + case LayoutPropertyLeftMargin: + m_layout->setContentsMargins(-1, top, right, bottom); + break; + case LayoutPropertyTopMargin: + m_layout->setContentsMargins(left, -1, right, bottom); + break; + case LayoutPropertyRightMargin: + m_layout->setContentsMargins(left, top, -1, bottom); + break; + case LayoutPropertyBottomMargin: + m_layout->setContentsMargins(left, top, right, -1); + break; + case LayoutPropertyBoxStretch: + if (QBoxLayout *box = qobject_cast<QBoxLayout *>(m_layout)) + QFormBuilderExtra::clearBoxLayoutStretch(box); + break; + case LayoutPropertyGridRowStretch: + if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) + QFormBuilderExtra::clearGridLayoutRowStretch(grid); + break; + case LayoutPropertyGridColumnStretch: + if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) + QFormBuilderExtra::clearGridLayoutColumnStretch(grid); + break; + case LayoutPropertyGridRowMinimumHeight: + if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) + QFormBuilderExtra::clearGridLayoutRowMinimumHeight(grid); + break; + case LayoutPropertyGridColumnMinimumWidth: + if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) + QFormBuilderExtra::clearGridLayoutColumnMinimumWidth(grid); + break; + default: + rc = QDesignerPropertySheet::reset(index); + break; + } + return rc; +} + +void LayoutPropertySheet::setChanged(int index, bool changed) +{ + const LayoutPropertyType type = layoutPropertyType(propertyName(index)); + switch (type) { + case LayoutPropertySpacing: + if (LayoutProperties::visibleProperties(m_layout) & LayoutProperties::HorizSpacingProperty) { + setChanged(indexOf(QLatin1String(horizontalSpacing)), changed); + setChanged(indexOf(QLatin1String(verticalSpacing)), changed); + } + break; + case LayoutPropertyMargin: + setChanged(indexOf(QLatin1String(leftMargin)), changed); + setChanged(indexOf(QLatin1String(topMargin)), changed); + setChanged(indexOf(QLatin1String(rightMargin)), changed); + setChanged(indexOf(QLatin1String(bottomMargin)), changed); + break; + default: + break; + } + QDesignerPropertySheet::setChanged(index, changed); +} + +void LayoutPropertySheet::stretchAttributesToDom(QDesignerFormEditorInterface *core, QLayout *lt, DomLayout *domLayout) +{ + // Check if the respective stretch properties of the layout are changed. + // If so, set them to the DOM + const int visibleMask = LayoutProperties::visibleProperties(lt); + if (!(visibleMask & (LayoutProperties::BoxStretchProperty|LayoutProperties::GridColumnStretchProperty|LayoutProperties::GridRowStretchProperty))) + return; + const QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), lt); + Q_ASSERT(sheet); + + // Stretch + if (visibleMask & LayoutProperties::BoxStretchProperty) { + const int index = sheet->indexOf(QLatin1String(boxStretchPropertyC)); + Q_ASSERT(index != -1); + if (sheet->isChanged(index)) + domLayout->setAttributeStretch(sheet->property(index).toString()); + } + if (visibleMask & LayoutProperties::GridColumnStretchProperty) { + const int index = sheet->indexOf(QLatin1String(gridColumnStretchPropertyC)); + Q_ASSERT(index != -1); + if (sheet->isChanged(index)) + domLayout->setAttributeColumnStretch(sheet->property(index).toString()); + } + if (visibleMask & LayoutProperties::GridRowStretchProperty) { + const int index = sheet->indexOf(QLatin1String(gridRowStretchPropertyC)); + Q_ASSERT(index != -1); + if (sheet->isChanged(index)) + domLayout->setAttributeRowStretch(sheet->property(index).toString()); + } + if (visibleMask & LayoutProperties::GridRowMinimumHeightProperty) { + const int index = sheet->indexOf(QLatin1String(gridRowMinimumHeightPropertyC)); + Q_ASSERT(index != -1); + if (sheet->isChanged(index)) + domLayout->setAttributeRowMinimumHeight(sheet->property(index).toString()); + } + if (visibleMask & LayoutProperties::GridColumnMinimumWidthProperty) { + const int index = sheet->indexOf(QLatin1String(gridColumnMinimumWidthPropertyC)); + Q_ASSERT(index != -1); + if (sheet->isChanged(index)) + domLayout->setAttributeColumnMinimumWidth(sheet->property(index).toString()); + } +} + +void LayoutPropertySheet::markChangedStretchProperties(QDesignerFormEditorInterface *core, QLayout *lt, const DomLayout *domLayout) +{ + // While the actual values are applied by the form builder, we still need + // to mark them as 'changed'. + QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), lt); + Q_ASSERT(sheet); + if (!domLayout->attributeStretch().isEmpty()) + sheet->setChanged(sheet->indexOf(QLatin1String(boxStretchPropertyC)), true); + if (!domLayout->attributeRowStretch().isEmpty()) + sheet->setChanged(sheet->indexOf(QLatin1String(gridRowStretchPropertyC)), true); + if (!domLayout->attributeColumnStretch().isEmpty()) + sheet->setChanged(sheet->indexOf(QLatin1String(gridColumnStretchPropertyC)), true); + if (!domLayout->attributeColumnMinimumWidth().isEmpty()) + sheet->setChanged(sheet->indexOf(QLatin1String(gridColumnMinimumWidthPropertyC)), true); + if (!domLayout->attributeRowMinimumHeight().isEmpty()) + sheet->setChanged(sheet->indexOf(QLatin1String(gridRowMinimumHeightPropertyC)), true); +} + +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/layout_propertysheet.h b/tools/designer/src/components/formeditor/layout_propertysheet.h new file mode 100644 index 0000000..bb2b785 --- /dev/null +++ b/tools/designer/src/components/formeditor/layout_propertysheet.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LAYOUT_PROPERTYSHEET_H +#define LAYOUT_PROPERTYSHEET_H + +#include <qdesigner_propertysheet_p.h> +#include <extensionfactory_p.h> + +#include <QtGui/QLayout> + +QT_BEGIN_NAMESPACE + +class QDesignerFormEditorInterface; +class DomLayout; + +namespace qdesigner_internal { + +class LayoutPropertySheet: public QDesignerPropertySheet +{ + Q_OBJECT + Q_INTERFACES(QDesignerPropertySheetExtension) +public: + explicit LayoutPropertySheet(QLayout *object, QObject *parent = 0); + virtual ~LayoutPropertySheet(); + + virtual void setProperty(int index, const QVariant &value); + virtual QVariant property(int index) const; + virtual bool reset(int index); + void setChanged(int index, bool changed); + + static void stretchAttributesToDom(QDesignerFormEditorInterface *core, QLayout *lt, DomLayout *domLayout); + static void markChangedStretchProperties(QDesignerFormEditorInterface *core, QLayout *lt, const DomLayout *domLayout); + +private: + QLayout *m_layout; +}; + +typedef QDesignerPropertySheetFactory<QLayout, LayoutPropertySheet> LayoutPropertySheetFactory; +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // LAYOUT_PROPERTYSHEET_H diff --git a/tools/designer/src/components/formeditor/line_propertysheet.cpp b/tools/designer/src/components/formeditor/line_propertysheet.cpp new file mode 100644 index 0000000..d13779e --- /dev/null +++ b/tools/designer/src/components/formeditor/line_propertysheet.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "line_propertysheet.h" +#include "formwindow.h" + +// sdk +#include <QtDesigner/QExtensionManager> + +#include <QtGui/QLayout> +#include <QtCore/QMetaObject> +#include <QtCore/QMetaProperty> +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +using namespace qdesigner_internal; + +LinePropertySheet::LinePropertySheet(Line *object, QObject *parent) + : QDesignerPropertySheet(object, parent) +{ + clearFakeProperties(); +} + +LinePropertySheet::~LinePropertySheet() +{ +} + +bool LinePropertySheet::isVisible(int index) const +{ + const QString name = propertyName(index); + + if (name == QLatin1String("frameShape")) + return false; + return QDesignerPropertySheet::isVisible(index); +} + +void LinePropertySheet::setProperty(int index, const QVariant &value) +{ + QDesignerPropertySheet::setProperty(index, value); +} + +QString LinePropertySheet::propertyGroup(int index) const +{ + return QDesignerPropertySheet::propertyGroup(index); +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/line_propertysheet.h b/tools/designer/src/components/formeditor/line_propertysheet.h new file mode 100644 index 0000000..5149cac --- /dev/null +++ b/tools/designer/src/components/formeditor/line_propertysheet.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LINE_PROPERTYSHEET_H +#define LINE_PROPERTYSHEET_H + +#include <qdesigner_propertysheet_p.h> +#include <qdesigner_widget_p.h> +#include <extensionfactory_p.h> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +class LinePropertySheet: public QDesignerPropertySheet +{ + Q_OBJECT + Q_INTERFACES(QDesignerPropertySheetExtension) +public: + explicit LinePropertySheet(Line *object, QObject *parent = 0); + virtual ~LinePropertySheet(); + + virtual void setProperty(int index, const QVariant &value); + virtual bool isVisible(int index) const; + virtual QString propertyGroup(int index) const; +}; + +typedef QDesignerPropertySheetFactory<Line, LinePropertySheet> LinePropertySheetFactory; +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // LINE_PROPERTYSHEET_H diff --git a/tools/designer/src/components/formeditor/previewactiongroup.cpp b/tools/designer/src/components/formeditor/previewactiongroup.cpp new file mode 100644 index 0000000..aa52872 --- /dev/null +++ b/tools/designer/src/components/formeditor/previewactiongroup.cpp @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "previewactiongroup.h" + +#include <deviceprofile_p.h> +#include <shared_settings_p.h> + +#include <QtGui/QStyleFactory> +#include <QtCore/QVariant> + +QT_BEGIN_NAMESPACE + +enum { MaxDeviceActions = 20 }; + +namespace qdesigner_internal { + +PreviewActionGroup::PreviewActionGroup(QDesignerFormEditorInterface *core, QObject *parent) : + QActionGroup(parent), + m_core(core) +{ + /* Create a list of up to MaxDeviceActions invisible actions to be + * populated with device profiles (actiondata: index) followed by the + * standard style actions (actiondata: style name). */ + connect(this, SIGNAL(triggered(QAction*)), this, SLOT(slotTriggered(QAction*))); + setExclusive(true); + + const QString objNamePostfix = QLatin1String("_action"); + // Create invisible actions for devices. Set index as action data. + QString objNamePrefix = QLatin1String("__qt_designer_device_"); + for (int i = 0; i < MaxDeviceActions; i++) { + QAction *a = new QAction(this); + QString objName = objNamePrefix; + objName += QString::number(i); + objName += objNamePostfix; + a->setObjectName(objName); + a->setVisible(false); + a->setData(i); + addAction(a); + } + // Create separator at index MaxDeviceActions + QAction *sep = new QAction(this); + sep->setObjectName(QLatin1String("__qt_designer_deviceseparator")); + sep->setSeparator(true); + sep->setVisible(false); + addAction(sep); + // Populate devices + updateDeviceProfiles(); + + // Add style actions + const QStringList styles = QStyleFactory::keys(); + const QStringList::const_iterator cend = styles.constEnd(); + // Make sure ObjectName is unique in case toolbar solution is used. + objNamePrefix = QLatin1String("__qt_designer_style_"); + // Create styles. Set style name string as action data. + for (QStringList::const_iterator it = styles.constBegin(); it != cend ;++it) { + QAction *a = new QAction(tr("%1 Style").arg(*it), this); + QString objName = objNamePrefix; + objName += *it; + objName += objNamePostfix; + a->setObjectName(objName); + a->setData(*it); + addAction(a); + } +} + +void PreviewActionGroup::updateDeviceProfiles() +{ + typedef QList<DeviceProfile> DeviceProfileList; + typedef QList<QAction *> ActionList; + + const QDesignerSharedSettings settings(m_core); + const DeviceProfileList profiles = settings.deviceProfiles(); + const ActionList al = actions(); + // Separator? + const bool hasProfiles = !profiles.empty(); + al.at(MaxDeviceActions)->setVisible(hasProfiles); + int index = 0; + if (hasProfiles) { + // Make actions visible + const int maxIndex = qMin(static_cast<int>(MaxDeviceActions), profiles.size()); + for (; index < maxIndex; index++) { + const QString name = profiles.at(index).name(); + al.at(index)->setText(name); + al.at(index)->setVisible(true); + } + } + // Hide rest + for ( ; index < MaxDeviceActions; index++) + al.at(index)->setVisible(false); +} + +void PreviewActionGroup::slotTriggered(QAction *a) +{ + // Device or style according to data. + const QVariant data = a->data(); + switch (data.type()) { + case QVariant::String: + emit preview(data.toString(), -1); + break; + case QVariant::Int: + emit preview(QString(), data.toInt()); + break; + default: + break; + } +} + +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/previewactiongroup.h b/tools/designer/src/components/formeditor/previewactiongroup.h new file mode 100644 index 0000000..851f554 --- /dev/null +++ b/tools/designer/src/components/formeditor/previewactiongroup.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of Qt Designer. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#ifndef PREVIEWACTIONGROUP_H +#define PREVIEWACTIONGROUP_H + +#include <QtGui/QActionGroup> + +QT_BEGIN_NAMESPACE + +class QDesignerFormEditorInterface; + +namespace qdesigner_internal { + +/* PreviewActionGroup: To be used as a submenu for 'Preview in...' + * Offers a menu of styles and device profiles. */ + +class PreviewActionGroup : public QActionGroup +{ + Q_DISABLE_COPY(PreviewActionGroup) + Q_OBJECT +public: + explicit PreviewActionGroup(QDesignerFormEditorInterface *core, QObject *parent = 0); + +signals: + void preview(const QString &style, int deviceProfileIndex); + +public slots: + void updateDeviceProfiles(); + +private slots: + void slotTriggered(QAction *); + +private: + QDesignerFormEditorInterface *m_core; +}; +} + +QT_END_NAMESPACE + +#endif // PREVIEWACTIONGROUP_H diff --git a/tools/designer/src/components/formeditor/qdesigner_resource.cpp b/tools/designer/src/components/formeditor/qdesigner_resource.cpp new file mode 100644 index 0000000..75a53b7 --- /dev/null +++ b/tools/designer/src/components/formeditor/qdesigner_resource.cpp @@ -0,0 +1,2665 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdesigner_resource.h" +#include "formwindow.h" +#include "dynamicpropertysheet.h" +#include "qdesigner_tabwidget_p.h" +#include "qdesigner_toolbox_p.h" +#include "qdesigner_stackedbox_p.h" +#include "qdesigner_toolbar_p.h" +#include "qdesigner_dockwidget_p.h" +#include "qdesigner_menu_p.h" +#include "qdesigner_menubar_p.h" +#include "qdesigner_membersheet_p.h" +#include "qtresourcemodel_p.h" +#include "qmdiarea_container.h" +#include "qwizard_container.h" +#include "itemview_propertysheet.h" +#include "layout_propertysheet.h" + +#include <ui4_p.h> +#include <formbuilderextra_p.h> +#include <resourcebuilder_p.h> +#include <textbuilder_p.h> +#include <qdesigner_widgetitem_p.h> + +// shared +#include <widgetdatabase_p.h> +#include <metadatabase_p.h> +#include <layout_p.h> +#include <layoutinfo_p.h> +#include <spacer_widget_p.h> +#include <pluginmanager_p.h> +#include <widgetfactory_p.h> +#include <abstractlanguage.h> +#include <abstractintrospection_p.h> + +#include <qlayout_widget_p.h> +#include <qdesigner_utils_p.h> +#include <ui4_p.h> + +// sdk +#include <QtDesigner/QDesignerPropertySheetExtension> +#include <QtDesigner/QDesignerFormEditorInterface> +#include <QtDesigner/QDesignerExtraInfoExtension> +#include <QtDesigner/QDesignerFormWindowToolInterface> +#include <QtDesigner/QExtensionManager> +#include <QtDesigner/QDesignerContainerExtension> +#include <abstractdialoggui_p.h> + +#include <QtGui/QMenu> +#include <QtGui/QMessageBox> +#include <QtGui/QLayout> +#include <QtGui/QFormLayout> +#include <QtGui/QTabWidget> +#include <QtGui/QToolBox> +#include <QtGui/QStackedWidget> +#include <QtGui/QToolBar> +#include <QtGui/QTabBar> +#include <QtGui/QAction> +#include <QtGui/QActionGroup> +#include <QtGui/QButtonGroup> +#include <QtGui/QApplication> +#include <QtGui/QMainWindow> +#include <QtGui/QSplitter> +#include <QtGui/QMdiArea> +#include <QtGui/QWorkspace> +#include <QtGui/QMenuBar> +#include <QtGui/QFileDialog> +#include <QtGui/QHeaderView> +#include <QtGui/QTreeView> +#include <QtGui/QTableView> +#include <QtGui/QWizardPage> +#include <private/qlayoutengine_p.h> + +#include <QtCore/QBuffer> +#include <QtCore/QDir> +#include <QtCore/QMetaProperty> +#include <QtCore/qdebug.h> +#include <QtCore/QXmlStreamWriter> + +Q_DECLARE_METATYPE(QWidgetList) + +QT_BEGIN_NAMESPACE + +namespace { + typedef QList<DomProperty*> DomPropertyList; +} + +static const char *currentUiVersion = "4.0"; +static const char *clipboardObjectName = "__qt_fake_top_level"; + +#define OLD_RESOURCE_FORMAT // Support pre 4.4 format. + +namespace qdesigner_internal { + +// -------------------- QDesignerResourceBuilder: A resource builder that works on the property sheet icon types. +class QDesignerResourceBuilder : public QResourceBuilder +{ +public: + QDesignerResourceBuilder(QDesignerFormEditorInterface *core, DesignerPixmapCache *pixmapCache, DesignerIconCache *iconCache); + + void setPixmapCache(DesignerPixmapCache *pixmapCache) { m_pixmapCache = pixmapCache; } + void setIconCache(DesignerIconCache *iconCache) { m_iconCache = iconCache; } + bool isSaveRelative() const { return m_saveRelative; } + void setSaveRelative(bool relative) { m_saveRelative = relative; } + QStringList usedQrcFiles() const { return m_usedQrcFiles.keys(); } +#ifdef OLD_RESOURCE_FORMAT + QStringList loadedQrcFiles() const { return m_loadedQrcFiles.keys(); } // needed only for loading old resource attribute of <iconset> tag. +#endif + + virtual QVariant loadResource(const QDir &workingDirectory, const DomProperty *icon) const; + + virtual QVariant toNativeValue(const QVariant &value) const; + + virtual DomProperty *saveResource(const QDir &workingDirectory, const QVariant &value) const; + + virtual bool isResourceType(const QVariant &value) const; +private: + + QDesignerFormEditorInterface *m_core; + DesignerPixmapCache *m_pixmapCache; + DesignerIconCache *m_iconCache; + bool m_saveRelative; + mutable QMap<QString, bool> m_usedQrcFiles; + mutable QMap<QString, bool> m_loadedQrcFiles; +}; + +QDesignerResourceBuilder::QDesignerResourceBuilder(QDesignerFormEditorInterface *core, DesignerPixmapCache *pixmapCache, DesignerIconCache *iconCache) : + m_core(core), + m_pixmapCache(pixmapCache), + m_iconCache(iconCache), + m_saveRelative(true) +{ +} + +static inline void setIconPixmap(QIcon::Mode m, QIcon::State s, const QDir &workingDirectory, const QString &v, PropertySheetIconValue &icon) +{ + icon.setPixmap(m, s, PropertySheetPixmapValue(QFileInfo(workingDirectory, v).absoluteFilePath())); +} + +QVariant QDesignerResourceBuilder::loadResource(const QDir &workingDirectory, const DomProperty *property) const +{ + switch (property->kind()) { + case DomProperty::Pixmap: { + PropertySheetPixmapValue pixmap; + DomResourcePixmap *dp = property->elementPixmap(); + if (!dp->text().isEmpty()) { + pixmap.setPath(QFileInfo(workingDirectory, dp->text()).absoluteFilePath()); +#ifdef OLD_RESOURCE_FORMAT + if (dp->hasAttributeResource()) + m_loadedQrcFiles.insert(QFileInfo(workingDirectory, dp->attributeResource()).absoluteFilePath(), false); +#endif + } + return qVariantFromValue(pixmap); + } + + case DomProperty::IconSet: { + PropertySheetIconValue icon; + DomResourceIcon *di = property->elementIconSet(); + if (const int flags = iconStateFlags(di)) { // new, post 4.4 format + if (flags & NormalOff) + setIconPixmap(QIcon::Normal, QIcon::Off, workingDirectory, di->elementNormalOff()->text(), icon); + if (flags & NormalOn) + setIconPixmap(QIcon::Normal, QIcon::On, workingDirectory, di->elementNormalOn()->text(), icon); + if (flags & DisabledOff) + setIconPixmap(QIcon::Disabled, QIcon::Off, workingDirectory, di->elementDisabledOff()->text(), icon); + if (flags & DisabledOn) + setIconPixmap(QIcon::Disabled, QIcon::On, workingDirectory, di->elementDisabledOn()->text(), icon); + if (flags & ActiveOff) + setIconPixmap(QIcon::Active, QIcon::Off, workingDirectory, di->elementActiveOff()->text(), icon); + if (flags & ActiveOn) + setIconPixmap(QIcon::Active, QIcon::On, workingDirectory, di->elementActiveOn()->text(), icon); + if (flags & SelectedOff) + setIconPixmap(QIcon::Selected, QIcon::Off, workingDirectory, di->elementSelectedOff()->text(), icon); + if (flags & SelectedOn) + setIconPixmap(QIcon::Selected, QIcon::On, workingDirectory, di->elementSelectedOn()->text(), icon); + } else { +#ifdef OLD_RESOURCE_FORMAT + setIconPixmap(QIcon::Normal, QIcon::Off, workingDirectory, di->text(), icon); + if (di->hasAttributeResource()) + m_loadedQrcFiles.insert(QFileInfo(workingDirectory, di->attributeResource()).absoluteFilePath(), false); +#endif + } + return qVariantFromValue(icon); + } + default: + break; + } + return QVariant(); +} + +QVariant QDesignerResourceBuilder::toNativeValue(const QVariant &value) const +{ + if (qVariantCanConvert<PropertySheetPixmapValue>(value)) { + if (m_pixmapCache) + return m_pixmapCache->pixmap(qVariantValue<PropertySheetPixmapValue>(value)); + } else if (qVariantCanConvert<PropertySheetIconValue>(value)) { + if (m_iconCache) + return m_iconCache->icon(qVariantValue<PropertySheetIconValue>(value)); + } + return value; +} + +DomProperty *QDesignerResourceBuilder::saveResource(const QDir &workingDirectory, const QVariant &value) const +{ + DomProperty *p = new DomProperty; + if (qVariantCanConvert<PropertySheetPixmapValue>(value)) { + const PropertySheetPixmapValue pix = qvariant_cast<PropertySheetPixmapValue>(value); + DomResourcePixmap *rp = new DomResourcePixmap; + const QString pixPath = pix.path(); + switch (pix.pixmapSource(m_core)) { + case PropertySheetPixmapValue::LanguageResourcePixmap: + rp->setText(pixPath); + break; + case PropertySheetPixmapValue::ResourcePixmap: { + rp->setText(pixPath); + const QString qrcFile = m_core->resourceModel()->qrcPath(pixPath); + if (!qrcFile.isEmpty()) { + m_usedQrcFiles.insert(qrcFile, false); +#ifdef OLD_RESOURCE_FORMAT // Legacy: Add qrc path + rp->setAttributeResource(workingDirectory.relativeFilePath(qrcFile)); +#endif + } + } + break; + case PropertySheetPixmapValue::FilePixmap: + rp->setText(m_saveRelative ? workingDirectory.relativeFilePath(pixPath) : pixPath); + break; + } + p->setElementPixmap(rp); + return p; + } else if (qVariantCanConvert<PropertySheetIconValue>(value)) { + const PropertySheetIconValue icon = qvariant_cast<PropertySheetIconValue>(value); + const QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> pixmaps = icon.paths(); + if (!pixmaps.isEmpty()) { + DomResourceIcon *ri = new DomResourceIcon; + QMapIterator<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> itPix(pixmaps); + while (itPix.hasNext()) { + const QIcon::Mode mode = itPix.next().key().first; + const QIcon::State state = itPix.key().second; + DomResourcePixmap *rp = new DomResourcePixmap; + const PropertySheetPixmapValue pix = itPix.value(); + const PropertySheetPixmapValue::PixmapSource ps = pix.pixmapSource(m_core); + const QString pixPath = pix.path(); + rp->setText(ps == PropertySheetPixmapValue::FilePixmap && m_saveRelative ? workingDirectory.relativeFilePath(pixPath) : pixPath); + if (state == QIcon::Off) { + switch (mode) { + case QIcon::Normal: + ri->setElementNormalOff(rp); +#ifdef OLD_RESOURCE_FORMAT // Legacy: Set Normal off as text/path in old format. + ri->setText(rp->text()); +#endif + if (ps == PropertySheetPixmapValue::ResourcePixmap) { + // Be sure that ri->text() file comes from active resourceSet (i.e. make appropriate + // resourceSet active before calling this method). + const QString qrcFile = m_core->resourceModel()->qrcPath(ri->text()); + if (!qrcFile.isEmpty()) { + m_usedQrcFiles.insert(qrcFile, false); +#ifdef OLD_RESOURCE_FORMAT // Legacy: Set Normal off as text/path in old format. + ri->setAttributeResource(workingDirectory.relativeFilePath(qrcFile)); +#endif + } + } + break; + case QIcon::Disabled: ri->setElementDisabledOff(rp); break; + case QIcon::Active: ri->setElementActiveOff(rp); break; + case QIcon::Selected: ri->setElementSelectedOff(rp); break; + } + } else { + switch (mode) { + case QIcon::Normal: ri->setElementNormalOn(rp); break; + case QIcon::Disabled: ri->setElementDisabledOn(rp); break; + case QIcon::Active: ri->setElementActiveOn(rp); break; + case QIcon::Selected: ri->setElementSelectedOn(rp); break; + } + } + } + p->setElementIconSet(ri); + return p; + } + } + delete p; + return 0; +} + +bool QDesignerResourceBuilder::isResourceType(const QVariant &value) const +{ + if (qVariantCanConvert<PropertySheetPixmapValue>(value) || qVariantCanConvert<PropertySheetIconValue>(value)) + return true; + return false; +} +// ------------------------- QDesignerTextBuilder +class QDesignerTextBuilder : public QTextBuilder +{ +public: + QDesignerTextBuilder() {} + + virtual QVariant loadText(const DomProperty *icon) const; + + virtual QVariant toNativeValue(const QVariant &value) const; + + virtual DomProperty *saveText(const QVariant &value) const; +}; + +QVariant QDesignerTextBuilder::loadText(const DomProperty *text) const +{ + const DomString *str = text->elementString(); + PropertySheetStringValue strVal(str->text()); + if (str->hasAttributeComment()) { + strVal.setDisambiguation(str->attributeComment()); + } + if (str->hasAttributeExtraComment()) { + strVal.setComment(str->attributeExtraComment()); + } + if (str->hasAttributeNotr()) { + const QString notr = str->attributeNotr(); + const bool translatable = !(notr == QLatin1String("true") || notr == QLatin1String("yes")); + if (!translatable) + strVal.setTranslatable(translatable); + } + return qVariantFromValue(strVal); +} + +QVariant QDesignerTextBuilder::toNativeValue(const QVariant &value) const +{ + if (qVariantCanConvert<PropertySheetStringValue>(value)) + return qVariantFromValue(qVariantValue<PropertySheetStringValue>(value).value()); + return value; +} + +DomProperty *QDesignerTextBuilder::saveText(const QVariant &value) const +{ + if (!qVariantCanConvert<PropertySheetStringValue>(value) && !qVariantCanConvert<QString>(value)) + return 0; + + DomProperty *property = new DomProperty(); + DomString *domStr = new DomString(); + + if (qVariantCanConvert<PropertySheetStringValue>(value)) { + PropertySheetStringValue str = qVariantValue<PropertySheetStringValue>(value); + + domStr->setText(str.value()); + + const QString property_comment = str.disambiguation(); + if (!property_comment.isEmpty()) + domStr->setAttributeComment(property_comment); + const QString property_extraComment = str.comment(); + if (!property_extraComment.isEmpty()) + domStr->setAttributeExtraComment(property_extraComment); + const bool property_translatable = str.translatable(); + if (!property_translatable) + domStr->setAttributeNotr(QLatin1String("true")); + } else { + domStr->setText(value.toString()); + } + + property->setElementString(domStr); + return property; +} + +QDesignerResource::QDesignerResource(FormWindow *formWindow) : + QEditorFormBuilder(formWindow->core()), + m_formWindow(formWindow), + m_topLevelSpacerCount(0), + m_copyWidget(false), + m_selected(0), + m_resourceBuilder(new QDesignerResourceBuilder(m_formWindow->core(), m_formWindow->pixmapCache(), m_formWindow->iconCache())) +{ + setWorkingDirectory(formWindow->absoluteDir()); + setResourceBuilder(m_resourceBuilder); + setTextBuilder(new QDesignerTextBuilder()); + + // ### generalise + const QString designerWidget = QLatin1String("QDesignerWidget"); + const QString layoutWidget = QLatin1String("QLayoutWidget"); + const QString widget = QLatin1String("QWidget"); + m_internal_to_qt.insert(layoutWidget, widget); + m_internal_to_qt.insert(designerWidget, widget); + m_internal_to_qt.insert(QLatin1String("QDesignerDialog"), QLatin1String("QDialog")); + m_internal_to_qt.insert(QLatin1String("QDesignerMenuBar"), QLatin1String("QMenuBar")); + m_internal_to_qt.insert(QLatin1String("QDesignerMenu"), QLatin1String("QMenu")); + m_internal_to_qt.insert(QLatin1String("QDesignerDockWidget"), QLatin1String("QDockWidget")); + m_internal_to_qt.insert(QLatin1String("QDesignerQ3WidgetStack"), QLatin1String("Q3WidgetStack")); + + // invert + QHash<QString, QString>::const_iterator cend = m_internal_to_qt.constEnd(); + for (QHash<QString, QString>::const_iterator it = m_internal_to_qt.constBegin();it != cend; ++it ) { + if (it.value() != designerWidget && it.value() != layoutWidget) + m_qt_to_internal.insert(it.value(), it.key()); + + } +} + +QDesignerResource::~QDesignerResource() +{ +} + +static inline QString messageBoxTitle() +{ + return QApplication::translate("Designer", "Qt Designer"); +} + +void QDesignerResource::save(QIODevice *dev, QWidget *widget) +{ + m_topLevelSpacerCount = 0; + + QAbstractFormBuilder::save(dev, widget); + + if (QSimpleResource::warningsEnabled() && m_topLevelSpacerCount != 0) { + const QString message = QApplication::translate("Designer", "This file contains top level spacers.<br>" + "They have <b>NOT</b> been saved into the form."); + const QString infoMessage = QApplication::translate("Designer", "Perhaps you forgot to create a layout?"); + + core()->dialogGui()->message(widget->window(), QDesignerDialogGuiInterface::TopLevelSpacerMessage, + QMessageBox::Warning, messageBoxTitle(), message, infoMessage, + QMessageBox::Ok); + } +} + +void QDesignerResource::saveDom(DomUI *ui, QWidget *widget) +{ + QAbstractFormBuilder::saveDom(ui, widget); + + QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), widget); + Q_ASSERT(sheet != 0); + + const QVariant classVar = sheet->property(sheet->indexOf(QLatin1String("objectName"))); + QString classStr; + if (classVar.canConvert(QVariant::String)) + classStr = classVar.toString(); + else + classStr = qVariantValue<PropertySheetStringValue>(classVar).value(); + ui->setElementClass(classStr); + + for (int index = 0; index < m_formWindow->toolCount(); ++index) { + QDesignerFormWindowToolInterface *tool = m_formWindow->tool(index); + Q_ASSERT(tool != 0); + tool->saveToDom(ui, widget); + } + + const QString author = m_formWindow->author(); + if (!author.isEmpty()) { + ui->setElementAuthor(author); + } + + const QString comment = m_formWindow->comment(); + if (!comment.isEmpty()) { + ui->setElementComment(comment); + } + + const QString exportMacro = m_formWindow->exportMacro(); + if (!exportMacro.isEmpty()) { + ui->setElementExportMacro(exportMacro); + } + + const QVariantMap designerFormData = m_formWindow->formData(); + if (!designerFormData.empty()) { + DomPropertyList domPropertyList; + const QVariantMap::const_iterator cend = designerFormData.constEnd(); + for (QVariantMap::const_iterator it = designerFormData.constBegin(); it != cend; ++it) { + if (DomProperty *prop = variantToDomProperty(this, widget->metaObject(), it.key(), it.value())) + domPropertyList += prop; + } + if (!domPropertyList.empty()) { + DomDesignerData* domDesignerFormData = new DomDesignerData; + domDesignerFormData->setElementProperty(domPropertyList); + ui->setElementDesignerdata(domDesignerFormData); + } + } + + if (!m_formWindow->includeHints().isEmpty()) { + const QString local = QLatin1String("local"); + const QString global = QLatin1String("global"); + QList<DomInclude*> ui_includes; + foreach (QString includeHint, m_formWindow->includeHints()) { + if (includeHint.isEmpty()) + continue; + DomInclude *incl = new DomInclude; + const QString location = includeHint.at(0) == QLatin1Char('<') ? global : local; + includeHint.remove(QLatin1Char('"')); + includeHint.remove(QLatin1Char('<')); + includeHint.remove(QLatin1Char('>')); + incl->setAttributeLocation(location); + incl->setText(includeHint); + ui_includes.append(incl); + } + + DomIncludes *includes = new DomIncludes; + includes->setElementInclude(ui_includes); + ui->setElementIncludes(includes); + } + + int defaultMargin = INT_MIN, defaultSpacing = INT_MIN; + m_formWindow->layoutDefault(&defaultMargin, &defaultSpacing); + + if (defaultMargin != INT_MIN || defaultSpacing != INT_MIN) { + DomLayoutDefault *def = new DomLayoutDefault; + if (defaultMargin != INT_MIN) + def->setAttributeMargin(defaultMargin); + if (defaultSpacing != INT_MIN) + def->setAttributeSpacing(defaultSpacing); + ui->setElementLayoutDefault(def); + } + + QString marginFunction, spacingFunction; + m_formWindow->layoutFunction(&marginFunction, &spacingFunction); + if (!marginFunction.isEmpty() || !spacingFunction.isEmpty()) { + DomLayoutFunction *def = new DomLayoutFunction; + + if (!marginFunction.isEmpty()) + def->setAttributeMargin(marginFunction); + if (!spacingFunction.isEmpty()) + def->setAttributeSpacing(spacingFunction); + ui->setElementLayoutFunction(def); + } + + QString pixFunction = m_formWindow->pixmapFunction(); + if (!pixFunction.isEmpty()) { + ui->setElementPixmapFunction(pixFunction); + } + + if (QDesignerExtraInfoExtension *extra = qt_extension<QDesignerExtraInfoExtension*>(core()->extensionManager(), core())) + extra->saveUiExtraInfo(ui); + + if (MetaDataBase *metaDataBase = qobject_cast<MetaDataBase *>(core()->metaDataBase())) { + const MetaDataBaseItem *item = metaDataBase->metaDataBaseItem(m_formWindow->mainContainer()); + const QStringList fakeSlots = item->fakeSlots(); + const QStringList fakeSignals =item->fakeSignals(); + if (!fakeSlots.empty() || !fakeSignals.empty()) { + DomSlots *domSlots = new DomSlots(); + domSlots->setElementSlot(fakeSlots); + domSlots->setElementSignal(fakeSignals); + ui->setElementSlots(domSlots); + } + } +} + +namespace { + enum LoadPreCheck { LoadPreCheckFailed, LoadPreCheckVersion3, LoadPreCheckVersionMismatch, LoadPreCheckOk }; + // Pair of major, minor + typedef QPair<int, int> UiVersion; +} + +static UiVersion uiVersion(const QString &attr) +{ + const QStringList versions = attr.split(QLatin1Char('.')); + if (versions.empty()) + return UiVersion(-1, -1); + + bool ok = false; + UiVersion rc(versions.at(0).toInt(&ok), 0); + + if (!ok) + return UiVersion(-1, -1); + + if (versions.size() > 1) { + const int minorVersion = versions.at(1).toInt(&ok); + if (ok) + rc.second = minorVersion; + } + return rc; +} + +// Read version and language attributes of an <UI> element. +static bool readUiAttributes(QIODevice *dev, QString *errorMessage, + QString *version, + QString *language) +{ + const QString uiElement = QLatin1String("ui"); + const QString versionAttribute = QLatin1String("version"); + const QString languageAttribute = QLatin1String("language"); + QXmlStreamReader reader(dev); + // Read up to first element + while (!reader.atEnd()) { + if (reader.readNext() == QXmlStreamReader::StartElement) { + const QStringRef tag = reader.name(); + if (reader.name().compare(uiElement, Qt::CaseInsensitive) == 0) { + const QXmlStreamAttributes attributes = reader.attributes(); + if (attributes.hasAttribute(versionAttribute)) + *version = attributes.value(versionAttribute).toString(); + if (attributes.hasAttribute(languageAttribute)) + *language = attributes.value(languageAttribute).toString(); + return true; + } else { + *errorMessage = QCoreApplication::translate("Designer", "Invalid ui file: The root element <ui> is missing."); + return false; + + } + } + } + *errorMessage = QCoreApplication::translate("Designer", "An error has occurred while reading the ui file at line %1, column %2: %3") + .arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString()); + return false; +} + +// While loading a file, check language, version and extra extension +static LoadPreCheck loadPrecheck(QDesignerFormEditorInterface *core, + QIODevice *dev, + QString *errorMessage, QString *versionString) +{ + QString language; + // Read attributes of <ui> and rewind + if (!readUiAttributes(dev, errorMessage, versionString, &language)) { + // XML error: Mimick the behaviour occurring if an XML error is + // detected later on, report to warning log and have embedding + // application display a dialog. + designerWarning(*errorMessage); + errorMessage->clear(); + return LoadPreCheckFailed; + } + dev->seek(0); + + // Check language unless extension present (Jambi) + if (!language.isEmpty() && !qt_extension<QDesignerLanguageExtension*>(core->extensionManager(), core)) { + if (language.toLower() != QLatin1String("c++")) { + // Jambi?! + *errorMessage = QApplication::translate("Designer", "This file cannot be read because it was created using %1.").arg(language); + return LoadPreCheckFailed; + } + } + + // Version + if (!versionString->isEmpty()) { + const UiVersion version = uiVersion(*versionString); + switch (version.first) { + case 3: + return LoadPreCheckVersion3; + case 4: + break; + default: + *errorMessage = QApplication::translate("Designer", "This file was created using Designer from Qt-%1 and cannot be read.").arg(*versionString); + return LoadPreCheckVersionMismatch; + } + } + return LoadPreCheckOk; +} + +QWidget *QDesignerResource::load(QIODevice *dev, QWidget *parentWidget) +{ + // Run loadPreCheck for version and language + QString errorMessage; + QString version; + switch (loadPrecheck(core(), dev, &errorMessage, &version)) { + case LoadPreCheckFailed: + case LoadPreCheckVersionMismatch: + if (!errorMessage.isEmpty()) + core()->dialogGui()->message(parentWidget->window(), QDesignerDialogGuiInterface::FormLoadFailureMessage, + QMessageBox::Warning, messageBoxTitle(), errorMessage, QMessageBox::Ok); + return 0; + case LoadPreCheckVersion3: { + QWidget *w = 0; + QByteArray ba; + if (runUIC( m_formWindow->fileName(), UIC_ConvertV3, ba, errorMessage)) { + QBuffer buffer(&ba); + buffer.open(QIODevice::ReadOnly); + w = load(&buffer, parentWidget); + if (w) { + // Force the form to pop up a save file dialog + m_formWindow->setFileName(QString()); + } else { + errorMessage = QApplication::translate("Designer", "The converted file could not be read."); + } + } + if (w) { + const QString message = QApplication::translate("Designer", + "This file was created using Designer from Qt-%1 and" + " will be converted to a new form by Qt Designer.").arg(version); + const QString infoMessage = QApplication::translate("Designer", + "The old form has not been touched, but you will have to save the form" + " under a new name."); + + core()->dialogGui()->message(parentWidget->window(), + QDesignerDialogGuiInterface::UiVersionMismatchMessage, + QMessageBox::Information, messageBoxTitle(), message, infoMessage, + QMessageBox::Ok); + return w; + } + + const QString message = QApplication::translate("Designer", + "This file was created using Designer from Qt-%1 and " + "could not be read:\n%2").arg(version).arg(errorMessage); + const QString infoMessage = QApplication::translate("Designer", + "Please run it through <b>uic3 -convert</b> to convert " + "it to Qt-4's ui format."); + core()->dialogGui()->message(parentWidget->window(), QDesignerDialogGuiInterface::FormLoadFailureMessage, + QMessageBox::Warning, messageBoxTitle(), message, infoMessage, + QMessageBox::Ok); + return 0; + } + + case LoadPreCheckOk: + break; + } + return QEditorFormBuilder::load(dev, parentWidget); +} + +bool QDesignerResource::saveRelative() const +{ + return m_resourceBuilder->isSaveRelative(); +} + +void QDesignerResource::setSaveRelative(bool relative) +{ + m_resourceBuilder->setSaveRelative(relative); +} + +static bool addFakeMethods(const DomSlots *domSlots, QStringList &fakeSlots, QStringList &fakeSignals) +{ + if (!domSlots) + return false; + + bool rc = false; + foreach (const QString &fakeSlot, domSlots->elementSlot()) + if (fakeSlots.indexOf(fakeSlot) == -1) { + fakeSlots += fakeSlot; + rc = true; + } + + foreach (const QString &fakeSignal, domSlots->elementSignal()) + if (fakeSignals.indexOf(fakeSignal) == -1) { + fakeSignals += fakeSignal; + rc = true; + } + return rc; +} + +QWidget *QDesignerResource::create(DomUI *ui, QWidget *parentWidget) +{ + // Load extra info extension. This is used by Jambi for preventing + // C++ ui files from being loaded + if (QDesignerExtraInfoExtension *extra = qt_extension<QDesignerExtraInfoExtension*>(core()->extensionManager(), core())) { + if (!extra->loadUiExtraInfo(ui)) { + const QString errorMessage = QApplication::translate("Designer", "This file cannot be read because the extra info extension failed to load."); + core()->dialogGui()->message(parentWidget->window(), QDesignerDialogGuiInterface::FormLoadFailureMessage, + QMessageBox::Warning, messageBoxTitle(), errorMessage, QMessageBox::Ok); + return 0; + } + } + + qdesigner_internal::WidgetFactory *factory = qobject_cast<qdesigner_internal::WidgetFactory*>(core()->widgetFactory()); + Q_ASSERT(factory != 0); + + QDesignerFormWindowInterface *previousFormWindow = factory->currentFormWindow(m_formWindow); + + m_isMainWidget = true; + QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem. + QWidget *mainWidget = QAbstractFormBuilder::create(ui, parentWidget); + + if (mainWidget && m_formWindow) { + m_formWindow->setAuthor(ui->elementAuthor()); + m_formWindow->setComment(ui->elementComment()); + m_formWindow->setExportMacro(ui->elementExportMacro()); + + // Designer data + QVariantMap designerFormData; + if (ui->hasElementDesignerdata()) { + const DomPropertyList domPropertyList = ui->elementDesignerdata()->elementProperty(); + const DomPropertyList::const_iterator cend = domPropertyList.constEnd(); + for (DomPropertyList::const_iterator it = domPropertyList.constBegin(); it != cend; ++it) { + const QVariant vprop = domPropertyToVariant(this, mainWidget->metaObject(), *it); + if (vprop.type() != QVariant::Invalid) + designerFormData.insert((*it)->attributeName(), vprop); + } + } + m_formWindow->setFormData(designerFormData); + + m_formWindow->setPixmapFunction(ui->elementPixmapFunction()); + + if (DomLayoutDefault *def = ui->elementLayoutDefault()) { + m_formWindow->setLayoutDefault(def->attributeMargin(), def->attributeSpacing()); + } + + if (DomLayoutFunction *fun = ui->elementLayoutFunction()) { + m_formWindow->setLayoutFunction(fun->attributeMargin(), fun->attributeSpacing()); + } + + if (DomIncludes *includes = ui->elementIncludes()) { + const QString global = QLatin1String("global"); + QStringList includeHints; + foreach (DomInclude *incl, includes->elementInclude()) { + QString text = incl->text(); + + if (text.isEmpty()) + continue; + + if (incl->hasAttributeLocation() && incl->attributeLocation() == global ) { + text = text.prepend(QLatin1Char('<')).append(QLatin1Char('>')); + } else { + text = text.prepend(QLatin1Char('"')).append(QLatin1Char('"')); + } + + includeHints.append(text); + } + + m_formWindow->setIncludeHints(includeHints); + } + + // Register all button groups the form builder adds as children of the main container for them to be found + // in the signal slot editor + const QObjectList mchildren = mainWidget->children(); + if (!mchildren.empty()) { + QDesignerMetaDataBaseInterface *mdb = core()->metaDataBase(); + const QObjectList::const_iterator cend = mchildren.constEnd(); + for (QObjectList::const_iterator it = mchildren.constBegin(); it != cend; ++it) + if (QButtonGroup *bg = qobject_cast<QButtonGroup*>(*it)) + mdb->add(bg); + } + // Load tools + for (int index = 0; index < m_formWindow->toolCount(); ++index) { + QDesignerFormWindowToolInterface *tool = m_formWindow->tool(index); + Q_ASSERT(tool != 0); + tool->loadFromDom(ui, mainWidget); + } + } + + factory->currentFormWindow(previousFormWindow); + + if (const DomSlots *domSlots = ui->elementSlots()) { + if (MetaDataBase *metaDataBase = qobject_cast<MetaDataBase *>(core()->metaDataBase())) { + QStringList fakeSlots; + QStringList fakeSignals; + if (addFakeMethods(domSlots, fakeSlots, fakeSignals)) { + MetaDataBaseItem *item = metaDataBase->metaDataBaseItem(mainWidget); + item->setFakeSlots(fakeSlots); + item->setFakeSignals(fakeSignals); + } + } + } + if (mainWidget) { + // Initialize the mainwindow geometry. Has it been explicitly specified? + bool hasExplicitGeometry = false; + const QList<DomProperty *> properties = ui->elementWidget()->elementProperty(); + if (!properties.empty()) { + const QString geometry = QLatin1String("geometry"); + foreach (const DomProperty *p, properties) + if (p->attributeName() == geometry) { + hasExplicitGeometry = true; + break; + } + } + if (hasExplicitGeometry) { + // Geometry was specified explicitly: Verify that smartMinSize is respected + // (changed fonts, label wrapping policies, etc). This does not happen automatically in docked mode. + const QSize size = mainWidget->size(); + const QSize minSize = size.expandedTo(qSmartMinSize(mainWidget)); + if (minSize != size) + mainWidget->resize(minSize); + } else { + // No explicit Geometry: perform an adjustSize() to resize the form correctly before embedding it into a container + // (which might otherwise squeeze the form) + mainWidget->adjustSize(); + } + // Some integration wizards create forms with main containers + // based on derived classes of QWidget and load them into Designer + // without the plugin existing. This will trigger the auto-promotion + // mechanism of Designer, which will set container=false for + // QWidgets. For the main container, force container=true and warn. + const QDesignerWidgetDataBaseInterface *wdb = core()->widgetDataBase(); + const int wdbIndex = wdb->indexOfObject(mainWidget); + if (wdbIndex != -1) { + QDesignerWidgetDataBaseItemInterface *item = wdb->item(wdbIndex); + // Promoted main container that is not of container type + if (item->isPromoted() && !item->isContainer()) { + item->setContainer(true); + qWarning("** WARNING The form's main container is an unknown custom widget '%s'." + " Defaulting to a promoted instance of '%s', assuming container.", + item->name().toUtf8().constData(), item->extends().toUtf8().constData()); + } + } + } + return mainWidget; +} + +QWidget *QDesignerResource::create(DomWidget *ui_widget, QWidget *parentWidget) +{ + const QString className = ui_widget->attributeClass(); + if (!m_isMainWidget && className == QLatin1String("QWidget") && ui_widget->elementLayout().size() && + !ui_widget->hasAttributeNative()) { + // ### check if elementLayout.size() == 1 + + QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), parentWidget); + + if (container == 0) { + // generate a QLayoutWidget iff the parent is not an QDesignerContainerExtension. + ui_widget->setAttributeClass(QLatin1String("QLayoutWidget")); + } + } + + // save the actions + const QList<DomActionRef*> actionRefs = ui_widget->elementAddAction(); + ui_widget->setElementAddAction(QList<DomActionRef*>()); + + QWidget *w = QAbstractFormBuilder::create(ui_widget, parentWidget); + + // restore the actions + ui_widget->setElementAddAction(actionRefs); + + if (w == 0) + return 0; + + // ### generalize using the extension manager + QDesignerMenu *menu = qobject_cast<QDesignerMenu*>(w); + QDesignerMenuBar *menuBar = qobject_cast<QDesignerMenuBar*>(w); + + if (menu) { + menu->interactive(false); + menu->hide(); + } else if (menuBar) { + menuBar->interactive(false); + } + + foreach (DomActionRef *ui_action_ref, actionRefs) { + const QString name = ui_action_ref->attributeName(); + if (name == QLatin1String("separator")) { + QAction *sep = new QAction(w); + sep->setSeparator(true); + w->addAction(sep); + addMenuAction(sep); + } else if (QAction *a = m_actions.value(name)) { + w->addAction(a); + } else if (QActionGroup *g = m_actionGroups.value(name)) { + w->addActions(g->actions()); + } else if (QMenu *menu = qFindChild<QMenu*>(w, name)) { + w->addAction(menu->menuAction()); + addMenuAction(menu->menuAction()); + } + } + + if (menu) { + menu->interactive(true); + menu->adjustSpecialActions(); + } else if (menuBar) { + menuBar->interactive(true); + menuBar->adjustSpecialActions(); + } + + ui_widget->setAttributeClass(className); // fix the class name + applyExtensionDataFromDOM(this, core(), ui_widget, w, true); + + // store user-defined scripts + if (MetaDataBase *metaDataBase = qobject_cast<MetaDataBase *>(core()->metaDataBase())) { + const QString designerSource = QLatin1String("designer"); + const DomScripts domScripts = ui_widget->elementScript(); + if (!domScripts.empty()) { + foreach (const DomScript *script, domScripts) { + if (script->hasAttributeSource() && script->attributeSource() == designerSource) { + metaDataBase->metaDataBaseItem(w)->setScript(script->text()); + } + } + } + } + + return w; +} + +QLayout *QDesignerResource::create(DomLayout *ui_layout, QLayout *layout, QWidget *parentWidget) +{ + QLayout *l = QAbstractFormBuilder::create(ui_layout, layout, parentWidget); + + if (QGridLayout *gridLayout = qobject_cast<QGridLayout*>(l)) { + QLayoutSupport::createEmptyCells(gridLayout); + } else { + if (QFormLayout *formLayout = qobject_cast<QFormLayout*>(l)) + QLayoutSupport::createEmptyCells(formLayout); + } + // While the actual values are applied by the form builder, we still need + // to mark them as 'changed'. + LayoutPropertySheet::markChangedStretchProperties(core(), l, ui_layout); + return l; +} + +QLayoutItem *QDesignerResource::create(DomLayoutItem *ui_layoutItem, QLayout *layout, QWidget *parentWidget) +{ + if (ui_layoutItem->kind() == DomLayoutItem::Spacer) { + const DomSpacer *domSpacer = ui_layoutItem->elementSpacer(); + const QHash<QString, DomProperty*> properties = propertyMap(domSpacer->elementProperty()); + Spacer *spacer = static_cast<Spacer*>(core()->widgetFactory()->createWidget(QLatin1String("Spacer"), parentWidget)); + if (domSpacer->hasAttributeName()) + changeObjectName(spacer, domSpacer->attributeName()); + core()->metaDataBase()->add(spacer); + + spacer->setInteractiveMode(false); + applyProperties(spacer, ui_layoutItem->elementSpacer()->elementProperty()); + spacer->setInteractiveMode(true); + + if (m_formWindow) { + m_formWindow->manageWidget(spacer); + if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), spacer)) + sheet->setChanged(sheet->indexOf(QLatin1String("orientation")), true); + } + + return new QWidgetItem(spacer); + } else if (ui_layoutItem->kind() == DomLayoutItem::Layout && parentWidget) { + DomLayout *ui_layout = ui_layoutItem->elementLayout(); + QLayoutWidget *layoutWidget = new QLayoutWidget(m_formWindow, parentWidget); + core()->metaDataBase()->add(layoutWidget); + if (m_formWindow) + m_formWindow->manageWidget(layoutWidget); + (void) create(ui_layout, 0, layoutWidget); + return new QWidgetItem(layoutWidget); + } + return QAbstractFormBuilder::create(ui_layoutItem, layout, parentWidget); +} + +void QDesignerResource::changeObjectName(QObject *o, QString objName) +{ + m_formWindow->unify(o, objName, true); + o->setObjectName(objName); + +} + +/* If the property is a enum or flag value, retrieve + * the existing enum/flag via property sheet and use it to convert */ + +static bool readDomEnumerationValue(const DomProperty *p, + const QDesignerPropertySheetExtension* sheet, int index, + QVariant &v) +{ + switch (p->kind()) { + case DomProperty::Set: { + const QVariant sheetValue = sheet->property(index); + if (qVariantCanConvert<PropertySheetFlagValue>(sheetValue)) { + const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(sheetValue); + bool ok = false; + v = f.metaFlags.parseFlags(p->elementSet(), &ok); + if (!ok) + designerWarning(f.metaFlags.messageParseFailed(p->elementSet())); + return true; + } + } + break; + case DomProperty::Enum: { + const QVariant sheetValue = sheet->property(index); + if (qVariantCanConvert<PropertySheetEnumValue>(sheetValue)) { + const PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(sheetValue); + bool ok = false; + v = e.metaEnum.parseEnum(p->elementEnum(), &ok); + if (!ok) + designerWarning(e.metaEnum.messageParseFailed(p->elementEnum())); + return true; + } + } + break; + default: + break; + } + return false; +} + +void QDesignerResource::applyProperties(QObject *o, const QList<DomProperty*> &properties) +{ + if (properties.empty()) + return; + + QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), o); + if (!sheet) + return; + + QFormBuilderExtra *formBuilderExtra = QFormBuilderExtra::instance(this); + QDesignerDynamicPropertySheetExtension *dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(core()->extensionManager(), o); + const bool dynamicPropertiesAllowed = dynamicSheet && dynamicSheet->dynamicPropertiesAllowed(); + + const QString objectNameProperty = QLatin1String("objectName"); + const DomPropertyList::const_iterator cend = properties.constEnd(); + for (DomPropertyList::const_iterator it = properties.constBegin(); it != cend; ++it) { + const DomProperty *p = *it; + const QString propertyName = p->attributeName(); + const int index = sheet->indexOf(propertyName); + QVariant v; + if (!readDomEnumerationValue(p, sheet, index, v)) + v = toVariant(o->metaObject(), *it); + + if (p->kind() == DomProperty::String) { + if (index != -1 && sheet->property(index).userType() == qMetaTypeId<PropertySheetKeySequenceValue>()) { + const DomString *key = p->elementString(); + PropertySheetKeySequenceValue keyVal(QKeySequence(key->text())); + if (key->hasAttributeComment()) + keyVal.setDisambiguation(key->attributeComment()); + if (key->hasAttributeExtraComment()) + keyVal.setComment(key->attributeExtraComment()); + if (key->hasAttributeNotr()) { + const QString notr = key->attributeNotr(); + const bool translatable = !(notr == QLatin1String("true") || notr == QLatin1String("yes")); + if (!translatable) + keyVal.setTranslatable(translatable); + } + v = qVariantFromValue(keyVal); + } else { + const DomString *str = p->elementString(); + PropertySheetStringValue strVal(v.toString()); + if (str->hasAttributeComment()) + strVal.setDisambiguation(str->attributeComment()); + if (str->hasAttributeExtraComment()) + strVal.setComment(str->attributeExtraComment()); + if (str->hasAttributeNotr()) { + const QString notr = str->attributeNotr(); + const bool translatable = !(notr == QLatin1String("true") || notr == QLatin1String("yes")); + if (!translatable) + strVal.setTranslatable(translatable); + } + v = qVariantFromValue(strVal); + } + } + + formBuilderExtra->applyPropertyInternally(o, propertyName, v); + if (index != -1) { + sheet->setProperty(index, v); + sheet->setChanged(index, true); + } else if (dynamicPropertiesAllowed) { + QVariant defaultValue = QVariant(v.type()); + bool isDefault = (v == defaultValue); + if (qVariantCanConvert<PropertySheetIconValue>(v)) { + defaultValue = QVariant(QVariant::Icon); + isDefault = (qVariantValue<PropertySheetIconValue>(v) == PropertySheetIconValue()); + } else if (qVariantCanConvert<PropertySheetPixmapValue>(v)) { + defaultValue = QVariant(QVariant::Pixmap); + isDefault = (qVariantValue<PropertySheetPixmapValue>(v) == PropertySheetPixmapValue()); + } else if (qVariantCanConvert<PropertySheetStringValue>(v)) { + defaultValue = QVariant(QVariant::String); + isDefault = (qVariantValue<PropertySheetStringValue>(v) == PropertySheetStringValue()); + } else if (qVariantCanConvert<PropertySheetKeySequenceValue>(v)) { + defaultValue = QVariant(QVariant::KeySequence); + isDefault = (qVariantValue<PropertySheetKeySequenceValue>(v) == PropertySheetKeySequenceValue()); + } + if (defaultValue.type() != QVariant::UserType) { + const int idx = dynamicSheet->addDynamicProperty(p->attributeName(), defaultValue); + if (idx != -1) { + sheet->setProperty(idx, v); + sheet->setChanged(idx, !isDefault); + } + } + } + + if (propertyName == objectNameProperty) + changeObjectName(o, o->objectName()); + } +} + +QWidget *QDesignerResource::createWidget(const QString &widgetName, QWidget *parentWidget, const QString &_name) +{ + QString name = _name; + QString className = widgetName; + if (m_isMainWidget) + m_isMainWidget = false; + + QWidget *w = core()->widgetFactory()->createWidget(className, parentWidget); + if (!w) + return 0; + + if (name.isEmpty()) { + QDesignerWidgetDataBaseInterface *db = core()->widgetDataBase(); + if (QDesignerWidgetDataBaseItemInterface *item = db->item(db->indexOfObject(w))) + name = qtify(item->name()); + } + + changeObjectName(w, name); + + QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), parentWidget); + if (!qobject_cast<QMenu*>(w) && (!parentWidget || !container)) { + m_formWindow->manageWidget(w); + if (parentWidget) { + QList<QWidget *> list = qVariantValue<QWidgetList>(parentWidget->property("_q_widgetOrder")); + list.append(w); + parentWidget->setProperty("_q_widgetOrder", qVariantFromValue(list)); + QList<QWidget *> zOrder = qVariantValue<QWidgetList>(parentWidget->property("_q_zOrder")); + zOrder.append(w); + parentWidget->setProperty("_q_zOrder", qVariantFromValue(list)); + } + } else { + core()->metaDataBase()->add(w); + } + + w->setWindowFlags(w->windowFlags() & ~Qt::Window); + // Make sure it is non-modal (for example, KDialog calls setModal(true) in the constructor). + w->setWindowModality(Qt::NonModal); + + return w; +} + +QLayout *QDesignerResource::createLayout(const QString &layoutName, QObject *parent, const QString &name) +{ + QWidget *layoutBase = 0; + QLayout *layout = qobject_cast<QLayout*>(parent); + + if (parent->isWidgetType()) + layoutBase = static_cast<QWidget*>(parent); + else { + Q_ASSERT( layout != 0 ); + layoutBase = layout->parentWidget(); + } + + LayoutInfo::Type layoutType = LayoutInfo::layoutType(layoutName); + if (layoutType == LayoutInfo::NoLayout) { + designerWarning(QCoreApplication::translate("QDesignerResource", "The layout type '%1' is not supported, defaulting to grid.").arg(layoutName)); + layoutType = LayoutInfo::Grid; + } + QLayout *lay = core()->widgetFactory()->createLayout(layoutBase, layout, layoutType); + if (lay != 0) + changeObjectName(lay, name); + + return lay; +} + +// save +DomWidget *QDesignerResource::createDom(QWidget *widget, DomWidget *ui_parentWidget, bool recursive) +{ + QDesignerMetaDataBaseItemInterface *item = core()->metaDataBase()->item(widget); + if (!item) + return 0; + + if (qobject_cast<Spacer*>(widget) && m_copyWidget == false) { + ++m_topLevelSpacerCount; + return 0; + } + + const QDesignerWidgetDataBaseInterface *wdb = core()->widgetDataBase(); + QDesignerWidgetDataBaseItemInterface *widgetInfo = 0; + const int widgetInfoIndex = wdb->indexOfObject(widget, false); + if (widgetInfoIndex != -1) { + widgetInfo = wdb->item(widgetInfoIndex); + // Recursively add all dependent custom widgets + QDesignerWidgetDataBaseItemInterface *customInfo = widgetInfo; + while (customInfo && customInfo->isCustom()) { + m_usedCustomWidgets.insert(customInfo, true); + const QString extends = customInfo->extends(); + if (extends == customInfo->name()) { + break; // There are faulty files around that have name==extends + } else { + const int extendsIndex = wdb->indexOfClassName(customInfo->extends()); + customInfo = extendsIndex != -1 ? wdb->item(extendsIndex) : static_cast<QDesignerWidgetDataBaseItemInterface *>(0); + } + } + } + + DomWidget *w = 0; + + if (QTabWidget *tabWidget = qobject_cast<QTabWidget*>(widget)) + w = saveWidget(tabWidget, ui_parentWidget); + else if (QStackedWidget *stackedWidget = qobject_cast<QStackedWidget*>(widget)) + w = saveWidget(stackedWidget, ui_parentWidget); + else if (QToolBox *toolBox = qobject_cast<QToolBox*>(widget)) + w = saveWidget(toolBox, ui_parentWidget); + else if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) + w = saveWidget(toolBar, ui_parentWidget); + else if (QDesignerDockWidget *dockWidget = qobject_cast<QDesignerDockWidget*>(widget)) + w = saveWidget(dockWidget, ui_parentWidget); + else if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), widget)) + w = saveWidget(widget, container, ui_parentWidget); + else if (QTreeView *treeView = qobject_cast<QTreeView*>(widget)) + w = saveWidget(treeView, ui_parentWidget); + else if (QTableView *tableView = qobject_cast<QTableView*>(widget)) + w = saveWidget(tableView, ui_parentWidget); + else if (QWizardPage *wizardPage = qobject_cast<QWizardPage*>(widget)) + w = saveWidget(wizardPage, ui_parentWidget); + else + w = QAbstractFormBuilder::createDom(widget, ui_parentWidget, recursive); + + Q_ASSERT( w != 0 ); + + if (!qobject_cast<QLayoutWidget*>(widget) && w->attributeClass() == QLatin1String("QWidget")) { + w->setAttributeNative(true); + } + + const QString className = w->attributeClass(); + if (m_internal_to_qt.contains(className)) + w->setAttributeClass(m_internal_to_qt.value(className)); + + w->setAttributeName(widget->objectName()); + + if (isPromoted( core(), widget)) { // is promoted? + Q_ASSERT(widgetInfo != 0); + + w->setAttributeName(widget->objectName()); + w->setAttributeClass(widgetInfo->name()); + + QList<DomProperty*> prop_list = w->elementProperty(); + foreach (DomProperty *prop, prop_list) { + if (prop->attributeName() == QLatin1String("geometry")) { + if (DomRect *rect = prop->elementRect()) { + rect->setElementX(widget->x()); + rect->setElementY(widget->y()); + } + break; + } + } + } else if (widgetInfo != 0 && m_usedCustomWidgets.contains(widgetInfo)) { + if (widgetInfo->name() != w->attributeClass()) + w->setAttributeClass(widgetInfo->name()); + } + addExtensionDataToDOM(this, core(), w, widget); + + addUserDefinedScripts(widget, w); + return w; +} + +DomLayout *QDesignerResource::createDom(QLayout *layout, DomLayout *ui_parentLayout, DomWidget *ui_parentWidget) +{ + QDesignerMetaDataBaseItemInterface *item = core()->metaDataBase()->item(layout); + + if (item == 0) { + layout = qFindChild<QLayout*>(layout); + // refresh the meta database item + item = core()->metaDataBase()->item(layout); + } + + if (item == 0) { + // nothing to do. + return 0; + } + + if (qobject_cast<QSplitter*>(layout->parentWidget()) != 0) { + // nothing to do. + return 0; + } + + m_chain.push(layout); + + DomLayout *l = QAbstractFormBuilder::createDom(layout, ui_parentLayout, ui_parentWidget); + Q_ASSERT(l != 0); + LayoutPropertySheet::stretchAttributesToDom(core(), layout, l); + + m_chain.pop(); + + return l; +} + +DomLayoutItem *QDesignerResource::createDom(QLayoutItem *item, DomLayout *ui_layout, DomWidget *ui_parentWidget) +{ + DomLayoutItem *ui_item = 0; + + if (Spacer *s = qobject_cast<Spacer*>(item->widget())) { + if (!core()->metaDataBase()->item(s)) + return 0; + + DomSpacer *spacer = new DomSpacer(); + const QString objectName = s->objectName(); + if (!objectName.isEmpty()) + spacer->setAttributeName(objectName); + const QList<DomProperty*> properties = computeProperties(item->widget()); + // ### filter the properties + spacer->setElementProperty(properties); + + ui_item = new DomLayoutItem(); + ui_item->setElementSpacer(spacer); + m_laidout.insert(item->widget(), true); + } else if (QLayoutWidget *layoutWidget = qobject_cast<QLayoutWidget*>(item->widget())) { + // Do not save a QLayoutWidget if it is within a layout (else it is saved as "QWidget" + Q_ASSERT(layoutWidget->layout()); + DomLayout *l = createDom(layoutWidget->layout(), ui_layout, ui_parentWidget); + ui_item = new DomLayoutItem(); + ui_item->setElementLayout(l); + m_laidout.insert(item->widget(), true); + } else if (!item->spacerItem()) { // we use spacer as fake item in the Designer + ui_item = QAbstractFormBuilder::createDom(item, ui_layout, ui_parentWidget); + } else { + return 0; + } + + if (m_chain.size() && item->widget()) { + if (QGridLayout *grid = qobject_cast<QGridLayout*>(m_chain.top())) { + const int index = Utils::indexOfWidget(grid, item->widget()); + + int row, column, rowspan, colspan; + grid->getItemPosition(index, &row, &column, &rowspan, &colspan); + ui_item->setAttributeRow(row); + ui_item->setAttributeColumn(column); + + if (colspan != 1) + ui_item->setAttributeColSpan(colspan); + + if (rowspan != 1) + ui_item->setAttributeRowSpan(rowspan); + } else { + if (QFormLayout *form = qobject_cast<QFormLayout*>(m_chain.top())) { + const int index = Utils::indexOfWidget(form, item->widget()); + int row, column, colspan; + getFormLayoutItemPosition(form, index, &row, &column, 0, &colspan); + ui_item->setAttributeRow(row); + ui_item->setAttributeColumn(column); + if (colspan != 1) + ui_item->setAttributeColSpan(colspan); + } + } + } + + return ui_item; +} + +static void addFakeMethodsToWidgetDataBase(const DomCustomWidget *domCustomWidget, WidgetDataBaseItem *item) +{ + const DomSlots *domSlots = domCustomWidget->elementSlots(); + if (!domSlots) + return; + + // Merge in new slots, signals + QStringList fakeSlots = item->fakeSlots(); + QStringList fakeSignals = item->fakeSignals(); + if (addFakeMethods(domSlots, fakeSlots, fakeSignals)) { + item->setFakeSlots(fakeSlots); + item->setFakeSignals(fakeSignals); + } +} + +void QDesignerResource::addCustomWidgetsToWidgetDatabase(DomCustomWidgetList& custom_widget_list) +{ + // Perform one iteration of adding the custom widgets to the database, + // looking up the base class and inheriting its data. + // Remove the succeeded custom widgets from the list. + // Classes whose base class could not be found are left in the list. + QDesignerWidgetDataBaseInterface *db = m_formWindow->core()->widgetDataBase(); + for (int i=0; i < custom_widget_list.size(); ) { + bool classInserted = false; + DomCustomWidget *custom_widget = custom_widget_list[i]; + const QString customClassName = custom_widget->elementClass(); + const QString base_class = custom_widget->elementExtends(); + QString includeFile; + IncludeType includeType = IncludeLocal; + if (const DomHeader *header = custom_widget->elementHeader()) { + includeFile = header->text(); + if (header->hasAttributeLocation() && header->attributeLocation() == QLatin1String("global")) + includeType = IncludeGlobal; + } + const bool domIsContainer = custom_widget->elementContainer(); + // Append a new item + if (base_class.isEmpty()) { + WidgetDataBaseItem *item = new WidgetDataBaseItem(customClassName); + item->setPromoted(false); + item->setGroup(QApplication::translate("Designer", "Custom Widgets")); + item->setIncludeFile(buildIncludeFile(includeFile, includeType)); + item->setContainer(domIsContainer); + item->setCustom(true); + addFakeMethodsToWidgetDataBase(custom_widget, item); + db->append(item); + custom_widget_list.removeAt(i); + classInserted = true; + } else { + // Create a new entry cloned from base class. Note that this will ignore existing + // classes, eg, plugin custom widgets. + QDesignerWidgetDataBaseItemInterface *item = + appendDerived(db, customClassName, QApplication::translate("Designer", "Promoted Widgets"), + base_class, + buildIncludeFile(includeFile, includeType), + true,true); + // Ok, base class found. + if (item) { + // Hack to accommodate for old UI-files in which "contains" is not set properly: + // Apply "contains" from DOM only if true (else, eg classes from QFrame might not accept + // dropping child widgets on them as container=false). This also allows for + // QWidget-derived stacked pages. + if (domIsContainer) + item->setContainer(domIsContainer); + + addFakeMethodsToWidgetDataBase(custom_widget, static_cast<WidgetDataBaseItem*>(item)); + custom_widget_list.removeAt(i); + classInserted = true; + } + } + // Skip failed item. + if (!classInserted) + i++; + } + +} +void QDesignerResource::createCustomWidgets(DomCustomWidgets *dom_custom_widgets) +{ + if (dom_custom_widgets == 0) + return; + DomCustomWidgetList custom_widget_list = dom_custom_widgets->elementCustomWidget(); + // Attempt to insert each item derived from its base class. + // This should at most require two iterations in the event that the classes are out of order + // (derived first, max depth: promoted custom plugin = 2) + for (int iteration = 0; iteration < 2; iteration++) { + addCustomWidgetsToWidgetDatabase(custom_widget_list); + if (custom_widget_list.empty()) + return; + } + // Oops, there are classes left whose base class could not be found. + // Default them to QWidget with warnings. + const QString fallBackBaseClass = QLatin1String("QWidget"); + for (int i=0; i < custom_widget_list.size(); i++ ) { + DomCustomWidget *custom_widget = custom_widget_list[i]; + const QString customClassName = custom_widget->elementClass(); + const QString base_class = custom_widget->elementExtends(); + qDebug() << "** WARNING The base class " << base_class << " of the custom widget class " << customClassName + << " could not be found. Defaulting to " << fallBackBaseClass << '.'; + custom_widget->setElementExtends(fallBackBaseClass); + } + // One more pass. + addCustomWidgetsToWidgetDatabase(custom_widget_list); + Q_ASSERT(custom_widget_list.empty()); +} + +DomTabStops *QDesignerResource::saveTabStops() +{ + QDesignerMetaDataBaseItemInterface *item = core()->metaDataBase()->item(m_formWindow); + Q_ASSERT(item); + + QStringList tabStops; + foreach (QWidget *widget, item->tabOrder()) { + if (m_formWindow->mainContainer()->isAncestorOf(widget)) + tabStops.append(widget->objectName()); + } + + if (tabStops.count()) { + DomTabStops *dom = new DomTabStops; + dom->setElementTabStop(tabStops); + return dom; + } + + return 0; +} + +void QDesignerResource::applyTabStops(QWidget *widget, DomTabStops *tabStops) +{ + if (!tabStops) + return; + + QList<QWidget*> tabOrder; + foreach (QString widgetName, tabStops->elementTabStop()) { + if (QWidget *w = qFindChild<QWidget*>(widget, widgetName)) { + tabOrder.append(w); + } + } + + QDesignerMetaDataBaseItemInterface *item = core()->metaDataBase()->item(m_formWindow); + Q_ASSERT(item); + item->setTabOrder(tabOrder); +} + +/* Unmanaged container pages occur when someone adds a page in a custom widget + * constructor. They don't have a meta DB entry which causes createDom + * to return 0. */ +inline QString msgUnmanagedPage(QDesignerFormEditorInterface *core, + QWidget *container, int index, QWidget *page) +{ + return QCoreApplication::translate("QDesignerResource", +"The container extension of the widget '%1' (%2) returned a widget not managed by Designer '%3' (%4) when queried for page #%5.\n" +"Container pages should only be added by specifying them in XML returned by the domXml() method of the custom widget."). + arg(container->objectName(), WidgetFactory::classNameOf(core, container), + page->objectName(), WidgetFactory::classNameOf(core, page)). + arg(index); +} + +DomWidget *QDesignerResource::saveWidget(QWidget *widget, QDesignerContainerExtension *container, DomWidget *ui_parentWidget) +{ + DomWidget *ui_widget = QAbstractFormBuilder::createDom(widget, ui_parentWidget, false); + QList<DomWidget*> ui_widget_list; + + for (int i=0; i<container->count(); ++i) { + QWidget *page = container->widget(i); + Q_ASSERT(page); + + if (DomWidget *ui_page = createDom(page, ui_widget)) { + ui_widget_list.append(ui_page); + } else { + if (QSimpleResource::warningsEnabled()) + designerWarning(msgUnmanagedPage(core(), widget, i, page)); + } + } + + ui_widget->setElementWidget(ui_widget_list); + + return ui_widget; +} + +DomWidget *QDesignerResource::saveWidget(QStackedWidget *widget, DomWidget *ui_parentWidget) +{ + DomWidget *ui_widget = QAbstractFormBuilder::createDom(widget, ui_parentWidget, false); + QList<DomWidget*> ui_widget_list; + if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), widget)) { + for (int i=0; i<container->count(); ++i) { + QWidget *page = container->widget(i); + Q_ASSERT(page); + if (DomWidget *ui_page = createDom(page, ui_widget)) { + ui_widget_list.append(ui_page); + } else { + if (QSimpleResource::warningsEnabled()) + designerWarning(msgUnmanagedPage(core(), widget, i, page)); + } + } + } + + ui_widget->setElementWidget(ui_widget_list); + + return ui_widget; +} + +DomWidget *QDesignerResource::saveWidget(QToolBar *toolBar, DomWidget *ui_parentWidget) +{ + DomWidget *ui_widget = QAbstractFormBuilder::createDom(toolBar, ui_parentWidget, false); + if (const QMainWindow *mainWindow = qobject_cast<QMainWindow*>(toolBar->parentWidget())) { + const bool toolBarBreak = mainWindow->toolBarBreak(toolBar); + const Qt::ToolBarArea area = mainWindow->toolBarArea(toolBar); + + QList<DomProperty*> attributes = ui_widget->elementAttribute(); + + DomProperty *attr = new DomProperty(); + attr->setAttributeName(QLatin1String("toolBarArea")); + attr->setElementEnum(QLatin1String(toolBarAreaMetaEnum().valueToKey(area))); + attributes << attr; + + attr = new DomProperty(); + attr->setAttributeName(QLatin1String("toolBarBreak")); + attr->setElementBool(toolBarBreak ? QLatin1String("true") : QLatin1String("false")); + attributes << attr; + ui_widget->setElementAttribute(attributes); + } + + return ui_widget; +} + +DomWidget *QDesignerResource::saveWidget(QDesignerDockWidget *dockWidget, DomWidget *ui_parentWidget) +{ + DomWidget *ui_widget = QAbstractFormBuilder::createDom(dockWidget, ui_parentWidget, true); + if (QMainWindow *mainWindow = qobject_cast<QMainWindow*>(dockWidget->parentWidget())) { + const Qt::DockWidgetArea area = mainWindow->dockWidgetArea(dockWidget); + DomProperty *attr = new DomProperty(); + attr->setAttributeName(QLatin1String("dockWidgetArea")); + attr->setElementNumber(int(area)); + ui_widget->setElementAttribute(ui_widget->elementAttribute() << attr); + } + + return ui_widget; +} + +DomWidget *QDesignerResource::saveWidget(QTreeView *treeView, DomWidget *ui_parentWidget) +{ + DomWidget *ui_widget = QAbstractFormBuilder::createDom(treeView, ui_parentWidget, true); + + QDesignerPropertySheetExtension *sheet + = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), treeView); + ItemViewPropertySheet *itemViewSheet = static_cast<ItemViewPropertySheet*>(sheet); + + if (itemViewSheet) { + QHash<QString,QString> nameMap = itemViewSheet->propertyNameMap(); + foreach (const QString &fakeName, nameMap.keys()) { + int index = itemViewSheet->indexOf(fakeName); + if (sheet->isChanged(index)) { + DomProperty *domAttr = createProperty(treeView->header(), nameMap.value(fakeName), + itemViewSheet->property(index)); + domAttr->setAttributeName(fakeName); + ui_widget->setElementAttribute(ui_widget->elementAttribute() << domAttr); + } + } + } + + return ui_widget; +} + +DomWidget *QDesignerResource::saveWidget(QTableView *tableView, DomWidget *ui_parentWidget) +{ + DomWidget *ui_widget = QAbstractFormBuilder::createDom(tableView, ui_parentWidget, true); + + QDesignerPropertySheetExtension *sheet + = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), tableView); + ItemViewPropertySheet *itemViewSheet = static_cast<ItemViewPropertySheet*>(sheet); + + if (itemViewSheet) { + QHash<QString,QString> nameMap = itemViewSheet->propertyNameMap(); + foreach (const QString &fakeName, nameMap.keys()) { + int index = itemViewSheet->indexOf(fakeName); + if (sheet->isChanged(index)) { + DomProperty *domAttr; + if (fakeName.startsWith(QLatin1String("horizontal"))) { + domAttr = createProperty(tableView->horizontalHeader(), nameMap.value(fakeName), + itemViewSheet->property(index)); + } else { + domAttr = createProperty(tableView->verticalHeader(), nameMap.value(fakeName), + itemViewSheet->property(index)); + } + domAttr->setAttributeName(fakeName); + ui_widget->setElementAttribute(ui_widget->elementAttribute() << domAttr); + } + } + } + + return ui_widget; +} + +static void saveStringProperty(DomProperty *property, const PropertySheetStringValue &value) +{ + DomString *str = new DomString(); + str->setText(value.value()); + + const QString property_comment = value.disambiguation(); + if (!property_comment.isEmpty()) + str->setAttributeComment(property_comment); + const QString property_extraComment = value.comment(); + if (!property_extraComment.isEmpty()) + str->setAttributeExtraComment(property_extraComment); + const bool property_translatable = value.translatable(); + if (!property_translatable) + str->setAttributeNotr(QLatin1String("true")); + + property->setElementString(str); +} + +static void saveKeySequenceProperty(DomProperty *property, const PropertySheetKeySequenceValue &value) +{ + DomString *str = new DomString(); + str->setText(value.value().toString()); + + const QString property_comment = value.disambiguation(); + if (!property_comment.isEmpty()) + str->setAttributeComment(property_comment); + const QString property_extraComment = value.comment(); + if (!property_extraComment.isEmpty()) + str->setAttributeExtraComment(property_extraComment); + const bool property_translatable = value.translatable(); + if (!property_translatable) + str->setAttributeNotr(QLatin1String("true")); + + property->setElementString(str); +} + +DomWidget *QDesignerResource::saveWidget(QTabWidget *widget, DomWidget *ui_parentWidget) +{ + DomWidget *ui_widget = QAbstractFormBuilder::createDom(widget, ui_parentWidget, false); + QList<DomWidget*> ui_widget_list; + + if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), widget)) { + const int current = widget->currentIndex(); + for (int i=0; i<container->count(); ++i) { + QWidget *page = container->widget(i); + Q_ASSERT(page); + + DomWidget *ui_page = createDom(page, ui_widget); + if (!ui_page) { + if (QSimpleResource::warningsEnabled()) + designerWarning(msgUnmanagedPage(core(), widget, i, page)); + continue; + } + QList<DomProperty*> ui_attribute_list; + + const QFormBuilderStrings &strings = QFormBuilderStrings::instance(); + // attribute `icon' + widget->setCurrentIndex(i); + QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), widget); + PropertySheetIconValue icon = qVariantValue<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String("currentTabIcon")))); + DomProperty *p = resourceBuilder()->saveResource(workingDirectory(), qVariantFromValue(icon)); + if (p) { + p->setAttributeName(strings.iconAttribute); + ui_attribute_list.append(p); + } + // attribute `title' + p = textBuilder()->saveText(sheet->property(sheet->indexOf(QLatin1String("currentTabText")))); + if (p) { + p->setAttributeName(strings.titleAttribute); + ui_attribute_list.append(p); + } + + // attribute `toolTip' + QVariant v = sheet->property(sheet->indexOf(QLatin1String("currentTabToolTip"))); + if (!qVariantValue<PropertySheetStringValue>(v).value().isEmpty()) { + p = textBuilder()->saveText(v); + if (p) { + p->setAttributeName(strings.toolTipAttribute); + ui_attribute_list.append(p); + } + } + + // attribute `whatsThis' + v = sheet->property(sheet->indexOf(QLatin1String("currentTabWhatsThis"))); + if (!qVariantValue<PropertySheetStringValue>(v).value().isEmpty()) { + p = textBuilder()->saveText(v); + if (p) { + p->setAttributeName(strings.whatsThisAttribute); + ui_attribute_list.append(p); + } + } + + ui_page->setElementAttribute(ui_attribute_list); + + ui_widget_list.append(ui_page); + } + widget->setCurrentIndex(current); + } + + ui_widget->setElementWidget(ui_widget_list); + + return ui_widget; +} + +DomWidget *QDesignerResource::saveWidget(QToolBox *widget, DomWidget *ui_parentWidget) +{ + DomWidget *ui_widget = QAbstractFormBuilder::createDom(widget, ui_parentWidget, false); + QList<DomWidget*> ui_widget_list; + + if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), widget)) { + const int current = widget->currentIndex(); + for (int i=0; i<container->count(); ++i) { + QWidget *page = container->widget(i); + Q_ASSERT(page); + + DomWidget *ui_page = createDom(page, ui_widget); + if (!ui_page) { + if (QSimpleResource::warningsEnabled()) + designerWarning(msgUnmanagedPage(core(), widget, i, page)); + continue; + } + + // attribute `label' + QList<DomProperty*> ui_attribute_list; + + const QFormBuilderStrings &strings = QFormBuilderStrings::instance(); + + // attribute `icon' + widget->setCurrentIndex(i); + QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), widget); + PropertySheetIconValue icon = qVariantValue<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String("currentItemIcon")))); + DomProperty *p = resourceBuilder()->saveResource(workingDirectory(), qVariantFromValue(icon)); + if (p) { + p->setAttributeName(strings.iconAttribute); + ui_attribute_list.append(p); + } + p = textBuilder()->saveText(sheet->property(sheet->indexOf(QLatin1String("currentItemText")))); + if (p) { + p->setAttributeName(strings.labelAttribute); + ui_attribute_list.append(p); + } + + // attribute `toolTip' + QVariant v = sheet->property(sheet->indexOf(QLatin1String("currentItemToolTip"))); + if (!qVariantValue<PropertySheetStringValue>(v).value().isEmpty()) { + p = textBuilder()->saveText(v); + if (p) { + p->setAttributeName(strings.toolTipAttribute); + ui_attribute_list.append(p); + } + } + + ui_page->setElementAttribute(ui_attribute_list); + + ui_widget_list.append(ui_page); + } + widget->setCurrentIndex(current); + } + + ui_widget->setElementWidget(ui_widget_list); + + return ui_widget; +} + +DomWidget *QDesignerResource::saveWidget(QWizardPage *wizardPage, DomWidget *ui_parentWidget) +{ + DomWidget *ui_widget = QAbstractFormBuilder::createDom(wizardPage, ui_parentWidget, true); + QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), wizardPage); + // Save the page id (string) attribute, append to existing attributes + const QString pageIdPropertyName = QLatin1String(QWizardPagePropertySheet::pageIdProperty); + const int pageIdIndex = sheet->indexOf(pageIdPropertyName); + if (pageIdIndex != -1 && sheet->isChanged(pageIdIndex)) { + DomProperty *property = variantToDomProperty(this, wizardPage->metaObject(), pageIdPropertyName, sheet->property(pageIdIndex)); + Q_ASSERT(property); + property->elementString()->setAttributeNotr(QLatin1String("true")); + DomPropertyList attributes = ui_widget->elementAttribute(); + attributes.push_back(property); + ui_widget->setElementAttribute(attributes); + } + return ui_widget; +} + +// Do not save the 'currentTabName' properties of containers +static inline bool checkContainerProperty(const QWidget *w, const QString &propertyName) +{ + if (qobject_cast<const QToolBox *>(w)) + return QToolBoxWidgetPropertySheet::checkProperty(propertyName); + if (qobject_cast<const QTabWidget *>(w)) + return QTabWidgetPropertySheet::checkProperty(propertyName); + if (qobject_cast<const QStackedWidget *>(w)) + return QStackedWidgetPropertySheet::checkProperty(propertyName); + if (qobject_cast<const QMdiArea *>(w) || qobject_cast<const QWorkspace *>(w)) + return QMdiAreaPropertySheet::checkProperty(propertyName); + return true; +} + +bool QDesignerResource::checkProperty(QObject *obj, const QString &prop) const +{ + const QDesignerMetaObjectInterface *meta = core()->introspection()->metaObject(obj); + + const int pindex = meta->indexOfProperty(prop); + if (pindex != -1 && !(meta->property(pindex)->attributes(obj) & QDesignerMetaPropertyInterface::StoredAttribute)) + return false; + + if (prop == QLatin1String("objectName") || prop == QLatin1String("spacerName")) // ### don't store the property objectName + return false; + + QWidget *check_widget = 0; + if (obj->isWidgetType()) + check_widget = static_cast<QWidget*>(obj); + + if (check_widget && prop == QLatin1String("geometry")) { + if (check_widget == m_formWindow->mainContainer()) + return true; // Save although maincontainer is technically laid-out by embedding container + if (m_selected && m_selected == check_widget) + return true; + + return !LayoutInfo::isWidgetLaidout(core(), check_widget); + } + + if (check_widget && !checkContainerProperty(check_widget, prop)) + return false; + + if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), obj)) { + QDesignerDynamicPropertySheetExtension *dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(core()->extensionManager(), obj); + const int pindex = sheet->indexOf(prop); + if (sheet->isAttribute(pindex)) + return false; + + if (!dynamicSheet || !dynamicSheet->isDynamicProperty(pindex)) + return sheet->isChanged(pindex); + if (!sheet->isVisible(pindex)) + return false; + return true; + } + + return false; +} + +bool QDesignerResource::addItem(DomLayoutItem *ui_item, QLayoutItem *item, QLayout *layout) +{ + if (item->widget() == 0) { + return false; + } + + QGridLayout *grid = qobject_cast<QGridLayout*>(layout); + QBoxLayout *box = qobject_cast<QBoxLayout*>(layout); + + if (grid != 0) { + const int rowSpan = ui_item->hasAttributeRowSpan() ? ui_item->attributeRowSpan() : 1; + const int colSpan = ui_item->hasAttributeColSpan() ? ui_item->attributeColSpan() : 1; + grid->addWidget(item->widget(), ui_item->attributeRow(), ui_item->attributeColumn(), rowSpan, colSpan, item->alignment()); + return true; + } else if (box != 0) { + box->addItem(item); + return true; + } + + return QAbstractFormBuilder::addItem(ui_item, item, layout); +} + +bool QDesignerResource::addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget) +{ + core()->metaDataBase()->add(widget); // ensure the widget is in the meta database + + if (! QAbstractFormBuilder::addItem(ui_widget, widget, parentWidget) || qobject_cast<QMainWindow*> (parentWidget)) { + if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), parentWidget)) + container->addWidget(widget); + } + + if (QTabWidget *tabWidget = qobject_cast<QTabWidget*>(parentWidget)) { + const int tabIndex = tabWidget->count() - 1; + const int current = tabWidget->currentIndex(); + + tabWidget->setCurrentIndex(tabIndex); + + const QFormBuilderStrings &strings = QFormBuilderStrings::instance(); + + const DomPropertyHash attributes = propertyMap(ui_widget->elementAttribute()); + QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), parentWidget); + if (DomProperty *picon = attributes.value(strings.iconAttribute)) { + QVariant v = resourceBuilder()->loadResource(workingDirectory(), picon); + sheet->setProperty(sheet->indexOf(QLatin1String("currentTabIcon")), v); + } + if (DomProperty *ptext = attributes.value(strings.titleAttribute)) { + QVariant v = textBuilder()->loadText(ptext); + sheet->setProperty(sheet->indexOf(QLatin1String("currentTabText")), v); + } + if (DomProperty *ptext = attributes.value(strings.toolTipAttribute)) { + QVariant v = textBuilder()->loadText(ptext); + sheet->setProperty(sheet->indexOf(QLatin1String("currentTabToolTip")), v); + } + if (DomProperty *ptext = attributes.value(strings.whatsThisAttribute)) { + QVariant v = textBuilder()->loadText(ptext); + sheet->setProperty(sheet->indexOf(QLatin1String("currentTabWhatsThis")), v); + } + tabWidget->setCurrentIndex(current); + } else if (QToolBox *toolBox = qobject_cast<QToolBox*>(parentWidget)) { + const int itemIndex = toolBox->count() - 1; + const int current = toolBox->currentIndex(); + + toolBox->setCurrentIndex(itemIndex); + + const QFormBuilderStrings &strings = QFormBuilderStrings::instance(); + + const DomPropertyHash attributes = propertyMap(ui_widget->elementAttribute()); + QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), parentWidget); + if (DomProperty *picon = attributes.value(strings.iconAttribute)) { + QVariant v = resourceBuilder()->loadResource(workingDirectory(), picon); + sheet->setProperty(sheet->indexOf(QLatin1String("currentItemIcon")), v); + } + if (DomProperty *ptext = attributes.value(strings.labelAttribute)) { + QVariant v = textBuilder()->loadText(ptext); + sheet->setProperty(sheet->indexOf(QLatin1String("currentItemText")), v); + } + if (DomProperty *ptext = attributes.value(strings.toolTipAttribute)) { + QVariant v = textBuilder()->loadText(ptext); + sheet->setProperty(sheet->indexOf(QLatin1String("currentItemToolTip")), v); + } + toolBox->setCurrentIndex(current); + } + + return true; +} + +bool QDesignerResource::copy(QIODevice *dev, const FormBuilderClipboard &selection) +{ + m_copyWidget = true; + + DomUI *ui = copy(selection); + + m_laidout.clear(); + m_copyWidget = false; + + if (!ui) + return false; + + QXmlStreamWriter writer(dev); + writer.setAutoFormatting(true); + writer.setAutoFormattingIndent(1); + writer.writeStartDocument(); + ui->write(writer); + writer.writeEndDocument(); + delete ui; + return true; +} + +DomUI *QDesignerResource::copy(const FormBuilderClipboard &selection) +{ + if (selection.empty()) + return 0; + + m_copyWidget = true; + + DomWidget *ui_widget = new DomWidget(); + ui_widget->setAttributeName(QLatin1String(clipboardObjectName)); + bool hasItems = false; + // Widgets + if (!selection.m_widgets.empty()) { + QList<DomWidget*> ui_widget_list; + const int size = selection.m_widgets.size(); + for (int i=0; i< size; ++i) { + QWidget *w = selection.m_widgets.at(i); + m_selected = w; + DomWidget *ui_child = createDom(w, ui_widget); + m_selected = 0; + if (ui_child) + ui_widget_list.append(ui_child); + } + if (!ui_widget_list.empty()) { + ui_widget->setElementWidget(ui_widget_list); + hasItems = true; + } + } + // actions + if (!selection.m_actions.empty()) { + QList<DomAction*> domActions; + foreach(QAction* action, selection.m_actions) + if (DomAction *domAction = createDom(action)) + domActions += domAction; + if (!domActions.empty()) { + ui_widget-> setElementAction(domActions); + hasItems = true; + } + } + + m_laidout.clear(); + m_copyWidget = false; + + if (!hasItems) { + delete ui_widget; + return 0; + } + // UI + DomUI *ui = new DomUI(); + ui->setAttributeVersion(QLatin1String(currentUiVersion)); + ui->setElementWidget(ui_widget); + ui->setElementResources(saveResources(m_resourceBuilder->usedQrcFiles())); + if (DomCustomWidgets *cws = saveCustomWidgets()) + ui->setElementCustomWidgets(cws); + return ui; +} + +FormBuilderClipboard QDesignerResource::paste(DomUI *ui, QWidget *widgetParent, QObject *actionParent) +{ + QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem. + const int saved = m_isMainWidget; + m_isMainWidget = false; + + FormBuilderClipboard rc; + + // Widgets + const DomWidget *topLevel = ui->elementWidget(); + initialize(ui); + const QList<DomWidget*> domWidgets = topLevel->elementWidget(); + if (!domWidgets.empty()) { + const QPoint offset = m_formWindow->grid(); + foreach (DomWidget* domWidget, domWidgets) { + if (QWidget *w = create(domWidget, widgetParent)) { + w->move(w->pos() + offset); + // ### change the init properties of w + rc.m_widgets.append(w); + } + } + } + const QList<DomAction*> domActions = topLevel->elementAction(); + if (!domActions.empty()) + foreach (DomAction *domAction, domActions) + if (QAction *a = create(domAction, actionParent)) + rc.m_actions .append(a); + + m_isMainWidget = saved; + + if (QDesignerExtraInfoExtension *extra = qt_extension<QDesignerExtraInfoExtension*>(core()->extensionManager(), core())) + extra->loadUiExtraInfo(ui); + + createResources(ui->elementResources()); + + return rc; +} + +FormBuilderClipboard QDesignerResource::paste(QIODevice *dev, QWidget *widgetParent, QObject *actionParent) +{ + DomUI ui; + QXmlStreamReader reader(dev); + bool uiInitialized = false; + + const QString uiElement = QLatin1String("ui"); + while (!reader.atEnd()) { + if (reader.readNext() == QXmlStreamReader::StartElement) { + if (reader.name().compare(uiElement, Qt::CaseInsensitive)) { + ui.read(reader); + uiInitialized = true; + } else { + //: Parsing clipboard contents + reader.raiseError(QCoreApplication::translate("QDesignerResource", "Unexpected element <%1>").arg(reader.name().toString())); + } + } + } + if (reader.hasError()) { + //: Parsing clipboard contents + designerWarning(QCoreApplication::translate("QDesignerResource", "Error while pasting clipboard contents at line %1, column %2: %3") + .arg(reader.lineNumber()).arg(reader.columnNumber()) + .arg(reader.errorString())); + uiInitialized = false; + } else if (uiInitialized == false) { + //: Parsing clipboard contents + designerWarning(QCoreApplication::translate("QDesignerResource", "Error while pasting clipboard contents: The root element <ui> is missing.")); + } + + if (!uiInitialized) + return FormBuilderClipboard(); + + FormBuilderClipboard clipBoard = paste(&ui, widgetParent, actionParent); + + return clipBoard; +} + +void QDesignerResource::layoutInfo(DomLayout *layout, QObject *parent, int *margin, int *spacing) +{ + QAbstractFormBuilder::layoutInfo(layout, parent, margin, spacing); +} + +DomCustomWidgets *QDesignerResource::saveCustomWidgets() +{ + if (m_usedCustomWidgets.isEmpty()) + return 0; + + // We would like the list to be in order of the widget database indexes + // to ensure that base classes come first (nice optics) + QDesignerFormEditorInterface *core = m_formWindow->core(); + QDesignerWidgetDataBaseInterface *db = core->widgetDataBase(); + const bool isInternalWidgetDataBase = qobject_cast<const WidgetDataBase *>(db); + typedef QMap<int,DomCustomWidget*> OrderedDBIndexDomCustomWidgetMap; + OrderedDBIndexDomCustomWidgetMap orderedMap; + + const QString global = QLatin1String("global"); + foreach (QDesignerWidgetDataBaseItemInterface *item, m_usedCustomWidgets.keys()) { + const QString name = item->name(); + DomCustomWidget *custom_widget = new DomCustomWidget; + + custom_widget->setElementClass(name); + if (item->isContainer()) + custom_widget->setElementContainer(item->isContainer()); + + if (!item->includeFile().isEmpty()) { + DomHeader *header = new DomHeader; + const IncludeSpecification spec = includeSpecification(item->includeFile()); + header->setText(spec.first); + if (spec.second == IncludeGlobal) { + header->setAttributeLocation(global); + } + custom_widget->setElementHeader(header); + custom_widget->setElementExtends(item->extends()); + } + + if (isInternalWidgetDataBase) { + WidgetDataBaseItem *internalItem = static_cast<WidgetDataBaseItem *>(item); + const QStringList fakeSlots = internalItem->fakeSlots(); + const QStringList fakeSignals = internalItem->fakeSignals(); + if (!fakeSlots.empty() || !fakeSignals.empty()) { + DomSlots *domSlots = new DomSlots(); + domSlots->setElementSlot(fakeSlots); + domSlots->setElementSignal(fakeSignals); + custom_widget->setElementSlots(domSlots); + } + const QString addPageMethod = internalItem->addPageMethod(); + if (!addPageMethod.isEmpty()) + custom_widget->setElementAddPageMethod(addPageMethod); + } + + // Look up static per-class scripts of designer + if (DomScript *domScript = createScript(customWidgetScript(core, name), ScriptCustomWidgetPlugin)) + custom_widget->setElementScript(domScript); + + orderedMap.insert(db->indexOfClassName(name), custom_widget); + } + + DomCustomWidgets *customWidgets = new DomCustomWidgets; + customWidgets->setElementCustomWidget(orderedMap.values()); + return customWidgets; +} + +bool QDesignerResource::canCompressMargins(QObject *object) const +{ + if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), object)) { + if (qobject_cast<QLayout *>(object)) { + const int l = sheet->property(sheet->indexOf(QLatin1String("leftMargin"))).toInt(); + const int t = sheet->property(sheet->indexOf(QLatin1String("topMargin"))).toInt(); + const int r = sheet->property(sheet->indexOf(QLatin1String("rightMargin"))).toInt(); + const int b = sheet->property(sheet->indexOf(QLatin1String("bottomMargin"))).toInt(); + if (l == t && l == r && l == b) + return true; + } + } + return false; +} + +bool QDesignerResource::canCompressSpacings(QObject *object) const +{ + if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), object)) { + if (qobject_cast<QGridLayout *>(object)) { + const int h = sheet->property(sheet->indexOf(QLatin1String("horizontalSpacing"))).toInt(); + const int v = sheet->property(sheet->indexOf(QLatin1String("verticalSpacing"))).toInt(); + if (h == v) + return true; + } + } + return false; +} + +QList<DomProperty*> QDesignerResource::computeProperties(QObject *object) +{ + QList<DomProperty*> properties; + if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), object)) { + QDesignerDynamicPropertySheetExtension *dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(core()->extensionManager(), object); + const int count = sheet->count(); + QList<DomProperty *> marginProperties; + QList<DomProperty *> spacingProperties; + const bool compressMargins = canCompressMargins(object); + const bool compressSpacings = canCompressSpacings(object); + for (int index = 0; index < count; ++index) { + if (!sheet->isChanged(index) && (!dynamicSheet || !dynamicSheet->isDynamicProperty(index))) + continue; + + const QString propertyName = sheet->propertyName(index); + // Suppress windowModality in legacy forms that have it set on child widgets + if (propertyName == QLatin1String("windowModality") && !sheet->isVisible(index)) + continue; + + const QVariant value = sheet->property(index); + if (DomProperty *p = createProperty(object, propertyName, value)) { + if (compressMargins && (propertyName == QLatin1String("leftMargin") + || propertyName == QLatin1String("rightMargin") + || propertyName == QLatin1String("topMargin") + || propertyName == QLatin1String("bottomMargin"))) { + marginProperties.append(p); + } else if (compressSpacings && (propertyName == QLatin1String("horizontalSpacing") + || propertyName == QLatin1String("verticalSpacing"))) { + spacingProperties.append(p); + } else { + properties.append(p); + } + } + } + if (compressMargins) { + if (marginProperties.count() == 4) { // if we have 3 it means one is reset so we can't compress + DomProperty *marginProperty = marginProperties.at(0); + marginProperty->setAttributeName(QLatin1String("margin")); + properties.append(marginProperty); + delete marginProperties.at(1); + delete marginProperties.at(2); + delete marginProperties.at(3); + } else { + properties += marginProperties; + } + } + if (compressSpacings) { + if (spacingProperties.count() == 2) { + DomProperty *spacingProperty = spacingProperties.at(0); + spacingProperty->setAttributeName(QLatin1String("spacing")); + properties.append(spacingProperty); + delete spacingProperties.at(1); + } else { + properties += spacingProperties; + } + } + } + return properties; +} + +DomProperty *QDesignerResource::applyProperStdSetAttribute(QObject *object, const QString &propertyName, DomProperty *property) +{ + if (!property) + return 0; + + QExtensionManager *mgr = core()->extensionManager(); + if (const QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(mgr, object)) { + const QDesignerDynamicPropertySheetExtension *dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(mgr, object); + const QDesignerPropertySheet *designerSheet = qobject_cast<QDesignerPropertySheet*>(core()->extensionManager()->extension(object, Q_TYPEID(QDesignerPropertySheetExtension))); + const int index = sheet->indexOf(propertyName); + if ((dynamicSheet && dynamicSheet->isDynamicProperty(index)) || (designerSheet && designerSheet->isDefaultDynamicProperty(index))) + property->setAttributeStdset(0); + } + return property; +} + +// Optimistic check for a standard setter function +static inline bool hasSetter(QDesignerFormEditorInterface *core, QObject *object, const QString &propertyName) +{ + const QDesignerMetaObjectInterface *meta = core->introspection()->metaObject(object); + const int pindex = meta->indexOfProperty(propertyName); + if (pindex == -1) + return true; + return meta->property(pindex)->hasSetter(); +} + +DomProperty *QDesignerResource::createProperty(QObject *object, const QString &propertyName, const QVariant &value) +{ + if (!checkProperty(object, propertyName)) { + return 0; + } + + if (qVariantCanConvert<PropertySheetFlagValue>(value)) { + const PropertySheetFlagValue f = qVariantValue<PropertySheetFlagValue>(value); + const QString flagString = f.metaFlags.toString(f.value, DesignerMetaFlags::FullyQualified); + if (flagString.isEmpty()) + return 0; + + DomProperty *p = new DomProperty; + // check if we have a standard cpp set function + if (!hasSetter(core(), object, propertyName)) + p->setAttributeStdset(0); + p->setAttributeName(propertyName); + p->setElementSet(flagString); + return applyProperStdSetAttribute(object, propertyName, p); + } else if (qVariantCanConvert<PropertySheetEnumValue>(value)) { + const PropertySheetEnumValue e = qVariantValue<PropertySheetEnumValue>(value); + bool ok; + const QString id = e.metaEnum.toString(e.value, DesignerMetaEnum::FullyQualified, &ok); + if (!ok) + designerWarning(e.metaEnum.messageToStringFailed(e.value)); + if (id.isEmpty()) + return 0; + + DomProperty *p = new DomProperty; + // check if we have a standard cpp set function + if (!hasSetter(core(), object, propertyName)) + p->setAttributeStdset(0); + p->setAttributeName(propertyName); + p->setElementEnum(id); + return applyProperStdSetAttribute(object, propertyName, p); + } else if (qVariantCanConvert<PropertySheetStringValue>(value)) { + const PropertySheetStringValue strVal = qVariantValue<PropertySheetStringValue>(value); + DomProperty *p = new DomProperty; + if (!hasSetter(core(), object, propertyName)) + p->setAttributeStdset(0); + + p->setAttributeName(propertyName); + + saveStringProperty(p, strVal); + + return applyProperStdSetAttribute(object, propertyName, p); + } else if (qVariantCanConvert<PropertySheetKeySequenceValue>(value)) { + const PropertySheetKeySequenceValue keyVal = qVariantValue<PropertySheetKeySequenceValue>(value); + DomProperty *p = new DomProperty; + if (!hasSetter(core(), object, propertyName)) + p->setAttributeStdset(0); + + p->setAttributeName(propertyName); + + saveKeySequenceProperty(p, keyVal); + + return applyProperStdSetAttribute(object, propertyName, p); + } + + return applyProperStdSetAttribute(object, propertyName, QAbstractFormBuilder::createProperty(object, propertyName, value)); +} + +QStringList QDesignerResource::mergeWithLoadedPaths(const QStringList &paths) const +{ + QStringList newPaths = paths; +#ifdef OLD_RESOURCE_FORMAT + QStringList loadedPaths = m_resourceBuilder->loadedQrcFiles(); + QStringListIterator it(loadedPaths); + while (it.hasNext()) { + const QString path = it.next(); + if (!newPaths.contains(path)) + newPaths << path; + } +#endif + return newPaths; +} + + +void QDesignerResource::createResources(DomResources *resources) +{ + QStringList paths; + if (resources != 0) { + const QList<DomResource*> dom_include = resources->elementInclude(); + foreach (DomResource *res, dom_include) { + QString path = QDir::cleanPath(m_formWindow->absoluteDir().absoluteFilePath(res->attributeLocation())); + while (!QFile::exists(path)) { + QWidget *dialogParent = m_formWindow->core()->topLevel(); + const QString promptTitle = QApplication::translate("qdesigner_internal::QDesignerResource", "Loading qrc file", 0, QApplication::UnicodeUTF8); + const QString prompt = QApplication::translate("qdesigner_internal::QDesignerResource", "The specified qrc file <p><b>%1</b></p><p>could not be found. Do you want to update the file location?</p>", 0, QApplication::UnicodeUTF8).arg(path); + + const QMessageBox::StandardButton answer = core()->dialogGui()->message(dialogParent, QDesignerDialogGuiInterface::ResourceLoadFailureMessage, + QMessageBox::Warning, promptTitle, prompt, QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes); + if (answer == QMessageBox::Yes) { + const QFileInfo fi(path); + const QString fileDialogTitle = QApplication::translate("qdesigner_internal::QDesignerResource", "New location for %1", 0, QApplication::UnicodeUTF8).arg(fi.fileName()); + const QString fileDialogPattern = QApplication::translate("qdesigner_internal::QDesignerResource", "Resource files (*.qrc)", 0, QApplication::UnicodeUTF8); + path = core()->dialogGui()->getOpenFileName(dialogParent, fileDialogTitle, fi.absolutePath(), fileDialogPattern); + if (path.isEmpty()) + break; + } else { + break; + } + } + if (!path.isEmpty()) { + paths << path; + m_formWindow->addResourceFile(path); + } + } + } + +#ifdef OLD_RESOURCE_FORMAT + paths = mergeWithLoadedPaths(paths); +#endif + + QtResourceSet *resourceSet = m_formWindow->resourceSet(); + if (resourceSet) { + QStringList oldPaths = resourceSet->activeQrcPaths(); + QStringList newPaths = oldPaths; + QStringListIterator it(paths); + while (it.hasNext()) { + const QString path = it.next(); + if (!newPaths.contains(path)) + newPaths << path; + } + resourceSet->activateQrcPaths(newPaths); + } else { + resourceSet = m_formWindow->core()->resourceModel()->addResourceSet(paths); + m_formWindow->setResourceSet(resourceSet); + QObject::connect(m_formWindow->core()->resourceModel(), SIGNAL(resourceSetActivated(QtResourceSet *, bool)), + m_formWindow, SLOT(resourceSetActivated(QtResourceSet *, bool))); + } +} + +DomResources *QDesignerResource::saveResources() +{ + QStringList paths; + if (m_formWindow->saveResourcesBehaviour() == FormWindowBase::SaveAll) { + QtResourceSet *resourceSet = m_formWindow->resourceSet(); + QList<DomResource*> dom_include; + if (resourceSet) + paths = resourceSet->activeQrcPaths(); + } else if (m_formWindow->saveResourcesBehaviour() == FormWindowBase::SaveOnlyUsedQrcFiles) { + paths = m_resourceBuilder->usedQrcFiles(); + } + + return saveResources(paths); +} + +DomResources *QDesignerResource::saveResources(const QStringList &qrcPaths) +{ + QtResourceSet *resourceSet = m_formWindow->resourceSet(); + QList<DomResource*> dom_include; + if (resourceSet) { + const QStringList activePaths = resourceSet->activeQrcPaths(); + foreach (QString path, activePaths) { + if (qrcPaths.contains(path)) { + DomResource *dom_res = new DomResource; + QString conv_path = path; + if (m_resourceBuilder->isSaveRelative()) + conv_path = m_formWindow->absoluteDir().relativeFilePath(path); + dom_res->setAttributeLocation(conv_path.replace(QDir::separator(), QLatin1Char('/'))); + dom_include.append(dom_res); + } + } + } + + DomResources *dom_resources = new DomResources; + dom_resources->setElementInclude(dom_include); + + return dom_resources; +} + +DomAction *QDesignerResource::createDom(QAction *action) +{ + if (!core()->metaDataBase()->item(action) || action->menu()) + return 0; + + return QAbstractFormBuilder::createDom(action); +} + +DomActionGroup *QDesignerResource::createDom(QActionGroup *actionGroup) +{ + if (core()->metaDataBase()->item(actionGroup) != 0) { + return QAbstractFormBuilder::createDom(actionGroup); + } + + return 0; +} + +QAction *QDesignerResource::create(DomAction *ui_action, QObject *parent) +{ + if (QAction *action = QAbstractFormBuilder::create(ui_action, parent)) { + core()->metaDataBase()->add(action); + return action; + } + + return 0; +} + +QActionGroup *QDesignerResource::create(DomActionGroup *ui_action_group, QObject *parent) +{ + if (QActionGroup *actionGroup = QAbstractFormBuilder::create(ui_action_group, parent)) { + core()->metaDataBase()->add(actionGroup); + return actionGroup; + } + + return 0; +} + +DomActionRef *QDesignerResource::createActionRefDom(QAction *action) +{ + if (!core()->metaDataBase()->item(action) + || (!action->isSeparator() && !action->menu() && action->objectName().isEmpty())) + return 0; + + return QAbstractFormBuilder::createActionRefDom(action); +} + +void QDesignerResource::addMenuAction(QAction *action) +{ + core()->metaDataBase()->add(action); +} + +QAction *QDesignerResource::createAction(QObject *parent, const QString &name) +{ + if (QAction *action = QAbstractFormBuilder::createAction(parent, name)) { + core()->metaDataBase()->add(action); + return action; + } + + return 0; +} + +QActionGroup *QDesignerResource::createActionGroup(QObject *parent, const QString &name) +{ + if (QActionGroup *actionGroup = QAbstractFormBuilder::createActionGroup(parent, name)) { + core()->metaDataBase()->add(actionGroup); + return actionGroup; + } + + return 0; +} + +/* Apply the attributes to a widget via property sheet where appropriate, + * that is, the sheet handles attributive fake properties */ +void QDesignerResource::applyAttributesToPropertySheet(const DomWidget *ui_widget, QWidget *widget) +{ + const DomPropertyList attributes = ui_widget->elementAttribute(); + if (attributes.empty()) + return; + QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(m_formWindow->core()->extensionManager(), widget); + const DomPropertyList::const_iterator acend = attributes.constEnd(); + for (DomPropertyList::const_iterator it = attributes.constBegin(); it != acend; ++it) { + const QString name = (*it)->attributeName(); + const int index = sheet->indexOf(name); + if (index == -1) { + const QString msg = QString::fromUtf8("Unable to apply attributive property '%1' to '%2'. It does not exist.").arg(name, widget->objectName()); + designerWarning(msg); + } else { + sheet->setProperty(index, domPropertyToVariant(this, widget->metaObject(), *it)); + sheet->setChanged(index, true); + } + } +} + +void QDesignerResource::loadExtraInfo(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget) +{ + QAbstractFormBuilder::loadExtraInfo(ui_widget, widget, parentWidget); + // Apply the page id attribute of a QWizardPage (which is an attributive fake property) + if (qobject_cast<const QWizardPage*>(widget)) + applyAttributesToPropertySheet(ui_widget, widget); +} + +// Add user defined scripts (dialog box) belonging to QWidget to DomWidget. +void QDesignerResource::addUserDefinedScripts(QWidget *w, DomWidget *ui_widget) +{ + QDesignerFormEditorInterface *core = m_formWindow->core(); + DomScripts domScripts = ui_widget->elementScript(); + // Look up user-defined scripts of designer + if (const qdesigner_internal::MetaDataBase *metaDataBase = qobject_cast<const qdesigner_internal::MetaDataBase *>(core->metaDataBase())) { + if (const qdesigner_internal::MetaDataBaseItem *metaItem = metaDataBase->metaDataBaseItem(w)) { + addScript(metaItem->script(), ScriptDesigner, domScripts); + } + } + if (!domScripts.empty()) + ui_widget->setElementScript(domScripts); +} +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/qdesigner_resource.h b/tools/designer/src/components/formeditor/qdesigner_resource.h new file mode 100644 index 0000000..3d6a842 --- /dev/null +++ b/tools/designer/src/components/formeditor/qdesigner_resource.h @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDESIGNER_RESOURCE_H +#define QDESIGNER_RESOURCE_H + +#include "formeditor_global.h" +#include "qsimpleresource_p.h" + +#include <QtCore/QHash> +#include <QtCore/QStack> +#include <QtCore/QList> + +QT_BEGIN_NAMESPACE + +class DomCustomWidget; +class DomCustomWidgets; +class DomResource; + +class QDesignerContainerExtension; +class QDesignerFormEditorInterface; +class QDesignerCustomWidgetInterface; +class QDesignerWidgetDataBaseItemInterface; + +class QTabWidget; +class QStackedWidget; +class QToolBox; +class QToolBar; +class QTreeView; +class QTableView; +class QDesignerDockWidget; +class QLayoutWidget; +class QWizardPage; + +namespace qdesigner_internal { + +class FormWindow; + +class QT_FORMEDITOR_EXPORT QDesignerResource : public QEditorFormBuilder +{ +public: + explicit QDesignerResource(FormWindow *fw); + virtual ~QDesignerResource(); + + virtual void save(QIODevice *dev, QWidget *widget); + + virtual bool copy(QIODevice *dev, const FormBuilderClipboard &selection); + virtual DomUI *copy(const FormBuilderClipboard &selection); + + virtual FormBuilderClipboard paste(DomUI *ui, QWidget *widgetParent, QObject *actionParent = 0); + virtual FormBuilderClipboard paste(QIODevice *dev, QWidget *widgetParent, QObject *actionParent = 0); + + bool saveRelative() const; + void setSaveRelative(bool relative); + + virtual QWidget *load(QIODevice *dev, QWidget *parentWidget = 0); + +protected: + using QEditorFormBuilder::create; + using QEditorFormBuilder::createDom; + + virtual void saveDom(DomUI *ui, QWidget *widget); + virtual QWidget *create(DomUI *ui, QWidget *parentWidget); + virtual QWidget *create(DomWidget *ui_widget, QWidget *parentWidget); + virtual QLayout *create(DomLayout *ui_layout, QLayout *layout, QWidget *parentWidget); + virtual QLayoutItem *create(DomLayoutItem *ui_layoutItem, QLayout *layout, QWidget *parentWidget); + virtual void applyProperties(QObject *o, const QList<DomProperty*> &properties); + virtual QList<DomProperty*> computeProperties(QObject *obj); + virtual DomProperty *createProperty(QObject *object, const QString &propertyName, const QVariant &value); + + virtual QWidget *createWidget(const QString &widgetName, QWidget *parentWidget, const QString &name); + virtual QLayout *createLayout(const QString &layoutName, QObject *parent, const QString &name); + virtual void createCustomWidgets(DomCustomWidgets *); + virtual void createResources(DomResources*); + virtual void applyTabStops(QWidget *widget, DomTabStops *tabStops); + + virtual bool addItem(DomLayoutItem *ui_item, QLayoutItem *item, QLayout *layout); + virtual bool addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget); + + virtual DomWidget *createDom(QWidget *widget, DomWidget *ui_parentWidget, bool recursive = true); + virtual DomLayout *createDom(QLayout *layout, DomLayout *ui_layout, DomWidget *ui_parentWidget); + virtual DomLayoutItem *createDom(QLayoutItem *item, DomLayout *ui_layout, DomWidget *ui_parentWidget); + + virtual QAction *create(DomAction *ui_action, QObject *parent); + virtual QActionGroup *create(DomActionGroup *ui_action_group, QObject *parent); + virtual void addMenuAction(QAction *action); + + virtual DomAction *createDom(QAction *action); + virtual DomActionGroup *createDom(QActionGroup *actionGroup); + virtual DomActionRef *createActionRefDom(QAction *action); + + virtual QAction *createAction(QObject *parent, const QString &name); + virtual QActionGroup *createActionGroup(QObject *parent, const QString &name); + + virtual bool checkProperty(QObject *obj, const QString &prop) const; + + DomWidget *saveWidget(QTabWidget *widget, DomWidget *ui_parentWidget); + DomWidget *saveWidget(QStackedWidget *widget, DomWidget *ui_parentWidget); + DomWidget *saveWidget(QToolBox *widget, DomWidget *ui_parentWidget); + DomWidget *saveWidget(QWidget *widget, QDesignerContainerExtension *container, DomWidget *ui_parentWidget); + DomWidget *saveWidget(QToolBar *toolBar, DomWidget *ui_parentWidget); + DomWidget *saveWidget(QDesignerDockWidget *dockWidget, DomWidget *ui_parentWidget); + DomWidget *saveWidget(QTreeView *treeView, DomWidget *ui_parentWidget); + DomWidget *saveWidget(QTableView *tableView, DomWidget *ui_parentWidget); + DomWidget *saveWidget(QWizardPage *wizardPage, DomWidget *ui_parentWidget); + + virtual DomCustomWidgets *saveCustomWidgets(); + virtual DomTabStops *saveTabStops(); + virtual DomResources *saveResources(); + + virtual void layoutInfo(DomLayout *layout, QObject *parent, int *margin, int *spacing); + + virtual void loadExtraInfo(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget); + + void changeObjectName(QObject *o, QString name); + DomProperty *applyProperStdSetAttribute(QObject *object, const QString &propertyName, DomProperty *property); + +private: + void addUserDefinedScripts(QWidget *w, DomWidget *ui_widget); + DomResources *saveResources(const QStringList &qrcPaths); + bool canCompressMargins(QObject *object) const; + bool canCompressSpacings(QObject *object) const; + QStringList mergeWithLoadedPaths(const QStringList &paths) const; + void applyAttributesToPropertySheet(const DomWidget *ui_widget, QWidget *widget); + + typedef QList<DomCustomWidget*> DomCustomWidgetList; + void addCustomWidgetsToWidgetDatabase(DomCustomWidgetList& list); + FormWindow *m_formWindow; + bool m_isMainWidget; + QHash<QString, QString> m_internal_to_qt; + QHash<QString, QString> m_qt_to_internal; + QStack<QLayout*> m_chain; + QHash<QDesignerWidgetDataBaseItemInterface*, bool> m_usedCustomWidgets; + int m_topLevelSpacerCount; + bool m_copyWidget; + QWidget *m_selected; + class QDesignerResourceBuilder *m_resourceBuilder; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // QDESIGNER_RESOURCE_H diff --git a/tools/designer/src/components/formeditor/qlayoutwidget_propertysheet.cpp b/tools/designer/src/components/formeditor/qlayoutwidget_propertysheet.cpp new file mode 100644 index 0000000..e3e4a97 --- /dev/null +++ b/tools/designer/src/components/formeditor/qlayoutwidget_propertysheet.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlayoutwidget_propertysheet.h" +#include "qlayout_widget_p.h" +#include "formwindow.h" +#include "formeditor.h" + +#include <QtDesigner/QExtensionManager> + +#include <QtGui/QLayout> + +QT_BEGIN_NAMESPACE + +using namespace qdesigner_internal; + +QLayoutWidgetPropertySheet::QLayoutWidgetPropertySheet(QLayoutWidget *object, QObject *parent) + : QDesignerPropertySheet(object, parent) +{ + clearFakeProperties(); +} + +QLayoutWidgetPropertySheet::~QLayoutWidgetPropertySheet() +{ +} + +bool QLayoutWidgetPropertySheet::isVisible(int index) const +{ + static const QString layoutPropertyGroup = QLatin1String("Layout"); + if (propertyGroup(index) == layoutPropertyGroup) + return QDesignerPropertySheet::isVisible(index); + return false; +} + +void QLayoutWidgetPropertySheet::setProperty(int index, const QVariant &value) +{ + QDesignerPropertySheet::setProperty(index, value); +} + +bool QLayoutWidgetPropertySheet::dynamicPropertiesAllowed() const +{ + return false; +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/qlayoutwidget_propertysheet.h b/tools/designer/src/components/formeditor/qlayoutwidget_propertysheet.h new file mode 100644 index 0000000..e96adaf --- /dev/null +++ b/tools/designer/src/components/formeditor/qlayoutwidget_propertysheet.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLAYOUTWIDGET_PROPERTYSHEET_H +#define QLAYOUTWIDGET_PROPERTYSHEET_H + +#include <qdesigner_propertysheet_p.h> +#include <extensionfactory_p.h> +#include <qlayout_widget_p.h> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +class QLayoutWidgetPropertySheet: public QDesignerPropertySheet +{ + Q_OBJECT + Q_INTERFACES(QDesignerPropertySheetExtension) +public: + explicit QLayoutWidgetPropertySheet(QLayoutWidget *object, QObject *parent = 0); + virtual ~QLayoutWidgetPropertySheet(); + + virtual void setProperty(int index, const QVariant &value); + virtual bool isVisible(int index) const; + + virtual bool dynamicPropertiesAllowed() const; +}; + +typedef QDesignerPropertySheetFactory<QLayoutWidget, QLayoutWidgetPropertySheet> QLayoutWidgetPropertySheetFactory; +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // QLAYOUTWIDGET_PROPERTYSHEET_H diff --git a/tools/designer/src/components/formeditor/qmainwindow_container.cpp b/tools/designer/src/components/formeditor/qmainwindow_container.cpp new file mode 100644 index 0000000..7fd21d1 --- /dev/null +++ b/tools/designer/src/components/formeditor/qmainwindow_container.cpp @@ -0,0 +1,199 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmainwindow_container.h" +#include "qdesigner_toolbar_p.h" +#include "formwindow.h" + +#include <QtCore/qdebug.h> + +#include <QtGui/QLayout> +#include <QtGui/QMenuBar> +#include <QtGui/QToolBar> +#include <QtGui/QStatusBar> +#include <QtGui/QDockWidget> + +QT_BEGIN_NAMESPACE + +using namespace qdesigner_internal; + +QMainWindowContainer::QMainWindowContainer(QMainWindow *widget, QObject *parent) + : QObject(parent), + m_mainWindow(widget) +{ +} + +int QMainWindowContainer::count() const +{ + return m_widgets.count(); +} + +QWidget *QMainWindowContainer::widget(int index) const +{ + if (index == -1) + return 0; + + return m_widgets.at(index); +} + +int QMainWindowContainer::currentIndex() const +{ + return m_mainWindow->centralWidget() ? 0 : -1; +} + +void QMainWindowContainer::setCurrentIndex(int index) +{ + Q_UNUSED(index); +} + + +namespace { + // Pair of <area,break_before> + typedef QPair<Qt::ToolBarArea,bool> ToolBarData; + + ToolBarData toolBarData(QToolBar *me) { + const QMainWindow *mw = qobject_cast<const QMainWindow*>(me->parentWidget()); + if (!mw || !mw->layout() || mw->layout()->indexOf(me) == -1) + return ToolBarData(Qt::TopToolBarArea,false); + return ToolBarData(mw->toolBarArea(me), mw->toolBarBreak(me)); + } + +Qt::DockWidgetArea dockWidgetArea(QDockWidget *me) +{ + if (const QMainWindow *mw = qobject_cast<const QMainWindow*>(me->parentWidget())) { + // Make sure that me is actually managed by mw, otherwise + // QMainWindow::dockWidgetArea() will be VERY upset + QList<QLayout*> candidates; + if (mw->layout()) { + candidates.append(mw->layout()); + candidates += qFindChildren<QLayout*>(mw->layout()); + } + foreach (QLayout *l, candidates) { + if (l->indexOf(me) != -1) { + return mw->dockWidgetArea(me); + } + } + } + return Qt::LeftDockWidgetArea; +} +} + +void QMainWindowContainer::addWidget(QWidget *widget) +{ + // remove all the occurrences of widget + m_widgets.removeAll(widget); + + // the + if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) { + m_widgets.append(widget); + const ToolBarData data = toolBarData(toolBar); + m_mainWindow->addToolBar(data.first, toolBar); + if (data.second) m_mainWindow->insertToolBarBreak(toolBar); + toolBar->show(); + } + + else if (QMenuBar *menuBar = qobject_cast<QMenuBar*>(widget)) { + if (menuBar != m_mainWindow->menuBar()) + m_mainWindow->setMenuBar(menuBar); + + m_widgets.append(widget); + menuBar->show(); + } + + else if (QStatusBar *statusBar = qobject_cast<QStatusBar*>(widget)) { + if (statusBar != m_mainWindow->statusBar()) + m_mainWindow->setStatusBar(statusBar); + + m_widgets.append(widget); + statusBar->show(); + } + + else if (QDockWidget *dockWidget = qobject_cast<QDockWidget*>(widget)) { + m_widgets.append(widget); + m_mainWindow->addDockWidget(dockWidgetArea(dockWidget), dockWidget); + dockWidget->show(); + + if (FormWindow *fw = FormWindow::findFormWindow(m_mainWindow)) { + fw->manageWidget(widget); + } + } + + else if (widget) { + m_widgets.prepend(widget); + + if (widget != m_mainWindow->centralWidget()) { + // note that qmainwindow will delete the current central widget if you + // call setCentralWidget(), we end up with dangeling pointers in m_widgets list + m_widgets.removeAll(m_mainWindow->centralWidget()); + + widget->setParent(m_mainWindow); + m_mainWindow->setCentralWidget(widget); + } + } +} + +void QMainWindowContainer::insertWidget(int index, QWidget *widget) +{ + Q_UNUSED(index); + + addWidget(widget); +} + +void QMainWindowContainer::remove(int index) +{ + QWidget *widget = m_widgets.at(index); + if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) { + m_mainWindow->removeToolBar(toolBar); + } else if (QMenuBar *menuBar = qobject_cast<QMenuBar*>(widget)) { + menuBar->hide(); + menuBar->setParent(0); + m_mainWindow->setMenuBar(0); + } else if (QStatusBar *statusBar = qobject_cast<QStatusBar*>(widget)) { + statusBar->hide(); + statusBar->setParent(0); + m_mainWindow->setStatusBar(0); + } else if (QDockWidget *dockWidget = qobject_cast<QDockWidget*>(widget)) { + m_mainWindow->removeDockWidget(dockWidget); + } + m_widgets.removeAt(index); +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/qmainwindow_container.h b/tools/designer/src/components/formeditor/qmainwindow_container.h new file mode 100644 index 0000000..aaf942f --- /dev/null +++ b/tools/designer/src/components/formeditor/qmainwindow_container.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMAINWINDOW_CONTAINER_H +#define QMAINWINDOW_CONTAINER_H + +#include <QtDesigner/QDesignerContainerExtension> +#include <QtDesigner/QExtensionFactory> + +#include <extensionfactory_p.h> + +#include <QtGui/QMainWindow> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +class QMainWindowContainer: public QObject, public QDesignerContainerExtension +{ + Q_OBJECT + Q_INTERFACES(QDesignerContainerExtension) +public: + explicit QMainWindowContainer(QMainWindow *widget, QObject *parent = 0); + + virtual int count() const; + virtual QWidget *widget(int index) const; + virtual int currentIndex() const; + virtual void setCurrentIndex(int index); + virtual void addWidget(QWidget *widget); + virtual void insertWidget(int index, QWidget *widget); + virtual void remove(int index); + +private: + QMainWindow *m_mainWindow; + QList<QWidget*> m_widgets; +}; + +typedef ExtensionFactory<QDesignerContainerExtension, QMainWindow, QMainWindowContainer> QMainWindowContainerFactory; +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // QMAINWINDOW_CONTAINER_H diff --git a/tools/designer/src/components/formeditor/qmdiarea_container.cpp b/tools/designer/src/components/formeditor/qmdiarea_container.cpp new file mode 100644 index 0000000..fdeef03 --- /dev/null +++ b/tools/designer/src/components/formeditor/qmdiarea_container.cpp @@ -0,0 +1,280 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmdiarea_container.h" + +#include <QtDesigner/QExtensionManager> +#include <QtDesigner/QDesignerFormEditorInterface> + +#include <QtGui/QMdiArea> +#include <QtGui/QMdiSubWindow> +#include <QtGui/QApplication> +#include <QtCore/QDebug> +#include <QtCore/QHash> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +QMdiAreaContainer::QMdiAreaContainer(QMdiArea *widget, QObject *parent) + : QObject(parent), + m_mdiArea(widget) +{ +} + +int QMdiAreaContainer::count() const +{ + return m_mdiArea->subWindowList(QMdiArea::CreationOrder).count(); +} + +QWidget *QMdiAreaContainer::widget(int index) const +{ + if (index < 0) + return 0; + return m_mdiArea->subWindowList(QMdiArea::CreationOrder).at(index)->widget(); +} + +int QMdiAreaContainer::currentIndex() const +{ + if (QMdiSubWindow *sub = m_mdiArea->activeSubWindow()) + return m_mdiArea->subWindowList(QMdiArea::CreationOrder).indexOf(sub); + return -1; +} + +void QMdiAreaContainer::setCurrentIndex(int index) +{ + if (index < 0) { + qDebug() << "** WARNING Attempt to QMdiAreaContainer::setCurrentIndex(-1)"; + return; + } + QMdiSubWindow *frame = m_mdiArea->subWindowList(QMdiArea::CreationOrder).at(index); + m_mdiArea->setActiveSubWindow(frame); +} + +void QMdiAreaContainer::addWidget(QWidget *widget) +{ + QMdiSubWindow *frame = m_mdiArea->addSubWindow(widget, Qt::Window); + frame->show(); + m_mdiArea->cascadeSubWindows(); + positionNewMdiChild(m_mdiArea, frame); +} + +// Semi-smart positioning of new windows: Make child fill the whole MDI window below +// cascaded other windows +void QMdiAreaContainer::positionNewMdiChild(const QWidget *area, QWidget *mdiChild) +{ + enum { MinSize = 20 }; + const QPoint pos = mdiChild->pos(); + const QSize areaSize = area->size(); + switch (QApplication::layoutDirection()) { + case Qt::LeftToRight: { + const QSize fullSize = QSize(areaSize.width() - pos.x(), areaSize.height() - pos.y()); + if (fullSize.width() > MinSize && fullSize.height() > MinSize) + mdiChild->resize(fullSize); + } + break; + case Qt::RightToLeft: { + const QSize fullSize = QSize(pos.x() + mdiChild->width(), areaSize.height() - pos.y()); + if (fullSize.width() > MinSize && fullSize.height() > MinSize) { + mdiChild->move(0, pos.y()); + mdiChild->resize(fullSize); + } + } + break; + } +} + +void QMdiAreaContainer::insertWidget(int, QWidget *widget) +{ + addWidget(widget); +} + +void QMdiAreaContainer::remove(int index) +{ + QList<QMdiSubWindow *> subWins = m_mdiArea->subWindowList(QMdiArea::CreationOrder); + if (index >= 0 && index < subWins.size()) { + QMdiSubWindow *f = subWins.at(index); + m_mdiArea->removeSubWindow(f->widget()); + delete f; + } +} + +// ---------- MdiAreaPropertySheet, creates fake properties: +// 1) window name (object name of child) +// 2) title (windowTitle of child). + +static const char *subWindowTitleC = "activeSubWindowTitle"; +static const char *subWindowNameC = "activeSubWindowName"; + +QMdiAreaPropertySheet::QMdiAreaPropertySheet(QWidget *mdiArea, QObject *parent) : + QDesignerPropertySheet(mdiArea, parent), + m_windowTitleProperty(QLatin1String("windowTitle")) +{ + createFakeProperty(QLatin1String(subWindowNameC), QString()); + createFakeProperty(QLatin1String(subWindowTitleC), QString()); +} + +QMdiAreaPropertySheet::MdiAreaProperty QMdiAreaPropertySheet::mdiAreaProperty(const QString &name) +{ + typedef QHash<QString, MdiAreaProperty> MdiAreaPropertyHash; + static MdiAreaPropertyHash mdiAreaPropertyHash; + if (mdiAreaPropertyHash.empty()) { + mdiAreaPropertyHash.insert(QLatin1String(subWindowNameC), MdiAreaSubWindowName); + mdiAreaPropertyHash.insert(QLatin1String(subWindowTitleC), MdiAreaSubWindowTitle); + } + return mdiAreaPropertyHash.value(name,MdiAreaNone); +} + +void QMdiAreaPropertySheet::setProperty(int index, const QVariant &value) +{ + switch (mdiAreaProperty(propertyName(index))) { + case MdiAreaSubWindowName: + if (QWidget *w = currentWindow()) + w->setObjectName(value.toString()); + break; + case MdiAreaSubWindowTitle: // Forward to window title of subwindow + if (QDesignerPropertySheetExtension *cws = currentWindowSheet()) { + const int index = cws->indexOf(m_windowTitleProperty); + cws->setProperty(index, value); + cws->setChanged(index, true); + } + break; + default: + QDesignerPropertySheet::setProperty(index, value); + break; + } +} + +bool QMdiAreaPropertySheet::reset(int index) +{ + bool rc = true; + switch (mdiAreaProperty(propertyName(index))) { + case MdiAreaSubWindowName: + setProperty(index, QVariant(QString())); + setChanged(index, false); + break; + case MdiAreaSubWindowTitle: // Forward to window title of subwindow + if (QDesignerPropertySheetExtension *cws = currentWindowSheet()) { + const int index = cws->indexOf(m_windowTitleProperty); + rc = cws->reset(index); + } + break; + default: + rc = QDesignerPropertySheet::reset(index); + break; + } + return rc; +} + +QVariant QMdiAreaPropertySheet::property(int index) const +{ + switch (mdiAreaProperty(propertyName(index))) { + case MdiAreaSubWindowName: + if (QWidget *w = currentWindow()) + return w->objectName(); + return QVariant(QString()); + case MdiAreaSubWindowTitle: + if (QWidget *w = currentWindow()) + return w->windowTitle(); + return QVariant(QString()); + case MdiAreaNone: + break; + } + return QDesignerPropertySheet::property(index); +} + +bool QMdiAreaPropertySheet::isEnabled(int index) const +{ + switch (mdiAreaProperty(propertyName(index))) { + case MdiAreaSubWindowName: + case MdiAreaSubWindowTitle: + return currentWindow() != 0; + case MdiAreaNone: + break; + } + return QDesignerPropertySheet::isEnabled(index); +} + +bool QMdiAreaPropertySheet::isChanged(int index) const +{ + bool rc = false; + switch (mdiAreaProperty(propertyName(index))) { + case MdiAreaSubWindowName: + rc = currentWindow() != 0; + break; + case MdiAreaSubWindowTitle: + if (QDesignerPropertySheetExtension *cws = currentWindowSheet()) { + const int index = cws->indexOf(m_windowTitleProperty); + rc = cws->isChanged(index); + } + break; + default: + rc = QDesignerPropertySheet::isChanged(index); + break; + } + return rc; +} + +QWidget *QMdiAreaPropertySheet::currentWindow() const +{ + if (const QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), object())) { + const int ci = c->currentIndex(); + if (ci < 0) + return 0; + return c->widget(ci); + } + return 0; +} + +QDesignerPropertySheetExtension *QMdiAreaPropertySheet::currentWindowSheet() const +{ + QWidget *cw = currentWindow(); + if (cw == 0) + return 0; + return qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), cw); +} + +bool QMdiAreaPropertySheet::checkProperty(const QString &propertyName) +{ + return mdiAreaProperty(propertyName) == MdiAreaNone; +} +} +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/qmdiarea_container.h b/tools/designer/src/components/formeditor/qmdiarea_container.h new file mode 100644 index 0000000..462c11f --- /dev/null +++ b/tools/designer/src/components/formeditor/qmdiarea_container.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMDIAREA_CONTAINER_H +#define QMDIAREA_CONTAINER_H + +#include <QtDesigner/QDesignerContainerExtension> + + +#include <qdesigner_propertysheet_p.h> +#include <extensionfactory_p.h> + +#include <QtGui/QMdiArea> +#include <QtGui/QWorkspace> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +// Container for QMdiArea +class QMdiAreaContainer: public QObject, public QDesignerContainerExtension +{ + Q_OBJECT + Q_INTERFACES(QDesignerContainerExtension) +public: + explicit QMdiAreaContainer(QMdiArea *widget, QObject *parent = 0); + + virtual int count() const; + virtual QWidget *widget(int index) const; + virtual int currentIndex() const; + virtual void setCurrentIndex(int index); + virtual void addWidget(QWidget *widget); + virtual void insertWidget(int index, QWidget *widget); + virtual void remove(int index); + + // Semismart positioning of a new MDI child after cascading + static void positionNewMdiChild(const QWidget *area, QWidget *mdiChild); + +private: + QMdiArea *m_mdiArea; +}; + +// PropertySheet for QMdiArea: Fakes window title and name. +// Also works for a QWorkspace as it relies on the container extension. + +class QMdiAreaPropertySheet: public QDesignerPropertySheet +{ + Q_OBJECT + Q_INTERFACES(QDesignerPropertySheetExtension) +public: + explicit QMdiAreaPropertySheet(QWidget *mdiArea, QObject *parent = 0); + + virtual void setProperty(int index, const QVariant &value); + virtual bool reset(int index); + virtual bool isEnabled(int index) const; + virtual bool isChanged(int index) const; + virtual QVariant property(int index) const; + + // Check whether the property is to be saved. Returns false for the page + // properties (as the property sheet has no concept of 'stored') + static bool checkProperty(const QString &propertyName); + +private: + const QString m_windowTitleProperty; + QWidget *currentWindow() const; + QDesignerPropertySheetExtension *currentWindowSheet() const; + + enum MdiAreaProperty { MdiAreaSubWindowName, MdiAreaSubWindowTitle, MdiAreaNone }; + static MdiAreaProperty mdiAreaProperty(const QString &name); +}; + +// Factories + +typedef ExtensionFactory<QDesignerContainerExtension, QMdiArea, QMdiAreaContainer> QMdiAreaContainerFactory; +typedef QDesignerPropertySheetFactory<QMdiArea, QMdiAreaPropertySheet> QMdiAreaPropertySheetFactory; +typedef QDesignerPropertySheetFactory<QWorkspace, QMdiAreaPropertySheet> QWorkspacePropertySheetFactory; +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // QMDIAREA_CONTAINER_H diff --git a/tools/designer/src/components/formeditor/qtbrushmanager.cpp b/tools/designer/src/components/formeditor/qtbrushmanager.cpp new file mode 100644 index 0000000..c28c6b9 --- /dev/null +++ b/tools/designer/src/components/formeditor/qtbrushmanager.cpp @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtbrushmanager.h" +#include <QtGui/QPixmap> +#include <QtGui/QPainter> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +class QtBrushManagerPrivate +{ + QtBrushManager *q_ptr; + Q_DECLARE_PUBLIC(QtBrushManager) +public: + QMap<QString, QBrush> theBrushMap; + QString theCurrentBrush; +}; + +QtBrushManager::QtBrushManager(QObject *parent) + : QDesignerBrushManagerInterface(parent) +{ + d_ptr = new QtBrushManagerPrivate; + d_ptr->q_ptr = this; + +} + +QtBrushManager::~QtBrushManager() +{ + delete d_ptr; +} + +QBrush QtBrushManager::brush(const QString &name) const +{ + if (d_ptr->theBrushMap.contains(name)) + return d_ptr->theBrushMap[name]; + return QBrush(); +} + +QMap<QString, QBrush> QtBrushManager::brushes() const +{ + return d_ptr->theBrushMap; +} + +QString QtBrushManager::currentBrush() const +{ + return d_ptr->theCurrentBrush; +} + +QString QtBrushManager::addBrush(const QString &name, const QBrush &brush) +{ + if (name.isNull()) + return QString(); + + QString newName = name; + QString nameBase = newName; + int i = 0; + while (d_ptr->theBrushMap.contains(newName)) { + newName = nameBase + QString::number(++i); + } + d_ptr->theBrushMap[newName] = brush; + emit brushAdded(newName, brush); + + return newName; +} + +void QtBrushManager::removeBrush(const QString &name) +{ + if (!d_ptr->theBrushMap.contains(name)) + return; + if (currentBrush() == name) + setCurrentBrush(QString()); + emit brushRemoved(name); + d_ptr->theBrushMap.remove(name); +} + +void QtBrushManager::setCurrentBrush(const QString &name) +{ + QBrush newBrush; + if (!name.isNull()) { + if (d_ptr->theBrushMap.contains(name)) + newBrush = d_ptr->theBrushMap[name]; + else + return; + } + d_ptr->theCurrentBrush = name; + emit currentBrushChanged(name, newBrush); +} + +QPixmap QtBrushManager::brushPixmap(const QBrush &brush) const +{ + int w = 64; + int h = 64; + + QImage img(w, h, QImage::Format_ARGB32_Premultiplied); + QPainter p(&img); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(QRect(0, 0, w, h), brush); + return QPixmap::fromImage(img); +} + +} // namespace qdesigner_internal + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/qtbrushmanager.h b/tools/designer/src/components/formeditor/qtbrushmanager.h new file mode 100644 index 0000000..f8f1b8a --- /dev/null +++ b/tools/designer/src/components/formeditor/qtbrushmanager.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTBRUSHMANAGER_H +#define QTBRUSHMANAGER_H + +#include <QtDesigner/QDesignerBrushManagerInterface> +#include "formeditor_global.h" + +#include <QtCore/QObject> +#include <QtCore/QMap> +#include <QtGui/QBrush> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +class QtBrushManagerPrivate; + +class QT_FORMEDITOR_EXPORT QtBrushManager : public QDesignerBrushManagerInterface +{ + Q_OBJECT +public: + QtBrushManager(QObject *parent = 0); + ~QtBrushManager(); + + QBrush brush(const QString &name) const; + QMap<QString, QBrush> brushes() const; + QString currentBrush() const; + + QString addBrush(const QString &name, const QBrush &brush); + void removeBrush(const QString &name); + void setCurrentBrush(const QString &name); + + QPixmap brushPixmap(const QBrush &brush) const; +signals: + void brushAdded(const QString &name, const QBrush &brush); + void brushRemoved(const QString &name); + void currentBrushChanged(const QString &name, const QBrush &brush); + +private: + QtBrushManagerPrivate *d_ptr; + Q_DECLARE_PRIVATE(QtBrushManager) + Q_DISABLE_COPY(QtBrushManager) +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif diff --git a/tools/designer/src/components/formeditor/qwizard_container.cpp b/tools/designer/src/components/formeditor/qwizard_container.cpp new file mode 100644 index 0000000..669f71a --- /dev/null +++ b/tools/designer/src/components/formeditor/qwizard_container.cpp @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwizard_container.h" + +#include <QtDesigner/QExtensionManager> +#include <QtDesigner/QDesignerFormEditorInterface> + +#include <QtGui/QWizard> +#include <QtGui/QWizardPage> +#include <QtCore/QDebug> + +QT_BEGIN_NAMESPACE + +typedef QList<int> IdList; +typedef QList<QWizardPage *> WizardPageList; + +namespace qdesigner_internal { + +QWizardContainer::QWizardContainer(QWizard *widget, QObject *parent) : + QObject(parent), + m_wizard(widget) +{ +} + +int QWizardContainer::count() const +{ + return m_wizard->pageIds().size(); +} + +QWidget *QWizardContainer::widget(int index) const +{ + QWidget *rc = 0; + if (index >= 0) { + const IdList idList = m_wizard->pageIds(); + if (index < idList.size()) + rc = m_wizard->page(idList.at(index)); + } + return rc; +} + +int QWizardContainer::currentIndex() const +{ + const IdList idList = m_wizard->pageIds(); + const int currentId = m_wizard->currentId(); + const int rc = idList.empty() ? -1 : idList.indexOf(currentId); + return rc; +} + +void QWizardContainer::setCurrentIndex(int index) +{ + if (index < 0 || m_wizard->pageIds().empty()) + return; + + int currentIdx = currentIndex(); + + if (currentIdx == -1) { + m_wizard->restart(); + currentIdx = currentIndex(); + } + + if (currentIdx == index) + return; + + const int d = qAbs(index - currentIdx); + if (index > currentIdx) { + for (int i = 0; i < d; i++) + m_wizard->next(); + } else { + for (int i = 0; i < d; i++) + m_wizard->back(); + } +} + +static const char *msgWrongType = "** WARNING Attempt to add oject that is not of class WizardPage to a QWizard"; + +void QWizardContainer::addWidget(QWidget *widget) +{ + QWizardPage *page = qobject_cast<QWizardPage *>(widget); + if (!page) { + qWarning("%s", msgWrongType); + return; + } + m_wizard->addPage(page); + // Might be -1 after adding the first page + setCurrentIndex(m_wizard->pageIds().size() - 1); +} + +void QWizardContainer::insertWidget(int index, QWidget *widget) +{ + enum { delta = 5 }; + + QWizardPage *newPage = qobject_cast<QWizardPage *>(widget); + if (!newPage) { + qWarning("%s", msgWrongType); + return; + } + + const IdList idList = m_wizard->pageIds(); + const int pageCount = idList.size(); + if (index >= pageCount) { + addWidget(widget); + return; + } + + // Insert before, reshuffle ids if required + const int idBefore = idList.at(index); + const int newId = idBefore - 1; + const bool needsShuffle = + (index == 0 && newId < 0) // At start: QWizard refuses to insert id -1 + || (index > 0 && idList.at(index - 1) == newId); // In-between + if (needsShuffle) { + // Create a gap by shuffling pages + WizardPageList pageList; + pageList.push_back(newPage); + for (int i = index; i < pageCount; i++) { + pageList.push_back(m_wizard->page(idList.at(i))); + m_wizard->removePage(idList.at(i)); + } + int newId = idBefore + delta; + const WizardPageList::const_iterator wcend = pageList.constEnd(); + for (WizardPageList::const_iterator it = pageList.constBegin(); it != wcend; ++it) { + m_wizard->setPage(newId, *it); + newId += delta; + } + } else { + // Gap found, just insert + m_wizard->setPage(newId, newPage); + } + // Might be at -1 after adding the first page + setCurrentIndex(index); +} + +void QWizardContainer::remove(int index) +{ + if (index < 0) + return; + + const IdList idList = m_wizard->pageIds(); + if (index >= idList.size()) + return; + + m_wizard->removePage(idList.at(index)); + // goto next page, preferably + const int newSize = idList.size() - 1; + if (index < newSize) { + setCurrentIndex(index); + } else { + if (newSize > 0) + setCurrentIndex(newSize - 1); + } +} + +// ---------------- QWizardPagePropertySheet +const char *QWizardPagePropertySheet::pageIdProperty = "pageId"; + +QWizardPagePropertySheet::QWizardPagePropertySheet(QWizardPage *object, QObject *parent) : + QDesignerPropertySheet(object, parent), + m_pageIdIndex(createFakeProperty(QLatin1String(pageIdProperty), QString())) +{ + setAttribute(m_pageIdIndex, true); +} + +bool QWizardPagePropertySheet::reset(int index) +{ + if (index == m_pageIdIndex) { + setProperty(index, QString()); + return true; + } + return QDesignerPropertySheet::reset(index); +} + +// ---------------- QWizardPropertySheet +QWizardPropertySheet::QWizardPropertySheet(QWizard *object, QObject *parent) : + QDesignerPropertySheet(object, parent), + m_startId(QLatin1String("startId")) +{ +} + +bool QWizardPropertySheet::isVisible(int index) const +{ + if (propertyName(index) == m_startId) + return false; + return QDesignerPropertySheet::isVisible(index); +} +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/qwizard_container.h b/tools/designer/src/components/formeditor/qwizard_container.h new file mode 100644 index 0000000..6667a1d --- /dev/null +++ b/tools/designer/src/components/formeditor/qwizard_container.h @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWIZARD_CONTAINER_H +#define QWIZARD_CONTAINER_H + +#include <QtDesigner/QDesignerContainerExtension> + +#include <qdesigner_propertysheet_p.h> +#include <extensionfactory_p.h> + +#include <QtGui/QWizard> +#include <QtGui/QWizardPage> + +QT_BEGIN_NAMESPACE + +class QWizardPage; + +namespace qdesigner_internal { + +// Container for QWizard. Care must be taken to position +// the QWizard at some valid page after removal/insertion +// as it is not used to having its pages ripped out. +class QWizardContainer: public QObject, public QDesignerContainerExtension +{ + Q_OBJECT + Q_INTERFACES(QDesignerContainerExtension) +public: + explicit QWizardContainer(QWizard *widget, QObject *parent = 0); + + virtual int count() const; + virtual QWidget *widget(int index) const; + virtual int currentIndex() const; + virtual void setCurrentIndex(int index); + virtual void addWidget(QWidget *widget); + virtual void insertWidget(int index, QWidget *widget); + virtual void remove(int index); + +private: + QWizard *m_wizard; +}; + +// QWizardPagePropertySheet: Introduces a attribute string fake property +// "pageId" that allows for specifying enumeration values (uic only). +// This breaks the pattern of having a "currentSth" property for the +// container, but was deemed to make sense here since the Page has +// its own "title" properties. +class QWizardPagePropertySheet: public QDesignerPropertySheet +{ + Q_OBJECT +public: + explicit QWizardPagePropertySheet(QWizardPage *object, QObject *parent = 0); + + virtual bool reset(int index); + + static const char *pageIdProperty; + +private: + const int m_pageIdIndex; +}; + +// QWizardPropertySheet: Hides the "startId" property. It cannot be used +// as QWizard cannot handle setting it as a property before the actual +// page is added. + +class QWizardPropertySheet: public QDesignerPropertySheet +{ + Q_OBJECT +public: + explicit QWizardPropertySheet(QWizard *object, QObject *parent = 0); + virtual bool isVisible(int index) const; + +private: + const QString m_startId; +}; + +// Factories +typedef QDesignerPropertySheetFactory<QWizard, QWizardPropertySheet> QWizardPropertySheetFactory; +typedef QDesignerPropertySheetFactory<QWizardPage, QWizardPagePropertySheet> QWizardPagePropertySheetFactory; +typedef ExtensionFactory<QDesignerContainerExtension, QWizard, QWizardContainer> QWizardContainerFactory; +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // QWIZARD_CONTAINER_H diff --git a/tools/designer/src/components/formeditor/qworkspace_container.cpp b/tools/designer/src/components/formeditor/qworkspace_container.cpp new file mode 100644 index 0000000..03cb382 --- /dev/null +++ b/tools/designer/src/components/formeditor/qworkspace_container.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qworkspace_container.h" +#include "qmdiarea_container.h" + +#include <QtGui/QWorkspace> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +QWorkspaceContainer::QWorkspaceContainer(QWorkspace *widget, QObject *parent) + : QObject(parent), + m_workspace(widget) +{ +} + +int QWorkspaceContainer::count() const +{ + return m_workspace->windowList(QWorkspace::CreationOrder).count(); +} + +QWidget *QWorkspaceContainer::widget(int index) const +{ + if (index < 0) + return 0; + return m_workspace->windowList(QWorkspace::CreationOrder).at(index); +} + +int QWorkspaceContainer::currentIndex() const +{ + if (QWidget *aw = m_workspace->activeWindow()) + return m_workspace->windowList(QWorkspace::CreationOrder).indexOf(aw); + return -1; +} + +void QWorkspaceContainer::setCurrentIndex(int index) +{ + m_workspace->setActiveWindow(m_workspace->windowList(QWorkspace::CreationOrder).at(index)); +} + +void QWorkspaceContainer::addWidget(QWidget *widget) +{ + QWidget *frame = m_workspace->addWindow(widget, Qt::Window); + frame->show(); + m_workspace->cascade(); + QMdiAreaContainer::positionNewMdiChild(m_workspace, frame); +} + +void QWorkspaceContainer::insertWidget(int, QWidget *widget) +{ + addWidget(widget); +} + +void QWorkspaceContainer::remove(int /* index */) +{ + // nothing to do here, reparenting to formwindow is apparently sufficient +} +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/qworkspace_container.h b/tools/designer/src/components/formeditor/qworkspace_container.h new file mode 100644 index 0000000..fa1e66c --- /dev/null +++ b/tools/designer/src/components/formeditor/qworkspace_container.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWORKSPACE_CONTAINER_H +#define QWORKSPACE_CONTAINER_H + +#include <QtDesigner/QDesignerContainerExtension> +#include <QtDesigner/QExtensionFactory> + +#include <extensionfactory_p.h> +#include <QtGui/QWorkspace> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +class QWorkspaceContainer: public QObject, public QDesignerContainerExtension +{ + Q_OBJECT + Q_INTERFACES(QDesignerContainerExtension) +public: + explicit QWorkspaceContainer(QWorkspace *widget, QObject *parent = 0); + + virtual int count() const; + virtual QWidget *widget(int index) const; + virtual int currentIndex() const; + virtual void setCurrentIndex(int index); + virtual void addWidget(QWidget *widget); + virtual void insertWidget(int index, QWidget *widget); + virtual void remove(int index); + +private: + QWorkspace *m_workspace; +}; + +typedef ExtensionFactory<QDesignerContainerExtension, QWorkspace, QWorkspaceContainer> QWorkspaceContainerFactory; +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // QWORKSPACE_CONTAINER_H diff --git a/tools/designer/src/components/formeditor/spacer_propertysheet.cpp b/tools/designer/src/components/formeditor/spacer_propertysheet.cpp new file mode 100644 index 0000000..16dd69d --- /dev/null +++ b/tools/designer/src/components/formeditor/spacer_propertysheet.cpp @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "spacer_propertysheet.h" +#include "qdesigner_widget_p.h" +#include "formwindow.h" +#include "spacer_widget_p.h" + +#include <QtDesigner/QExtensionManager> + +#include <QtGui/QLayout> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal +{ +SpacerPropertySheet::SpacerPropertySheet(Spacer *object, QObject *parent) + : QDesignerPropertySheet(object, parent) +{ + clearFakeProperties(); +} + +SpacerPropertySheet::~SpacerPropertySheet() +{ +} + +bool SpacerPropertySheet::isVisible(int index) const +{ + static const QString spacerGroup = QLatin1String("Spacer"); + return propertyGroup(index) == spacerGroup; +} + +void SpacerPropertySheet::setProperty(int index, const QVariant &value) +{ + QDesignerPropertySheet::setProperty(index, value); +} + +bool SpacerPropertySheet::dynamicPropertiesAllowed() const +{ + return false; +} +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/spacer_propertysheet.h b/tools/designer/src/components/formeditor/spacer_propertysheet.h new file mode 100644 index 0000000..a83e3d1 --- /dev/null +++ b/tools/designer/src/components/formeditor/spacer_propertysheet.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SPACER_PROPERTYSHEET_H +#define SPACER_PROPERTYSHEET_H + +#include <qdesigner_propertysheet_p.h> +#include <extensionfactory_p.h> +#include <spacer_widget_p.h> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +class SpacerPropertySheet: public QDesignerPropertySheet +{ + Q_OBJECT + Q_INTERFACES(QDesignerPropertySheetExtension) +public: + explicit SpacerPropertySheet(Spacer *object, QObject *parent = 0); + virtual ~SpacerPropertySheet(); + + virtual void setProperty(int index, const QVariant &value); + virtual bool isVisible(int index) const; + + virtual bool dynamicPropertiesAllowed() const; +}; + +typedef QDesignerPropertySheetFactory<Spacer, SpacerPropertySheet> SpacerPropertySheetFactory; +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // SPACER_PROPERTYSHEET_H diff --git a/tools/designer/src/components/formeditor/templateoptionspage.cpp b/tools/designer/src/components/formeditor/templateoptionspage.cpp new file mode 100644 index 0000000..dacd0d3 --- /dev/null +++ b/tools/designer/src/components/formeditor/templateoptionspage.cpp @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "templateoptionspage.h" +#include "ui_templateoptionspage.h" + +#include <shared_settings_p.h> +#include <iconloader_p.h> + +#include <QtDesigner/QDesignerFormEditorInterface> +#include <abstractdialoggui_p.h> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +// ----------------- TemplateOptionsWidget +TemplateOptionsWidget::TemplateOptionsWidget(QDesignerFormEditorInterface *core, QWidget *parent) : + QWidget(parent), + m_core(core), + m_ui(new Ui::TemplateOptionsWidget) +{ + m_ui->setupUi(this); + + m_ui->m_addTemplatePathButton->setIcon( + qdesigner_internal::createIconSet(QString::fromUtf8("plus.png"))); + m_ui->m_removeTemplatePathButton->setIcon( + qdesigner_internal::createIconSet(QString::fromUtf8("minus.png"))); + + connect(m_ui->m_templatePathListWidget, SIGNAL(itemSelectionChanged()), + this, SLOT(templatePathSelectionChanged())); + connect(m_ui->m_addTemplatePathButton, SIGNAL(clicked()), this, SLOT(addTemplatePath())); + connect(m_ui->m_removeTemplatePathButton, SIGNAL(clicked()), this, SLOT(removeTemplatePath())); +} + +TemplateOptionsWidget::~TemplateOptionsWidget() +{ + delete m_ui; +} + +QStringList TemplateOptionsWidget::templatePaths() const +{ + QStringList rc; + const int count = m_ui->m_templatePathListWidget->count(); + for (int i = 0; i < count; i++) { + rc += m_ui->m_templatePathListWidget->item(i)->text(); + } + return rc; +} + +void TemplateOptionsWidget::setTemplatePaths(const QStringList &l) +{ + // add paths and select 0 + m_ui->m_templatePathListWidget->clear(); + if (l.empty()) { + // disable button + templatePathSelectionChanged(); + } else { + const QStringList::const_iterator cend = l.constEnd(); + for (QStringList::const_iterator it = l.constBegin(); it != cend; ++it) + m_ui->m_templatePathListWidget->addItem(*it); + m_ui->m_templatePathListWidget->setCurrentItem(m_ui->m_templatePathListWidget->item(0)); + } +} + +void TemplateOptionsWidget::addTemplatePath() +{ + const QString templatePath = chooseTemplatePath(m_core, this); + if (templatePath.isEmpty()) + return; + + const QList<QListWidgetItem *> existing + = m_ui->m_templatePathListWidget->findItems(templatePath, Qt::MatchExactly); + if (!existing.empty()) + return; + + QListWidgetItem *newItem = new QListWidgetItem(templatePath); + m_ui->m_templatePathListWidget->addItem(newItem); + m_ui->m_templatePathListWidget->setCurrentItem(newItem); +} + +void TemplateOptionsWidget::removeTemplatePath() +{ + const QList<QListWidgetItem *> selectedPaths + = m_ui->m_templatePathListWidget->selectedItems(); + if (selectedPaths.empty()) + return; + delete selectedPaths.front(); +} + +void TemplateOptionsWidget::templatePathSelectionChanged() +{ + const QList<QListWidgetItem *> selectedPaths = m_ui->m_templatePathListWidget->selectedItems(); + m_ui->m_removeTemplatePathButton->setEnabled(!selectedPaths.empty()); +} + +QString TemplateOptionsWidget::chooseTemplatePath(QDesignerFormEditorInterface *core, QWidget *parent) +{ + QString rc = core->dialogGui()->getExistingDirectory(parent, + tr("Pick a directory to save templates in")); + if (rc.isEmpty()) + return rc; + + if (rc.endsWith(QDir::separator())) + rc.remove(rc.size() - 1, 1); + return rc; +} + +// ----------------- TemplateOptionsPage +TemplateOptionsPage::TemplateOptionsPage(QDesignerFormEditorInterface *core) : + m_core(core) +{ +} + +QString TemplateOptionsPage::name() const +{ + //: Tab in preferences dialog + return QCoreApplication::translate("TemplateOptionsPage", "Template Paths"); +} + +QWidget *TemplateOptionsPage::createPage(QWidget *parent) +{ + m_widget = new TemplateOptionsWidget(m_core, parent); + m_initialTemplatePaths = QDesignerSharedSettings(m_core).additionalFormTemplatePaths(); + m_widget->setTemplatePaths(m_initialTemplatePaths); + return m_widget; +} + +void TemplateOptionsPage::apply() +{ + if (m_widget) { + const QStringList newTemplatePaths = m_widget->templatePaths(); + if (newTemplatePaths != m_initialTemplatePaths) { + QDesignerSharedSettings settings(m_core); + settings.setAdditionalFormTemplatePaths(newTemplatePaths); + m_initialTemplatePaths = newTemplatePaths; + } + } +} + +void TemplateOptionsPage::finish() +{ +} +} +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/templateoptionspage.h b/tools/designer/src/components/formeditor/templateoptionspage.h new file mode 100644 index 0000000..2f17141 --- /dev/null +++ b/tools/designer/src/components/formeditor/templateoptionspage.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDESIGNER_TEMPLATEOPTIONS_H +#define QDESIGNER_TEMPLATEOPTIONS_H + +#include <QtDesigner/private/abstractoptionspage_p.h> + +#include <QtCore/QPointer> +#include <QtCore/QStringList> + +#include <QtGui/QWidget> + +QT_BEGIN_NAMESPACE + +class QDesignerFormEditorInterface; + +namespace qdesigner_internal { + +namespace Ui { + class TemplateOptionsWidget; +} + +/* Present the user with a list of form template paths to save + * form templates. */ +class TemplateOptionsWidget : public QWidget +{ + Q_OBJECT + Q_DISABLE_COPY(TemplateOptionsWidget) +public: + explicit TemplateOptionsWidget(QDesignerFormEditorInterface *core, + QWidget *parent = 0); + ~TemplateOptionsWidget(); + + + QStringList templatePaths() const; + void setTemplatePaths(const QStringList &l); + + static QString chooseTemplatePath(QDesignerFormEditorInterface *core, QWidget *parent); + +private slots: + void addTemplatePath(); + void removeTemplatePath(); + void templatePathSelectionChanged(); + +private: + QDesignerFormEditorInterface *m_core; + Ui::TemplateOptionsWidget *m_ui; +}; + +class TemplateOptionsPage : public QDesignerOptionsPageInterface +{ + Q_DISABLE_COPY(TemplateOptionsPage) +public: + explicit TemplateOptionsPage(QDesignerFormEditorInterface *core); + + virtual QString name() const; + virtual QWidget *createPage(QWidget *parent); + virtual void apply(); + virtual void finish(); + +private: + QDesignerFormEditorInterface *m_core; + QStringList m_initialTemplatePaths; + QPointer<TemplateOptionsWidget> m_widget; +}; + +} + +QT_END_NAMESPACE + +#endif // QDESIGNER_TEMPLATEOPTIONS_H diff --git a/tools/designer/src/components/formeditor/templateoptionspage.ui b/tools/designer/src/components/formeditor/templateoptionspage.ui new file mode 100644 index 0000000..3427ffe --- /dev/null +++ b/tools/designer/src/components/formeditor/templateoptionspage.ui @@ -0,0 +1,59 @@ +<ui version="4.0" > + <class>qdesigner_internal::TemplateOptionsWidget</class> + <widget class="QWidget" name="qdesigner_internal::TemplateOptionsWidget" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>376</width> + <height>387</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout" > + <item row="0" column="0" > + <widget class="QGroupBox" name="m_templatePathGroupBox" > + <property name="title" > + <string>Additional Template Paths</string> + </property> + <layout class="QGridLayout" > + <item row="0" column="0" colspan="3" > + <widget class="QListWidget" name="m_templatePathListWidget" /> + </item> + <item row="1" column="0" > + <widget class="QToolButton" name="m_addTemplatePathButton" > + <property name="text" > + <string>...</string> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="QToolButton" name="m_removeTemplatePathButton" > + <property name="text" > + <string>...</string> + </property> + </widget> + </item> + <item row="1" column="2" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/tools/designer/src/components/formeditor/tool_widgeteditor.cpp b/tools/designer/src/components/formeditor/tool_widgeteditor.cpp new file mode 100644 index 0000000..aed7e80 --- /dev/null +++ b/tools/designer/src/components/formeditor/tool_widgeteditor.cpp @@ -0,0 +1,363 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "tool_widgeteditor.h" +#include "formwindow.h" + +// sdk +#include <QtDesigner/QDesignerFormEditorInterface> +#include <QtDesigner/QDesignerWidgetFactoryInterface> +#include <QtDesigner/QDesignerWidgetBoxInterface> + +#include <layoutinfo_p.h> +#include <qdesigner_dnditem_p.h> +#include <qdesigner_resource.h> + +#include <QtGui/qevent.h> +#include <QtGui/QAction> +#include <QtGui/QMainWindow> +#include <QtGui/QCursor> +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +using namespace qdesigner_internal; + +WidgetEditorTool::WidgetEditorTool(FormWindow *formWindow) + : QDesignerFormWindowToolInterface(formWindow), + m_formWindow(formWindow), + m_action(new QAction(tr("Edit Widgets"), this)), + m_specialDockDrag(false) +{ +} + +QAction *WidgetEditorTool::action() const +{ + return m_action; +} + +WidgetEditorTool::~WidgetEditorTool() +{ +} + +QDesignerFormEditorInterface *WidgetEditorTool::core() const +{ + return m_formWindow->core(); +} + +QDesignerFormWindowInterface *WidgetEditorTool::formWindow() const +{ + return m_formWindow; +} + +bool WidgetEditorTool::mainWindowSeparatorEvent(QWidget *widget, QEvent *event) +{ + QMainWindow *mw = qobject_cast<QMainWindow*>(widget); + if (mw == 0) + return false; + + if (event->type() != QEvent::MouseButtonPress + && event->type() != QEvent::MouseMove + && event->type() != QEvent::MouseButtonRelease) + return false; + + QMouseEvent *e = static_cast<QMouseEvent*>(event); + + if (event->type() == QEvent::MouseButtonPress) { + if (mw->isSeparator(e->pos())) { + m_separator_drag_mw = mw; + return true; + } + return false; + } + + if (event->type() == QEvent::MouseMove) + return m_separator_drag_mw == mw; + + if (event->type() == QEvent::MouseButtonRelease) { + if (m_separator_drag_mw != mw) + return false; + m_separator_drag_mw = 0; + return true; + } + + return false; +} + +bool WidgetEditorTool::handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event) +{ + const bool passive = core()->widgetFactory()->isPassiveInteractor(widget) != 0 + || mainWindowSeparatorEvent(widget, event); // separators in QMainWindow + // are no longer widgets + switch (event->type()) { + case QEvent::Resize: + case QEvent::Move: + m_formWindow->updateSelection(widget); + break; + + case QEvent::FocusOut: + case QEvent::FocusIn: // Popup cancelled over a form widget: Reset its focus frame + return !(passive || widget == m_formWindow || widget == m_formWindow->mainContainer()); + + case QEvent::Wheel: // Prevent spinboxes and combos from reacting + return !passive; + + case QEvent::KeyPress: + return !passive && handleKeyPressEvent(widget, managedWidget, static_cast<QKeyEvent*>(event)); + + case QEvent::KeyRelease: + return !passive && handleKeyReleaseEvent(widget, managedWidget, static_cast<QKeyEvent*>(event)); + + case QEvent::MouseMove: + return !passive && handleMouseMoveEvent(widget, managedWidget, static_cast<QMouseEvent*>(event)); + + case QEvent::MouseButtonPress: + return !passive && handleMousePressEvent(widget, managedWidget, static_cast<QMouseEvent*>(event)); + + case QEvent::MouseButtonRelease: + return !passive && handleMouseReleaseEvent(widget, managedWidget, static_cast<QMouseEvent*>(event)); + + case QEvent::MouseButtonDblClick: + return !passive && handleMouseButtonDblClickEvent(widget, managedWidget, static_cast<QMouseEvent*>(event)); + + case QEvent::ContextMenu: + return !passive && handleContextMenu(widget, managedWidget, static_cast<QContextMenuEvent*>(event)); + + case QEvent::DragEnter: + return handleDragEnterMoveEvent(widget, managedWidget, static_cast<QDragEnterEvent *>(event), true); + case QEvent::DragMove: + return handleDragEnterMoveEvent(widget, managedWidget, static_cast<QDragEnterEvent *>(event), false); + case QEvent::DragLeave: + return handleDragLeaveEvent(widget, managedWidget, static_cast<QDragLeaveEvent *>(event)); + case QEvent::Drop: + return handleDropEvent(widget, managedWidget, static_cast<QDropEvent *>(event)); + default: + break; + + } // end switch + + return false; +} + +// ### remove me + +bool WidgetEditorTool::handleContextMenu(QWidget *widget, QWidget *managedWidget, QContextMenuEvent *e) +{ + return m_formWindow->handleContextMenu(widget, managedWidget, e); +} + +bool WidgetEditorTool::handleMouseButtonDblClickEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e) +{ + return m_formWindow->handleMouseButtonDblClickEvent(widget, managedWidget, e); +} + +bool WidgetEditorTool::handleMousePressEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e) +{ + return m_formWindow->handleMousePressEvent(widget, managedWidget, e); +} + +bool WidgetEditorTool::handleMouseMoveEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e) +{ + return m_formWindow->handleMouseMoveEvent(widget, managedWidget, e); +} + +bool WidgetEditorTool::handleMouseReleaseEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e) +{ + return m_formWindow->handleMouseReleaseEvent(widget, managedWidget, e); +} + +bool WidgetEditorTool::handleKeyPressEvent(QWidget *widget, QWidget *managedWidget, QKeyEvent *e) +{ + return m_formWindow->handleKeyPressEvent(widget, managedWidget, e); +} + +bool WidgetEditorTool::handleKeyReleaseEvent(QWidget *widget, QWidget *managedWidget, QKeyEvent *e) +{ + return m_formWindow->handleKeyReleaseEvent(widget, managedWidget, e); +} + +bool WidgetEditorTool::handlePaintEvent(QWidget *widget, QWidget *managedWidget, QPaintEvent *e) +{ + Q_UNUSED(widget); + Q_UNUSED(managedWidget); + Q_UNUSED(e); + + return false; +} + +void WidgetEditorTool::detectDockDrag(const QDesignerMimeData *mimeData) +{ + m_specialDockDrag = false; + if (!mimeData) + return; + + QMainWindow *mw = qobject_cast<QMainWindow*>(m_formWindow->mainContainer()); + if (!mw) + return; + + const QList<QDesignerDnDItemInterface*> item_list = mimeData->items(); + + foreach (QDesignerDnDItemInterface *item, item_list) { + if (item->decoration() && item->decoration()->property("_q_dockDrag").toBool()) + m_specialDockDrag = true; + + } +} + +bool WidgetEditorTool::handleDragEnterMoveEvent(QWidget *widget, QWidget * /*managedWidget*/, QDragMoveEvent *e, bool isEnter) +{ + const QDesignerMimeData *mimeData = qobject_cast<const QDesignerMimeData *>(e->mimeData()); + if (!mimeData) + return false; + + if (!m_formWindow->hasFeature(QDesignerFormWindowInterface::EditFeature)) { + e->ignore(); + return true; + } + + if (isEnter) + detectDockDrag(mimeData); + + + QPoint globalPos = QPoint(0, 0); + if (m_specialDockDrag) { + m_lastDropTarget = 0; + QMainWindow *mw = qobject_cast<QMainWindow*>(m_formWindow->mainContainer()); + if (mw) + m_lastDropTarget = mw->centralWidget(); + } else { + // If custom widgets have acceptDrops=true, the event occurs for them + const QPoint formPos = widget != m_formWindow ? widget->mapTo(m_formWindow, e->pos()) : e->pos(); + globalPos = m_formWindow->mapToGlobal(formPos); + const FormWindowBase::WidgetUnderMouseMode wum = mimeData->items().size() == 1 ? FormWindowBase::FindSingleSelectionDropTarget : FormWindowBase::FindMultiSelectionDropTarget; + QWidget *dropTarget = m_formWindow->widgetUnderMouse(formPos, wum); + if (m_lastDropTarget && dropTarget != m_lastDropTarget) + m_formWindow->highlightWidget(m_lastDropTarget, m_lastDropTarget->mapFromGlobal(globalPos), FormWindow::Restore); + m_lastDropTarget = dropTarget; + } + + if (m_lastDropTarget) + m_formWindow->highlightWidget(m_lastDropTarget, m_lastDropTarget->mapFromGlobal(globalPos), FormWindow::Highlight); + + if (isEnter || m_lastDropTarget) + mimeData->acceptEvent(e); + else + e->ignore(); + return true; +} + +bool WidgetEditorTool::handleDropEvent(QWidget *widget, QWidget *, QDropEvent *e) +{ + const QDesignerMimeData *mimeData = qobject_cast<const QDesignerMimeData *>(e->mimeData()); + if (!mimeData) + return false; + + if (!m_lastDropTarget || + !m_formWindow->hasFeature(QDesignerFormWindowInterface::EditFeature)) { + e->ignore(); + return true; + } + // FormWindow determines the position from the decoration. + const QPoint globalPos = widget->mapToGlobal(e->pos()); + mimeData->moveDecoration(globalPos); + if (m_specialDockDrag) { + if (!m_formWindow->dropDockWidget(mimeData->items().at(0), globalPos)) { + e->ignore(); + return true; + } + } else if (!m_formWindow->dropWidgets(mimeData->items(), m_lastDropTarget, globalPos)) { + e->ignore(); + return true; + } + mimeData->acceptEvent(e); + return true; +} + +bool WidgetEditorTool::restoreDropHighlighting() +{ + if (!m_lastDropTarget) + return false; + + m_formWindow->highlightWidget(m_lastDropTarget, m_lastDropTarget->mapFromGlobal(QCursor::pos()), FormWindow::Restore); + m_lastDropTarget = 0; + return true; +} + +bool WidgetEditorTool::handleDragLeaveEvent(QWidget *, QWidget *, QDragLeaveEvent *event) +{ + if (restoreDropHighlighting()) { + event->accept(); + return true; + } + return false; +} + +QWidget *WidgetEditorTool::editor() const +{ + Q_ASSERT(formWindow() != 0); + return formWindow()->mainContainer(); +} + +void WidgetEditorTool::activated() +{ + if (core()->widgetBox()) + core()->widgetBox()->setEnabled(true); + + if (m_formWindow == 0) + return; + + QList<QWidget*> sel = m_formWindow->selectedWidgets(); + foreach (QWidget *w, sel) + m_formWindow->raiseSelection(w); +} + +void WidgetEditorTool::deactivated() +{ + if (core()->widgetBox()) + core()->widgetBox()->setEnabled(false); + + if (m_formWindow == 0) + return; + + m_formWindow->clearSelection(); +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/tool_widgeteditor.h b/tools/designer/src/components/formeditor/tool_widgeteditor.h new file mode 100644 index 0000000..58df974 --- /dev/null +++ b/tools/designer/src/components/formeditor/tool_widgeteditor.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TOOL_WIDGETEDITOR_H +#define TOOL_WIDGETEDITOR_H + +#include <QtDesigner/QDesignerFormWindowToolInterface> + +#include <QtGui/qevent.h> +#include <QtCore/QPointer> + +QT_BEGIN_NAMESPACE + +class QAction; +class QMainWindow; + +namespace qdesigner_internal { + +class FormWindow; +class QDesignerMimeData; + +class WidgetEditorTool: public QDesignerFormWindowToolInterface +{ + Q_OBJECT +public: + explicit WidgetEditorTool(FormWindow *formWindow); + virtual ~WidgetEditorTool(); + + virtual QDesignerFormEditorInterface *core() const; + virtual QDesignerFormWindowInterface *formWindow() const; + virtual QWidget *editor() const; + virtual QAction *action() const; + + virtual void activated(); + virtual void deactivated(); + + virtual bool handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event); + + bool handleContextMenu(QWidget *widget, QWidget *managedWidget, QContextMenuEvent *e); + bool handleMouseButtonDblClickEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e); + bool handleMousePressEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e); + bool handleMouseMoveEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e); + bool handleMouseReleaseEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e); + bool handleKeyPressEvent(QWidget *widget, QWidget *managedWidget, QKeyEvent *e); + bool handleKeyReleaseEvent(QWidget *widget, QWidget *managedWidget, QKeyEvent *e); + bool handlePaintEvent(QWidget *widget, QWidget *managedWidget, QPaintEvent *e); + + bool handleDragEnterMoveEvent(QWidget *widget, QWidget *managedWidget, QDragMoveEvent *e, bool isEnter); + bool handleDragLeaveEvent(QWidget *widget, QWidget *managedWidget, QDragLeaveEvent *e); + bool handleDropEvent(QWidget *widget, QWidget *managedWidget, QDropEvent *e); + +private: + bool restoreDropHighlighting(); + void detectDockDrag(const QDesignerMimeData *mimeData); + + FormWindow *m_formWindow; + QAction *m_action; + + bool mainWindowSeparatorEvent(QWidget *widget, QEvent *event); + QPointer<QMainWindow> m_separator_drag_mw; + QPointer<QWidget> m_lastDropTarget; + bool m_specialDockDrag; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // TOOL_WIDGETEDITOR_H diff --git a/tools/designer/src/components/formeditor/widgetselection.cpp b/tools/designer/src/components/formeditor/widgetselection.cpp new file mode 100644 index 0000000..ce103ec --- /dev/null +++ b/tools/designer/src/components/formeditor/widgetselection.cpp @@ -0,0 +1,746 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "widgetselection.h" +#include "formwindow.h" +#include "formwindowmanager.h" + +// sdk +#include <QtDesigner/QDesignerFormEditorInterface> +#include <QtDesigner/QExtensionManager> + +// shared +#include <qdesigner_command_p.h> +#include <qdesigner_propertycommand_p.h> +#include <layout_p.h> +#include <layoutinfo_p.h> +#include <formwindowbase_p.h> +#include <grid_p.h> + +#include <QtGui/QMenu> +#include <QtGui/QWidget> +#include <QtGui/QMouseEvent> +#include <QtGui/QStylePainter> +#include <QtGui/QGridLayout> +#include <QtGui/QFormLayout> +#include <QtGui/QStyleOptionToolButton> +#include <QtGui/QApplication> + +#include <QtCore/QVariant> +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { +enum { debugWidgetSelection = 0 }; + +// Return the layout the widget is in +template <class Layout> +static inline Layout *managedLayoutOf(const QDesignerFormEditorInterface *core, + QWidget *w, + const Layout * /* vs6dummy */ = 0) +{ + if (QWidget *p = w->parentWidget()) + if (QLayout *l = LayoutInfo::managedLayout(core, p)) + return qobject_cast<Layout*>(l); + return 0; +} + +// ----------- WidgetHandle +WidgetHandle::WidgetHandle(FormWindow *parent, WidgetHandle::Type t, WidgetSelection *s) : + InvisibleWidget(parent->mainContainer()), + m_widget(0), + m_type(t), + m_formWindow( parent), + m_sel(s), + m_active(true) +{ + setMouseTracking(false); + setAutoFillBackground(true); + + setBackgroundRole(m_active ? QPalette::Text : QPalette::Dark); + setFixedSize(6, 6); + + updateCursor(); +} + +void WidgetHandle::updateCursor() +{ +#ifndef QT_NO_CURSOR + if (!m_active) { + setCursor(Qt::ArrowCursor); + return; + } + + switch (m_type) { + case LeftTop: + setCursor(Qt::SizeFDiagCursor); + break; + case Top: + setCursor(Qt::SizeVerCursor); + break; + case RightTop: + setCursor(Qt::SizeBDiagCursor); + break; + case Right: + setCursor(Qt::SizeHorCursor); + break; + case RightBottom: + setCursor(Qt::SizeFDiagCursor); + break; + case Bottom: + setCursor(Qt::SizeVerCursor); + break; + case LeftBottom: + setCursor(Qt::SizeBDiagCursor); + break; + case Left: + setCursor(Qt::SizeHorCursor); + break; + default: + Q_ASSERT(0); + } +#endif +} + +QDesignerFormEditorInterface *WidgetHandle::core() const +{ + if (m_formWindow) + return m_formWindow->core(); + + return 0; +} + +void WidgetHandle::setActive(bool a) +{ + m_active = a; + setBackgroundRole(m_active ? QPalette::Text : QPalette::Dark); + updateCursor(); +} + +void WidgetHandle::setWidget(QWidget *w) +{ + m_widget = w; +} + +void WidgetHandle::paintEvent(QPaintEvent *) +{ + QDesignerFormWindowManagerInterface *m = m_formWindow->core()->formWindowManager(); + + QStylePainter p(this); + if (m_formWindow->currentWidget() == m_widget) { + p.setPen(m->activeFormWindow() == m_formWindow ? Qt::blue : Qt::red); + p.drawRect(0, 0, width() - 1, height() - 1); + } +} + +void WidgetHandle::mousePressEvent(QMouseEvent *e) +{ + e->accept(); + + if (!m_formWindow->hasFeature(FormWindow::EditFeature)) + return; + + if (!(m_widget && e->button() == Qt::LeftButton)) + return; + + if (!(m_active)) + return; + + QWidget *container = m_widget->parentWidget(); + + m_origPressPos = container->mapFromGlobal(e->globalPos()); + m_geom = m_origGeom = m_widget->geometry(); +} + +void WidgetHandle::mouseMoveEvent(QMouseEvent *e) +{ + if (!(m_widget && m_active && e->buttons() & Qt::LeftButton)) + return; + + e->accept(); + + QWidget *container = m_widget->parentWidget(); + + const QPoint rp = container->mapFromGlobal(e->globalPos()); + const QPoint d = rp - m_origPressPos; + + const QRect pr = container->rect(); + + qdesigner_internal::Grid grid; + if (const qdesigner_internal::FormWindowBase *fwb = qobject_cast<const qdesigner_internal::FormWindowBase*>(m_formWindow)) + grid = fwb->designerGrid(); + + switch (m_type) { + + case LeftTop: { + if (rp.x() > pr.width() - 2 * width() || rp.y() > pr.height() - 2 * height()) + return; + + int w = m_origGeom.width() - d.x(); + m_geom.setWidth(w); + w = grid.widgetHandleAdjustX(w); + + int h = m_origGeom.height() - d.y(); + m_geom.setHeight(h); + h = grid.widgetHandleAdjustY(h); + + const int dx = m_widget->width() - w; + const int dy = m_widget->height() - h; + + trySetGeometry(m_widget, m_widget->x() + dx, m_widget->y() + dy, w, h); + } break; + + case Top: { + if (rp.y() > pr.height() - 2 * height()) + return; + + int h = m_origGeom.height() - d.y(); + m_geom.setHeight(h); + h = grid.widgetHandleAdjustY(h); + + const int dy = m_widget->height() - h; + trySetGeometry(m_widget, m_widget->x(), m_widget->y() + dy, m_widget->width(), h); + } break; + + case RightTop: { + if (rp.x() < 2 * width() || rp.y() > pr.height() - 2 * height()) + return; + + int h = m_origGeom.height() - d.y(); + m_geom.setHeight(h); + h = grid.widgetHandleAdjustY(h); + + const int dy = m_widget->height() - h; + + int w = m_origGeom.width() + d.x(); + m_geom.setWidth(w); + w = grid.widgetHandleAdjustX(w); + + trySetGeometry(m_widget, m_widget->x(), m_widget->y() + dy, w, h); + } break; + + case Right: { + if (rp.x() < 2 * width()) + return; + + int w = m_origGeom.width() + d.x(); + m_geom.setWidth(w); + w = grid.widgetHandleAdjustX(w); + + tryResize(m_widget, w, m_widget->height()); + } break; + + case RightBottom: { + if (rp.x() < 2 * width() || rp.y() < 2 * height()) + return; + + int w = m_origGeom.width() + d.x(); + m_geom.setWidth(w); + w = grid.widgetHandleAdjustX(w); + + int h = m_origGeom.height() + d.y(); + m_geom.setHeight(h); + h = grid.widgetHandleAdjustY(h); + + tryResize(m_widget, w, h); + } break; + + case Bottom: { + if (rp.y() < 2 * height()) + return; + + int h = m_origGeom.height() + d.y(); + m_geom.setHeight(h); + h = grid.widgetHandleAdjustY(h); + + tryResize(m_widget, m_widget->width(), h); + } break; + + case LeftBottom: { + if (rp.x() > pr.width() - 2 * width() || rp.y() < 2 * height()) + return; + + int w = m_origGeom.width() - d.x(); + m_geom.setWidth(w); + w = grid.widgetHandleAdjustX(w); + + int h = m_origGeom.height() + d.y(); + m_geom.setHeight(h); + h = grid.widgetHandleAdjustY(h); + + int dx = m_widget->width() - w; + + trySetGeometry(m_widget, m_widget->x() + dx, m_widget->y(), w, h); + } break; + + case Left: { + if (rp.x() > pr.width() - 2 * width()) + return; + + int w = m_origGeom.width() - d.x(); + m_geom.setWidth(w); + w = grid.widgetHandleAdjustX(w); + + const int dx = m_widget->width() - w; + + trySetGeometry(m_widget, m_widget->x() + dx, m_widget->y(), w, m_widget->height()); + } break; + + default: break; + + } // end switch + + m_sel->updateGeometry(); + + if (LayoutInfo::layoutType(m_formWindow->core(), m_widget) != LayoutInfo::NoLayout) + m_formWindow->updateChildSelections(m_widget); +} + +void WidgetHandle::mouseReleaseEvent(QMouseEvent *e) +{ + if (e->button() != Qt::LeftButton || !m_active) + return; + + e->accept(); + + if (!m_formWindow->hasFeature(FormWindow::EditFeature)) + return; + + switch (WidgetSelection::widgetState(m_formWindow->core(), m_widget)) { + case WidgetSelection::UnlaidOut: + if (m_geom != m_widget->geometry()) { + SetPropertyCommand *cmd = new SetPropertyCommand(m_formWindow); + cmd->init(m_widget, QLatin1String("geometry"), m_widget->geometry()); + cmd->setOldValue(m_origGeom); + m_formWindow->commandHistory()->push(cmd); + m_formWindow->emitSelectionChanged(); + } + break; + case WidgetSelection::LaidOut: + break; + case WidgetSelection::ManagedGridLayout: + changeGridLayoutItemSpan(); + break; + case WidgetSelection::ManagedFormLayout: + changeFormLayoutItemSpan(); + break; + } +} + +// Match the left/right widget handle mouse movements to form layout span-changing operations +static inline int formLayoutLeftHandleOperation(int dx, unsigned possibleOperations) +{ + if (dx < 0) { + if (possibleOperations & ChangeFormLayoutItemRoleCommand::FieldToSpanning) + return ChangeFormLayoutItemRoleCommand::FieldToSpanning; + return 0; + } + if (possibleOperations & ChangeFormLayoutItemRoleCommand::SpanningToField) + return ChangeFormLayoutItemRoleCommand::SpanningToField; + return 0; +} + +static inline int formLayoutRightHandleOperation(int dx, unsigned possibleOperations) +{ + if (dx < 0) { + if (possibleOperations & ChangeFormLayoutItemRoleCommand::SpanningToLabel) + return ChangeFormLayoutItemRoleCommand::SpanningToLabel; + return 0; + } + if (possibleOperations & ChangeFormLayoutItemRoleCommand::LabelToSpanning) + return ChangeFormLayoutItemRoleCommand::LabelToSpanning; + return 0; +} + +// Change form layout item horizontal span +void WidgetHandle::changeFormLayoutItemSpan() +{ + QUndoCommand *cmd = 0; + // Figure out command according to the movement + const int dx = m_widget->geometry().center().x() - m_origGeom.center().x(); + if (qAbs(dx) >= QApplication::startDragDistance()) { + int operation = 0; + if (const unsigned possibleOperations = ChangeFormLayoutItemRoleCommand::possibleOperations(m_formWindow->core(), m_widget)) { + switch (m_type) { + case WidgetHandle::Left: + operation = formLayoutLeftHandleOperation(dx, possibleOperations); + break; + case WidgetHandle::Right: + operation = formLayoutRightHandleOperation(dx, possibleOperations); + break; + default: + break; + } + if (operation) { + ChangeFormLayoutItemRoleCommand *fcmd = new ChangeFormLayoutItemRoleCommand(m_formWindow); + fcmd->init(m_widget, static_cast<ChangeFormLayoutItemRoleCommand::Operation>(operation)); + cmd = fcmd; + } + } + } + if (cmd) { + m_formWindow->commandHistory()->push(cmd); + } else { + // Cancelled/Invalid. Restore the size of the widget. + if (QFormLayout *form = managedLayoutOf<QFormLayout>(m_formWindow->core(), m_widget)) { + form->invalidate(); + form->activate(); + m_formWindow->clearSelection(false); + m_formWindow->selectWidget(m_widget); + } + } +} + +void WidgetHandle::changeGridLayoutItemSpan() +{ + QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(core()->extensionManager(), m_widget->parentWidget()); + if (!deco) + return; + QGridLayout *grid = managedLayoutOf<QGridLayout>(m_formWindow->core(), m_widget); + if (!grid) + return; + + const QSize size = m_widget->parentWidget()->size(); + + const int index = deco->indexOf(m_widget); + const QRect info = deco->itemInfo(index); + const int top = deco->findItemAt(info.top() - 1, info.left()); + const int left = deco->findItemAt(info.top(), info.left() - 1); + const int bottom = deco->findItemAt(info.bottom() + 1, info.left()); + const int right = deco->findItemAt(info.top(), info.right() + 1); + + const QPoint pt = m_origGeom.center() - m_widget->geometry().center(); + + ChangeLayoutItemGeometry *cmd = 0; + + switch (m_type) { + default: + break; + + case WidgetHandle::Top: { + if (pt.y() < 0 && info.height() > 1) { + cmd = new ChangeLayoutItemGeometry(m_formWindow); + cmd->init(m_widget, info.y() + 1, info.x(), info.height() - 1, info.width()); + } else if (pt.y() > 0 && top != -1 && grid->itemAt(top)->spacerItem()) { + cmd = new ChangeLayoutItemGeometry(m_formWindow); + cmd->init(m_widget, info.y() - 1, info.x(), info.height() + 1, info.width()); + } + } + break; + + case WidgetHandle::Left: { + if (pt.x() < 0 && info.width() > 1) { + cmd = new ChangeLayoutItemGeometry(m_formWindow); + cmd->init(m_widget, info.y(), info.x() + 1, info.height(), info.width() - 1); + } else if (pt.x() > 0 && left != -1 && grid->itemAt(left)->spacerItem()) { + cmd = new ChangeLayoutItemGeometry(m_formWindow); + cmd->init(m_widget, info.y(), info.x() - 1, info.height(), info.width() + 1); + } + } + break; + + case WidgetHandle::Right: { + if (pt.x() > 0 && info.width() > 1) { + cmd = new ChangeLayoutItemGeometry(m_formWindow); + cmd->init(m_widget, info.y(), info.x(), info.height(), info.width() - 1); + } else if (pt.x() < 0 && right != -1 && grid->itemAt(right)->spacerItem()) { + cmd = new ChangeLayoutItemGeometry(m_formWindow); + cmd->init(m_widget, info.y(), info.x(), info.height(), info.width() + 1); + } + } + break; + + case WidgetHandle::Bottom: { + if (pt.y() > 0 && info.width() > 1) { + cmd = new ChangeLayoutItemGeometry(m_formWindow); + cmd->init(m_widget, info.y(), info.x(), info.height() - 1, info.width()); + } else if (pt.y() < 0 && bottom != -1 && grid->itemAt(bottom)->spacerItem()) { + cmd = new ChangeLayoutItemGeometry(m_formWindow); + cmd->init(m_widget, info.y(), info.x(), info.height() + 1, info.width()); + } + } + break; + } + + if (cmd != 0) { + m_formWindow->commandHistory()->push(cmd); + } else { + grid->invalidate(); + grid->activate(); + m_formWindow->clearSelection(false); + m_formWindow->selectWidget(m_widget); + } +} + +void WidgetHandle::trySetGeometry(QWidget *w, int x, int y, int width, int height) +{ + if (!m_formWindow->hasFeature(FormWindow::EditFeature)) + return; + + int minw = w->minimumSize().width(); + minw = qMax(minw, 2 * m_formWindow->grid().x()); + + int minh = w->minimumSize().height(); + minh = qMax(minh, 2 * m_formWindow->grid().y()); + + if (qMax(minw, width) > w->maximumWidth() || + qMax(minh, height) > w->maximumHeight()) + return; + + if (width < minw && x != w->x()) + x -= minw - width; + + if (height < minh && y != w->y()) + y -= minh - height; + + w->setGeometry(x, y, qMax(minw, width), qMax(minh, height)); +} + +void WidgetHandle::tryResize(QWidget *w, int width, int height) +{ + int minw = w->minimumSize().width(); + minw = qMax(minw, 16); + + int minh = w->minimumSize().height(); + minh = qMax(minh, 16); + + w->resize(qMax(minw, width), qMax(minh, height)); +} + +// ------------------ WidgetSelection + +WidgetSelection::WidgetState WidgetSelection::widgetState(const QDesignerFormEditorInterface *core, QWidget *w) +{ + bool isManaged; + const LayoutInfo::Type lt = LayoutInfo::laidoutWidgetType(core, w, &isManaged); + if (lt == LayoutInfo::NoLayout) + return UnlaidOut; + if (!isManaged) + return LaidOut; + switch (lt) { + case LayoutInfo::Grid: + return ManagedGridLayout; + case LayoutInfo::Form: + return ManagedFormLayout; + default: + break; + } + return LaidOut; +} + +WidgetSelection::WidgetSelection(FormWindow *parent) : + m_widget(0), + m_formWindow(parent) +{ + for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i) + m_handles[i] = new WidgetHandle(m_formWindow, static_cast<WidgetHandle::Type>(i), this); + hide(); +} + +void WidgetSelection::setWidget(QWidget *w) +{ + if (m_widget != 0) + m_widget->removeEventFilter(this); + + if (w == 0) { + hide(); + m_widget = 0; + return; + } + + m_widget = w; + + m_widget->installEventFilter(this); + + updateActive(); + + updateGeometry(); + show(); +} + +void WidgetSelection::updateActive() +{ + const WidgetState ws = widgetState(m_formWindow->core(), m_widget); + bool active[WidgetHandle::TypeCount]; + qFill(active, active + WidgetHandle::TypeCount, false); + // Determine active handles + switch (ws) { + case UnlaidOut: + qFill(active, active + WidgetHandle::TypeCount, true); + break; + case ManagedGridLayout: // Grid: Allow changing span + active[WidgetHandle::Left] = active[WidgetHandle::Top] = active[WidgetHandle::Right] = active[WidgetHandle::Bottom] = true; + break; + case ManagedFormLayout: // Form: Allow changing column span + if (const unsigned operation = ChangeFormLayoutItemRoleCommand::possibleOperations(m_formWindow->core(), m_widget)) { + active[WidgetHandle::Left] = operation & (ChangeFormLayoutItemRoleCommand::SpanningToField|ChangeFormLayoutItemRoleCommand::FieldToSpanning); + active[WidgetHandle::Right] = operation & (ChangeFormLayoutItemRoleCommand::SpanningToLabel|ChangeFormLayoutItemRoleCommand::LabelToSpanning); + } + break; + default: + break; + } + + for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i) + if (WidgetHandle *h = m_handles[i]) { + h->setWidget(m_widget); + h->setActive(active[i]); + } +} + +bool WidgetSelection::isUsed() const +{ + return m_widget != 0; +} + +void WidgetSelection::updateGeometry() +{ + if (!m_widget || !m_widget->parentWidget()) + return; + + QPoint p = m_widget->parentWidget()->mapToGlobal(m_widget->pos()); + p = m_formWindow->mapFromGlobal(p); + const QRect r(p, m_widget->size()); + + const int w = 6; + const int h = 6; + + for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i) { + WidgetHandle *hndl = m_handles[ i ]; + if (!hndl) + continue; + switch (i) { + case WidgetHandle::LeftTop: + hndl->move(r.x() - w / 2, r.y() - h / 2); + break; + case WidgetHandle::Top: + hndl->move(r.x() + r.width() / 2 - w / 2, r.y() - h / 2); + break; + case WidgetHandle::RightTop: + hndl->move(r.x() + r.width() - w / 2, r.y() - h / 2); + break; + case WidgetHandle::Right: + hndl->move(r.x() + r.width() - w / 2, r.y() + r.height() / 2 - h / 2); + break; + case WidgetHandle::RightBottom: + hndl->move(r.x() + r.width() - w / 2, r.y() + r.height() - h / 2); + break; + case WidgetHandle::Bottom: + hndl->move(r.x() + r.width() / 2 - w / 2, r.y() + r.height() - h / 2); + break; + case WidgetHandle::LeftBottom: + hndl->move(r.x() - w / 2, r.y() + r.height() - h / 2); + break; + case WidgetHandle::Left: + hndl->move(r.x() - w / 2, r.y() + r.height() / 2 - h / 2); + break; + default: + break; + } + } +} + +void WidgetSelection::hide() +{ + for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i) { + WidgetHandle *h = m_handles[ i ]; + if (h) + h->hide(); + } +} + +void WidgetSelection::show() +{ + for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i) { + WidgetHandle *h = m_handles[ i ]; + if (h) { + h->show(); + h->raise(); + } + } +} + +void WidgetSelection::update() +{ + for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i) { + WidgetHandle *h = m_handles[ i ]; + if (h) + h->update(); + } +} + +QWidget *WidgetSelection::widget() const +{ + return m_widget; +} + +QDesignerFormEditorInterface *WidgetSelection::core() const +{ + if (m_formWindow) + return m_formWindow->core(); + + return 0; +} + +bool WidgetSelection::eventFilter(QObject *object, QEvent *event) +{ + if (object != widget()) + return false; + + switch (event->type()) { + default: break; + + case QEvent::Move: + case QEvent::Resize: + updateGeometry(); + break; + case QEvent::ZOrderChange: + show(); + break; + } // end switch + + return false; +} + +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/formeditor/widgetselection.h b/tools/designer/src/components/formeditor/widgetselection.h new file mode 100644 index 0000000..9099e89 --- /dev/null +++ b/tools/designer/src/components/formeditor/widgetselection.h @@ -0,0 +1,145 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WIDGETSELECTION_H +#define WIDGETSELECTION_H + +#include "formeditor_global.h" +#include <invisible_widget_p.h> + +#include <QtCore/QHash> +#include <QtCore/QPointer> + +QT_BEGIN_NAMESPACE + +class QDesignerFormEditorInterface; +class QMouseEvent; +class QPaintEvent; + +namespace qdesigner_internal { + +class FormWindow; +class WidgetSelection; + +class QT_FORMEDITOR_EXPORT WidgetHandle: public InvisibleWidget +{ + Q_OBJECT +public: + enum Type + { + LeftTop, + Top, + RightTop, + Right, + RightBottom, + Bottom, + LeftBottom, + Left, + + TypeCount + }; + + WidgetHandle(FormWindow *parent, Type t, WidgetSelection *s); + void setWidget(QWidget *w); + void setActive(bool a); + void updateCursor(); + + void setEnabled(bool) {} + + QDesignerFormEditorInterface *core() const; + +protected: + void paintEvent(QPaintEvent *e); + void mousePressEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + +private: + void changeGridLayoutItemSpan(); + void changeFormLayoutItemSpan(); + void trySetGeometry(QWidget *w, int x, int y, int width, int height); + void tryResize(QWidget *w, int width, int height); + +private: + QWidget *m_widget; + const Type m_type; + QPoint m_origPressPos; + FormWindow *m_formWindow; + WidgetSelection *m_sel; + QRect m_geom, m_origGeom; + bool m_active; +}; + +class QT_FORMEDITOR_EXPORT WidgetSelection: public QObject +{ + Q_OBJECT +public: + WidgetSelection(FormWindow *parent); + + void setWidget(QWidget *w); + bool isUsed() const; + + void updateActive(); + void updateGeometry(); + void hide(); + void show(); + void update(); + + QWidget *widget() const; + + QDesignerFormEditorInterface *core() const; + + virtual bool eventFilter(QObject *object, QEvent *event); + + enum WidgetState { UnlaidOut, LaidOut, ManagedGridLayout, ManagedFormLayout }; + static WidgetState widgetState(const QDesignerFormEditorInterface *core, QWidget *w); + +private: + WidgetHandle *m_handles[WidgetHandle::TypeCount]; + QPointer<QWidget> m_widget; + FormWindow *m_formWindow; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // WIDGETSELECTION_H |