2015-12-10 05:06:13 +02:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
|
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
|
|
**
|
2019-06-03 13:38:02 +00:00
|
|
|
** This file is part of the Qt Designer of the Katie Toolkit.
|
2015-12-10 05:06:13 +02:00
|
|
|
**
|
|
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
|
|
** Commercial License Usage
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
|
|
|
** information use the contact form at http://www.qt.io/contact-us.
|
|
|
|
**
|
|
|
|
** 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 or version 3 as published by the Free
|
|
|
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
|
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
|
|
** following information to ensure the GNU Lesser General Public License
|
|
|
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
|
|
**
|
|
|
|
** As a special exception, The Qt Company gives you certain additional
|
|
|
|
** rights. These rights are described in The Qt Company LGPL Exception
|
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
**
|
|
|
|
** GNU General Public License Usage
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
** General Public License version 3.0 as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.GPL included in the
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
** ensure the GNU General Public License version 3.0 requirements will be
|
|
|
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
|
|
|
**
|
|
|
|
** $QT_END_LICENSE$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include "abstractsettings_p.h"
|
|
|
|
#include "previewmanager_p.h"
|
|
|
|
#include "qdesigner_formbuilder_p.h"
|
|
|
|
#include "shared_settings_p.h"
|
|
|
|
#include "shared_settings_p.h"
|
|
|
|
#include "zoomwidget_p.h"
|
|
|
|
#include "formwindowbase_p.h"
|
|
|
|
#include "widgetfactory_p.h"
|
|
|
|
|
|
|
|
#include <QtDesigner/abstractformwindow.h>
|
|
|
|
#include <QtDesigner/abstractformeditor.h>
|
|
|
|
#include <QtDesigner/abstractformwindowmanager.h>
|
|
|
|
|
|
|
|
#include <QtGui/QWidget>
|
|
|
|
#include <QtGui/qevent.h>
|
|
|
|
#include <QtGui/QDesktopWidget>
|
|
|
|
#include <QtGui/QMainWindow>
|
|
|
|
#include <QtGui/QDockWidget>
|
|
|
|
#include <QtGui/QApplication>
|
|
|
|
#include <QtGui/QPixmap>
|
|
|
|
#include <QtGui/QVBoxLayout>
|
|
|
|
#include <QtGui/QDialog>
|
|
|
|
#include <QtGui/QMenu>
|
|
|
|
#include <QtGui/QAction>
|
|
|
|
#include <QtGui/QActionGroup>
|
|
|
|
#include <QtGui/QCursor>
|
|
|
|
#include <QtGui/QMatrix>
|
|
|
|
|
|
|
|
#include <QtCore/QMap>
|
|
|
|
#include <QtCore/QDebug>
|
|
|
|
#include <QtCore/QSharedData>
|
|
|
|
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
|
2019-05-04 16:47:40 +00:00
|
|
|
namespace qdesigner_internal {
|
|
|
|
|
2015-12-10 05:06:13 +02:00
|
|
|
static inline int compare(const qdesigner_internal::PreviewConfiguration &pc1, const qdesigner_internal::PreviewConfiguration &pc2)
|
|
|
|
{
|
|
|
|
int rc = pc1.style().compare(pc2.style());
|
|
|
|
if (rc)
|
|
|
|
return rc;
|
2019-05-04 17:06:44 +00:00
|
|
|
return pc1.applicationStyleSheet().compare(pc2.applicationStyleSheet());
|
2015-12-10 05:06:13 +02:00
|
|
|
}
|
|
|
|
|
2019-05-04 16:47:40 +00:00
|
|
|
// ------ PreviewData (data associated with a preview window)
|
|
|
|
struct PreviewData {
|
|
|
|
PreviewData(const QPointer<QWidget> &widget, const QDesignerFormWindowInterface *formWindow, const qdesigner_internal::PreviewConfiguration &pc);
|
|
|
|
QPointer<QWidget> m_widget;
|
|
|
|
const QDesignerFormWindowInterface *m_formWindow;
|
|
|
|
qdesigner_internal::PreviewConfiguration m_configuration;
|
|
|
|
};
|
2015-12-10 05:06:13 +02:00
|
|
|
|
2019-05-04 16:47:40 +00:00
|
|
|
PreviewData::PreviewData(const QPointer<QWidget>& widget,
|
|
|
|
const QDesignerFormWindowInterface *formWindow,
|
|
|
|
const qdesigner_internal::PreviewConfiguration &pc) :
|
|
|
|
m_widget(widget),
|
|
|
|
m_formWindow(formWindow),
|
|
|
|
m_configuration(pc)
|
|
|
|
{
|
2015-12-10 05:06:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* In designer, we have the situation that laid-out maincontainers have
|
|
|
|
* a geometry set (which might differ from their sizeHint()). The QGraphicsItem
|
|
|
|
* should return that in its size hint, else such cases won't work */
|
|
|
|
|
|
|
|
class DesignerZoomProxyWidget : public ZoomProxyWidget {
|
|
|
|
Q_DISABLE_COPY(DesignerZoomProxyWidget)
|
|
|
|
public:
|
|
|
|
DesignerZoomProxyWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
|
|
|
|
protected:
|
|
|
|
virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF & constraint = QSizeF() ) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
DesignerZoomProxyWidget::DesignerZoomProxyWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags) :
|
|
|
|
ZoomProxyWidget(parent, wFlags)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
QSizeF DesignerZoomProxyWidget::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const
|
|
|
|
{
|
|
|
|
if (const QWidget *w = widget())
|
|
|
|
return QSizeF(w->size());
|
|
|
|
return ZoomProxyWidget::sizeHint(which, constraint);
|
|
|
|
}
|
|
|
|
|
|
|
|
// DesignerZoomWidget which returns DesignerZoomProxyWidget in its factory function
|
|
|
|
class DesignerZoomWidget : public ZoomWidget {
|
|
|
|
Q_DISABLE_COPY(DesignerZoomWidget)
|
|
|
|
public:
|
2016-11-04 04:13:46 +00:00
|
|
|
DesignerZoomWidget(QWidget *parent = Q_NULLPTR);
|
2015-12-10 05:06:13 +02:00
|
|
|
private:
|
|
|
|
virtual QGraphicsProxyWidget *createProxyWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
DesignerZoomWidget::DesignerZoomWidget(QWidget *parent) :
|
|
|
|
ZoomWidget(parent)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
QGraphicsProxyWidget *DesignerZoomWidget::createProxyWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags) const
|
|
|
|
{
|
|
|
|
return new DesignerZoomProxyWidget(parent, wFlags);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------ PreviewConfigurationPrivate
|
|
|
|
class PreviewConfigurationData : public QSharedData {
|
|
|
|
public:
|
|
|
|
PreviewConfigurationData() {}
|
2019-05-04 17:06:44 +00:00
|
|
|
explicit PreviewConfigurationData(const QString &style, const QString &applicationStyleSheet);
|
2015-12-10 05:06:13 +02:00
|
|
|
|
|
|
|
QString m_style;
|
|
|
|
// Style sheet to prepend (to simulate the effect od QApplication::setSyleSheet()).
|
|
|
|
QString m_applicationStyleSheet;
|
|
|
|
};
|
|
|
|
|
2019-05-04 17:06:44 +00:00
|
|
|
PreviewConfigurationData::PreviewConfigurationData(const QString &style, const QString &applicationStyleSheet) :
|
2015-12-10 05:06:13 +02:00
|
|
|
m_style(style),
|
2019-05-04 17:06:44 +00:00
|
|
|
m_applicationStyleSheet(applicationStyleSheet)
|
2015-12-10 05:06:13 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------- PreviewConfiguration
|
|
|
|
|
|
|
|
static const char *styleKey = "Style";
|
|
|
|
static const char *appStyleSheetKey = "AppStyleSheet";
|
|
|
|
|
|
|
|
PreviewConfiguration::PreviewConfiguration() :
|
|
|
|
m_d(new PreviewConfigurationData)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-05-04 17:06:44 +00:00
|
|
|
PreviewConfiguration::PreviewConfiguration(const QString &sty, const QString &applicationSheet) :
|
|
|
|
m_d(new PreviewConfigurationData(sty, applicationSheet))
|
2015-12-10 05:06:13 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
PreviewConfiguration::PreviewConfiguration(const PreviewConfiguration &o) :
|
|
|
|
m_d(o.m_d)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
PreviewConfiguration &PreviewConfiguration::operator=(const PreviewConfiguration &o)
|
|
|
|
{
|
|
|
|
m_d.operator=(o.m_d);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
PreviewConfiguration::~PreviewConfiguration()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void PreviewConfiguration::clear()
|
|
|
|
{
|
|
|
|
PreviewConfigurationData &d = *m_d;
|
|
|
|
d.m_style.clear();
|
|
|
|
d.m_applicationStyleSheet.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
QString PreviewConfiguration::style() const
|
|
|
|
{
|
|
|
|
return m_d->m_style;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PreviewConfiguration::setStyle(const QString &s)
|
|
|
|
{
|
|
|
|
m_d->m_style = s;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Style sheet to prepend (to simulate the effect od QApplication::setSyleSheet()).
|
|
|
|
QString PreviewConfiguration::applicationStyleSheet() const
|
|
|
|
{
|
|
|
|
return m_d->m_applicationStyleSheet;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PreviewConfiguration::setApplicationStyleSheet(const QString &as)
|
|
|
|
{
|
|
|
|
m_d->m_applicationStyleSheet = as;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PreviewConfiguration::toSettings(const QString &prefix, QDesignerSettingsInterface *settings) const
|
|
|
|
{
|
|
|
|
const PreviewConfigurationData &d = *m_d;
|
|
|
|
settings->beginGroup(prefix);
|
|
|
|
settings->setValue(QLatin1String(styleKey), d.m_style);
|
|
|
|
settings->setValue(QLatin1String(appStyleSheetKey), d.m_applicationStyleSheet);
|
|
|
|
settings->endGroup();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PreviewConfiguration::fromSettings(const QString &prefix, const QDesignerSettingsInterface *settings)
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
QString key = prefix;
|
|
|
|
key += QLatin1Char('/');
|
|
|
|
const int prefixSize = key.size();
|
|
|
|
|
|
|
|
PreviewConfigurationData &d = *m_d;
|
|
|
|
|
|
|
|
const QVariant emptyString = QVariant(QString());
|
|
|
|
|
|
|
|
key += QLatin1String(styleKey);
|
|
|
|
d.m_style = settings->value(key, emptyString).toString();
|
|
|
|
|
|
|
|
key.replace(prefixSize, key.size() - prefixSize, QLatin1String(appStyleSheetKey));
|
|
|
|
d.m_applicationStyleSheet = settings->value(key, emptyString).toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QDESIGNER_SHARED_EXPORT bool operator<(const PreviewConfiguration &pc1, const PreviewConfiguration &pc2)
|
|
|
|
{
|
|
|
|
return compare(pc1, pc2) < 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
QDESIGNER_SHARED_EXPORT bool operator==(const PreviewConfiguration &pc1, const PreviewConfiguration &pc2)
|
|
|
|
{
|
|
|
|
return compare(pc1, pc2) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
QDESIGNER_SHARED_EXPORT bool operator!=(const PreviewConfiguration &pc1, const PreviewConfiguration &pc2)
|
|
|
|
{
|
|
|
|
return compare(pc1, pc2) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------- PreviewManagerPrivate
|
|
|
|
class PreviewManagerPrivate {
|
|
|
|
public:
|
|
|
|
PreviewManagerPrivate(PreviewManager::PreviewMode mode);
|
|
|
|
|
|
|
|
const PreviewManager::PreviewMode m_mode;
|
|
|
|
|
|
|
|
QPointer<QWidget> m_activePreview;
|
|
|
|
|
|
|
|
typedef QList<PreviewData> PreviewDataList;
|
|
|
|
|
|
|
|
PreviewDataList m_previews;
|
|
|
|
|
|
|
|
QDesignerFormEditorInterface *m_core;
|
|
|
|
bool m_updateBlocked;
|
|
|
|
};
|
|
|
|
|
|
|
|
PreviewManagerPrivate::PreviewManagerPrivate(PreviewManager::PreviewMode mode) :
|
|
|
|
m_mode(mode),
|
|
|
|
m_core(0),
|
|
|
|
m_updateBlocked(false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------- PreviewManager
|
|
|
|
|
|
|
|
PreviewManager::PreviewManager(PreviewMode mode, QObject *parent) :
|
|
|
|
QObject(parent),
|
|
|
|
d(new PreviewManagerPrivate(mode))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
PreviewManager:: ~PreviewManager()
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Qt::WindowFlags PreviewManager::previewWindowFlags(const QWidget *widget) const
|
|
|
|
{
|
|
|
|
#ifdef Q_WS_WIN
|
|
|
|
Qt::WindowFlags windowFlags = (widget->windowType() == Qt::Window) ? Qt::Window | Qt::WindowMaximizeButtonHint : Qt::WindowFlags(Qt::Dialog);
|
|
|
|
#else
|
|
|
|
Q_UNUSED(widget)
|
|
|
|
// Only Dialogs have close buttons on Mac.
|
|
|
|
// On Linux, we don't want an additional task bar item and we don't want a minimize button;
|
|
|
|
// we want the preview to be on top.
|
|
|
|
Qt::WindowFlags windowFlags = Qt::Dialog;
|
|
|
|
#endif
|
|
|
|
return windowFlags;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Some widgets might require fake containers
|
|
|
|
|
|
|
|
static QWidget *fakeContainer(QWidget *w)
|
|
|
|
{
|
|
|
|
// Prevent a dock widget from trying to dock to Designer's main window
|
|
|
|
// (which can be found in the parent hierarchy in MDI mode) by
|
|
|
|
// providing a fake mainwindow
|
|
|
|
if (QDockWidget *dock = qobject_cast<QDockWidget *>(w)) {
|
|
|
|
// Reparent: Clear modality, propagate title and resize outer container
|
|
|
|
const QSize size = w->size();
|
|
|
|
w->setWindowModality(Qt::NonModal);
|
|
|
|
dock->setFeatures(dock->features() & ~(QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetClosable));
|
|
|
|
dock->setAllowedAreas(Qt::LeftDockWidgetArea);
|
|
|
|
QMainWindow *mw = new QMainWindow;
|
|
|
|
int leftMargin, topMargin, rightMargin, bottomMargin;
|
|
|
|
mw->getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
|
|
|
|
mw->addDockWidget(Qt::LeftDockWidgetArea, dock);
|
|
|
|
mw->resize(size + QSize(leftMargin + rightMargin, topMargin + bottomMargin));
|
|
|
|
return mw;
|
|
|
|
}
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PreviewConfiguration configurationFromSettings(QDesignerFormEditorInterface *core, const QString &style)
|
|
|
|
{
|
|
|
|
qdesigner_internal::PreviewConfiguration pc;
|
|
|
|
const QDesignerSharedSettings settings(core);
|
|
|
|
if (settings.isCustomPreviewConfigurationEnabled())
|
|
|
|
pc = settings.customPreviewConfiguration();
|
|
|
|
if (!style.isEmpty())
|
|
|
|
pc.setStyle(style);
|
|
|
|
return pc;
|
|
|
|
}
|
|
|
|
|
|
|
|
QWidget *PreviewManager::showPreview(const QDesignerFormWindowInterface *fw, const QString &style, int deviceProfileIndex, QString *errorMessage)
|
|
|
|
{
|
|
|
|
return showPreview(fw, configurationFromSettings(fw->core(), style), deviceProfileIndex, errorMessage);
|
|
|
|
}
|
|
|
|
|
|
|
|
QWidget *PreviewManager::showPreview(const QDesignerFormWindowInterface *fw, const QString &style, QString *errorMessage)
|
|
|
|
{
|
|
|
|
return showPreview(fw, style, -1, errorMessage);
|
|
|
|
}
|
|
|
|
|
|
|
|
QWidget *PreviewManager::createPreview(const QDesignerFormWindowInterface *fw,
|
|
|
|
const PreviewConfiguration &pc,
|
|
|
|
int deviceProfileIndex,
|
|
|
|
QString *errorMessage,
|
|
|
|
int initialZoom)
|
|
|
|
{
|
|
|
|
if (!d->m_core)
|
|
|
|
d->m_core = fw->core();
|
|
|
|
|
|
|
|
const bool zoomable = initialZoom > 0;
|
|
|
|
// Figure out which profile to apply
|
|
|
|
DeviceProfile deviceProfile;
|
|
|
|
if (deviceProfileIndex >= 0) {
|
|
|
|
deviceProfile = QDesignerSharedSettings(fw->core()).deviceProfileAt(deviceProfileIndex);
|
|
|
|
} else {
|
|
|
|
if (const FormWindowBase *fwb = qobject_cast<const FormWindowBase *>(fw))
|
|
|
|
deviceProfile = fwb->deviceProfile();
|
|
|
|
}
|
|
|
|
// Create
|
|
|
|
QWidget *formWidget = QDesignerFormBuilder::createPreview(fw, pc.style(), pc.applicationStyleSheet(), deviceProfile, errorMessage);
|
|
|
|
if (!formWidget)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
const QString title = tr("%1 - [Preview]").arg(formWidget->windowTitle());
|
|
|
|
formWidget = fakeContainer(formWidget);
|
|
|
|
formWidget->setWindowTitle(title);
|
|
|
|
|
|
|
|
// Clear any modality settings, child widget modalities must not be higher than parent's
|
|
|
|
formWidget->setWindowModality(Qt::NonModal);
|
2019-05-04 17:06:44 +00:00
|
|
|
// Embed into ZoomWidget
|
2015-12-10 05:06:13 +02:00
|
|
|
if (zoomable) {
|
2019-05-04 17:06:44 +00:00
|
|
|
ZoomWidget *zw = new DesignerZoomWidget;
|
|
|
|
connect(zw->zoomMenu(), SIGNAL(zoomChanged(int)), this, SLOT(slotZoomChanged(int)));
|
|
|
|
zw->setWindowTitle(title);
|
|
|
|
zw->setWidget(formWidget);
|
|
|
|
// Keep any widgets' context menus working, do not use global menu
|
|
|
|
zw->setWidgetZoomContextMenuEnabled(true);
|
|
|
|
zw->setParent(fw->window(), previewWindowFlags(formWidget));
|
|
|
|
// Make preview close when Widget closes (Dialog/accept, etc)
|
|
|
|
formWidget->setAttribute(Qt::WA_DeleteOnClose, true);
|
|
|
|
connect(formWidget, SIGNAL(destroyed()), zw, SLOT(close()));
|
|
|
|
zw->setZoom(initialZoom);
|
|
|
|
zw->setProperty(WidgetFactory::disableStyleCustomPaintingPropertyC, QVariant(true));
|
|
|
|
return zw;
|
2015-12-10 05:06:13 +02:00
|
|
|
}
|
2019-05-04 17:06:44 +00:00
|
|
|
formWidget->setParent(fw->window(), previewWindowFlags(formWidget));
|
|
|
|
formWidget->setProperty(WidgetFactory::disableStyleCustomPaintingPropertyC, QVariant(true));
|
|
|
|
return formWidget;
|
2015-12-10 05:06:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QWidget *PreviewManager::showPreview(const QDesignerFormWindowInterface *fw,
|
|
|
|
const PreviewConfiguration &pc,
|
|
|
|
int deviceProfileIndex,
|
|
|
|
QString *errorMessage)
|
|
|
|
{
|
|
|
|
enum { Spacing = 10 };
|
|
|
|
if (QWidget *existingPreviewWidget = raise(fw, pc))
|
|
|
|
return existingPreviewWidget;
|
|
|
|
|
|
|
|
const QDesignerSharedSettings settings(fw->core());
|
|
|
|
const int initialZoom = settings.zoomEnabled() ? settings.zoom() : -1;
|
|
|
|
|
|
|
|
QWidget *widget = createPreview(fw, pc, deviceProfileIndex, errorMessage, initialZoom);
|
|
|
|
if (!widget)
|
|
|
|
return 0;
|
|
|
|
// Install filter for Escape key
|
|
|
|
widget->setAttribute(Qt::WA_DeleteOnClose, true);
|
|
|
|
widget->installEventFilter(this);
|
|
|
|
|
|
|
|
switch (d->m_mode) {
|
|
|
|
case ApplicationModalPreview:
|
|
|
|
// Cannot do this on the Mac as the dialog would have no close button
|
|
|
|
widget->setWindowModality(Qt::ApplicationModal);
|
|
|
|
break;
|
|
|
|
case SingleFormNonModalPreview:
|
|
|
|
case MultipleFormNonModalPreview:
|
|
|
|
widget->setWindowModality(Qt::NonModal);
|
|
|
|
connect(fw, SIGNAL(changed()), widget, SLOT(close()));
|
|
|
|
connect(fw, SIGNAL(destroyed()), widget, SLOT(close()));
|
|
|
|
if (d->m_mode == SingleFormNonModalPreview)
|
|
|
|
connect(fw->core()->formWindowManager(), SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)), widget, SLOT(close()));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Semi-smart algorithm to position previews:
|
|
|
|
// If its the first one, position relative to form.
|
|
|
|
// 2nd, attempt to tile right (for comparing styles) or cascade
|
|
|
|
const QSize size = widget->size();
|
|
|
|
const bool firstPreview = d->m_previews.empty();
|
|
|
|
if (firstPreview) {
|
|
|
|
widget->move(fw->mapToGlobal(QPoint(Spacing, Spacing)));
|
|
|
|
} else {
|
|
|
|
if (QWidget *lastPreview = d->m_previews.back().m_widget) {
|
|
|
|
QDesktopWidget *desktop = qApp->desktop();
|
|
|
|
const QRect lastPreviewGeometry = lastPreview->frameGeometry();
|
|
|
|
const QRect availGeometry = desktop->availableGeometry(desktop->screenNumber(lastPreview));
|
|
|
|
const QPoint newPos = lastPreviewGeometry.topRight() + QPoint(Spacing, 0);
|
|
|
|
if (newPos.x() + size.width() < availGeometry.right())
|
|
|
|
widget->move(newPos);
|
|
|
|
else
|
|
|
|
widget->move(lastPreviewGeometry.topLeft() + QPoint(Spacing, Spacing));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
d->m_previews.push_back(PreviewData(widget, fw, pc));
|
|
|
|
widget->show();
|
|
|
|
if (firstPreview)
|
|
|
|
emit firstPreviewOpened();
|
|
|
|
return widget;
|
|
|
|
}
|
|
|
|
|
|
|
|
QWidget *PreviewManager::raise(const QDesignerFormWindowInterface *fw, const PreviewConfiguration &pc)
|
|
|
|
{
|
|
|
|
typedef PreviewManagerPrivate::PreviewDataList PreviewDataList;
|
|
|
|
if (d->m_previews.empty())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// find matching window
|
|
|
|
const PreviewDataList::const_iterator cend = d->m_previews.constEnd();
|
|
|
|
for (PreviewDataList::const_iterator it = d->m_previews.constBegin(); it != cend ;++it) {
|
|
|
|
QWidget * w = it->m_widget;
|
|
|
|
if (w && it->m_formWindow == fw && it->m_configuration == pc) {
|
|
|
|
w->raise();
|
|
|
|
w->activateWindow();
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PreviewManager::closeAllPreviews()
|
|
|
|
{
|
|
|
|
typedef PreviewManagerPrivate::PreviewDataList PreviewDataList;
|
|
|
|
if (!d->m_previews.empty()) {
|
|
|
|
d->m_updateBlocked = true;
|
|
|
|
d->m_activePreview = 0;
|
|
|
|
const PreviewDataList::iterator cend = d->m_previews.end();
|
|
|
|
for (PreviewDataList::iterator it = d->m_previews.begin(); it != cend ;++it) {
|
|
|
|
if (it->m_widget)
|
|
|
|
it->m_widget->close();
|
|
|
|
}
|
|
|
|
d->m_previews.clear();
|
|
|
|
d->m_updateBlocked = false;
|
|
|
|
emit lastPreviewClosed();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PreviewManager::updatePreviewClosed(QWidget *w)
|
|
|
|
{
|
|
|
|
typedef PreviewManagerPrivate::PreviewDataList PreviewDataList;
|
|
|
|
if (d->m_updateBlocked)
|
|
|
|
return;
|
|
|
|
// Purge out all 0 or widgets to be deleted
|
|
|
|
for (PreviewDataList::iterator it = d->m_previews.begin(); it != d->m_previews.end() ; ) {
|
|
|
|
QWidget *iw = it->m_widget; // Might be 0 when catching QEvent::Destroyed
|
|
|
|
if (iw == 0 || iw == w) {
|
|
|
|
it = d->m_previews.erase(it);
|
|
|
|
} else {
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (d->m_previews.empty())
|
|
|
|
emit lastPreviewClosed();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PreviewManager::eventFilter(QObject *watched, QEvent *event)
|
|
|
|
{
|
|
|
|
// Courtesy of designer
|
|
|
|
do {
|
|
|
|
if (!watched->isWidgetType())
|
|
|
|
break;
|
|
|
|
QWidget *previewWindow = qobject_cast<QWidget *>(watched);
|
|
|
|
if (!previewWindow || !previewWindow->isWindow())
|
|
|
|
break;
|
|
|
|
|
|
|
|
switch (event->type()) {
|
|
|
|
case QEvent::KeyPress:
|
|
|
|
case QEvent::ShortcutOverride: {
|
|
|
|
const QKeyEvent *keyEvent = static_cast<const QKeyEvent *>(event);
|
|
|
|
const int key = keyEvent->key();
|
2016-09-19 18:25:25 +00:00
|
|
|
if (key == Qt::Key_Escape) {
|
2015-12-10 05:06:13 +02:00
|
|
|
previewWindow->close();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case QEvent::WindowActivate:
|
|
|
|
d->m_activePreview = previewWindow;
|
|
|
|
break;
|
|
|
|
case QEvent::Destroy: // We don't get QEvent::Close if someone accepts a QDialog.
|
|
|
|
updatePreviewClosed(previewWindow);
|
|
|
|
break;
|
|
|
|
case QEvent::Close:
|
|
|
|
updatePreviewClosed(previewWindow);
|
|
|
|
previewWindow->removeEventFilter (this);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while(false);
|
|
|
|
return QObject::eventFilter(watched, event);
|
|
|
|
}
|
|
|
|
|
|
|
|
int PreviewManager::previewCount() const
|
|
|
|
{
|
|
|
|
return d->m_previews.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
QPixmap PreviewManager::createPreviewPixmap(const QDesignerFormWindowInterface *fw, const QString &style, int deviceProfileIndex, QString *errorMessage)
|
|
|
|
{
|
|
|
|
return createPreviewPixmap(fw, configurationFromSettings(fw->core(), style), deviceProfileIndex, errorMessage);
|
|
|
|
}
|
|
|
|
|
|
|
|
QPixmap PreviewManager::createPreviewPixmap(const QDesignerFormWindowInterface *fw, const QString &style, QString *errorMessage)
|
|
|
|
{
|
|
|
|
return createPreviewPixmap(fw, style, -1, errorMessage);
|
|
|
|
}
|
|
|
|
|
|
|
|
QPixmap PreviewManager::createPreviewPixmap(const QDesignerFormWindowInterface *fw,
|
|
|
|
const PreviewConfiguration &pc,
|
|
|
|
int deviceProfileIndex,
|
|
|
|
QString *errorMessage)
|
|
|
|
{
|
|
|
|
QWidget *widget = createPreview(fw, pc, deviceProfileIndex, errorMessage);
|
|
|
|
if (!widget)
|
|
|
|
return QPixmap();
|
|
|
|
const QPixmap rc = QPixmap::grabWidget(widget);
|
|
|
|
widget->deleteLater();
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PreviewManager::slotZoomChanged(int z)
|
|
|
|
{
|
|
|
|
if (d->m_core) { // Save the last zoom chosen by the user.
|
|
|
|
QDesignerSharedSettings settings(d->m_core);
|
|
|
|
settings.setZoom(z);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QT_END_NAMESPACE
|
|
|
|
|
|
|
|
#include <moc_previewmanager_p.h>
|