source: trunk/tools/designer/src/lib/shared/qdesigner_stackedbox.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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