1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Designer of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 #include "orderdialog_p.h"
30 #include "iconloader_p.h"
31 #include "ui_orderdialog.h"
32 
33 #include <QtDesigner/qextensionmanager.h>
34 #include <QtDesigner/abstractformeditor.h>
35 #include <QtDesigner/container.h>
36 #include <QtCore/qabstractitemmodel.h>
37 #include <QtWidgets/qpushbutton.h>
38 
39 QT_BEGIN_NAMESPACE
40 
41 // OrderDialog: Used to reorder the pages of QStackedWidget and QToolBox.
42 // Provides up and down buttons as well as  DnD via QAbstractItemView::InternalMove mode
43 namespace qdesigner_internal {
44 
OrderDialog(QWidget * parent)45 OrderDialog::OrderDialog(QWidget *parent) :
46     QDialog(parent),
47     m_ui(new Ui::OrderDialog),
48     m_format(PageOrderFormat)
49 {
50     m_ui->setupUi(this);
51     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
52     m_ui->upButton->setIcon(createIconSet(QString::fromUtf8("up.png")));
53     m_ui->downButton->setIcon(createIconSet(QString::fromUtf8("down.png")));
54     m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
55     connect(m_ui->buttonBox->button(QDialogButtonBox::Reset), &QAbstractButton::clicked,
56             this, &OrderDialog::slotReset);
57     // Catch the remove operation of a DnD operation in QAbstractItemView::InternalMove mode to enable buttons
58     // Selection mode is 'contiguous' to enable DnD of groups
59     connect(m_ui->pageList->model(), &QAbstractItemModel::rowsRemoved,
60             this, &OrderDialog::slotEnableButtonsAfterDnD);
61 
62     m_ui->upButton->setEnabled(false);
63     m_ui->downButton->setEnabled(false);
64 }
65 
~OrderDialog()66 OrderDialog::~OrderDialog()
67 {
68     delete  m_ui;
69 }
70 
setDescription(const QString & d)71 void OrderDialog::setDescription(const QString &d)
72 {
73      m_ui->groupBox->setTitle(d);
74 }
75 
setPageList(const QWidgetList & pages)76 void OrderDialog::setPageList(const QWidgetList &pages)
77 {
78     // The QWidget* are stored in a map indexed by the old index.
79     // The old index is set as user data on the item instead of the QWidget*
80     // because DnD is enabled which requires the user data to serializable
81     m_orderMap.clear();
82     const int count = pages.count();
83     for (int i=0; i < count; ++i)
84         m_orderMap.insert(i, pages.at(i));
85     buildList();
86 }
87 
buildList()88 void OrderDialog::buildList()
89 {
90     m_ui->pageList->clear();
91     const OrderMap::const_iterator cend = m_orderMap.constEnd();
92     for (OrderMap::const_iterator it = m_orderMap.constBegin(); it != cend; ++it) {
93         QListWidgetItem *item = new QListWidgetItem();
94         const int index = it.key();
95         switch (m_format) {
96         case PageOrderFormat:
97             item->setText(tr("Index %1 (%2)").arg(index).arg(it.value()->objectName()));
98             break;
99         case TabOrderFormat:
100             item->setText(tr("%1 %2").arg(index+1).arg(it.value()->objectName()));
101             break;
102         }
103         item->setData(Qt::UserRole, QVariant(index));
104         m_ui->pageList->addItem(item);
105     }
106 
107     if (m_ui->pageList->count() > 0)
108         m_ui->pageList->setCurrentRow(0);
109 }
110 
slotReset()111 void OrderDialog::slotReset()
112 {
113     buildList();
114 }
115 
pageList() const116 QWidgetList OrderDialog::pageList() const
117 {
118     QWidgetList rc;
119     const int count = m_ui->pageList->count();
120     for (int i=0; i < count; ++i) {
121         const int oldIndex = m_ui->pageList->item(i)->data(Qt::UserRole).toInt();
122         rc.append(m_orderMap.value(oldIndex));
123     }
124     return rc;
125 }
126 
on_upButton_clicked()127 void OrderDialog::on_upButton_clicked()
128 {
129     const int row = m_ui->pageList->currentRow();
130     if (row <= 0)
131         return;
132 
133     m_ui->pageList->insertItem(row - 1, m_ui->pageList->takeItem(row));
134     m_ui->pageList->setCurrentRow(row - 1);
135 }
136 
on_downButton_clicked()137 void OrderDialog::on_downButton_clicked()
138 {
139     const int row = m_ui->pageList->currentRow();
140     if (row == -1 || row == m_ui->pageList->count() - 1)
141         return;
142 
143     m_ui->pageList->insertItem(row + 1, m_ui->pageList->takeItem(row));
144     m_ui->pageList->setCurrentRow(row + 1);
145 }
146 
slotEnableButtonsAfterDnD()147 void OrderDialog::slotEnableButtonsAfterDnD()
148 {
149     enableButtons(m_ui->pageList->currentRow());
150 }
151 
on_pageList_currentRowChanged(int r)152 void OrderDialog::on_pageList_currentRowChanged(int r)
153 {
154     enableButtons(r);
155 }
156 
enableButtons(int r)157 void OrderDialog::enableButtons(int r)
158 {
159     m_ui->upButton->setEnabled(r > 0);
160     m_ui->downButton->setEnabled(r >= 0 && r < m_ui->pageList->count() - 1);
161 }
162 
pagesOfContainer(const QDesignerFormEditorInterface * core,QWidget * container)163 QWidgetList OrderDialog::pagesOfContainer(const QDesignerFormEditorInterface *core, QWidget *container)
164 {
165     QWidgetList rc;
166     if (QDesignerContainerExtension* ce = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), container)) {
167         const int count = ce->count();
168         for (int i = 0; i < count ;i ++)
169             rc.push_back(ce->widget(i));
170     }
171     return rc;
172 }
173 
174 }
175 
176 QT_END_NAMESPACE
177