45
|
1 /****************************************************************************
|
|
2 **
|
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
4 ** Contact: Qt Software Information (qt-info@nokia.com)
|
|
5 **
|
|
6 ** This file is part of the demonstration applications of the Qt Toolkit.
|
|
7 **
|
|
8 ** $QT_BEGIN_LICENSE:LGPL$
|
|
9 ** Commercial Usage
|
|
10 ** Licensees holding valid Qt Commercial licenses may use this file in
|
|
11 ** accordance with the Qt Commercial License Agreement provided with the
|
|
12 ** Software or, alternatively, in accordance with the terms contained in
|
|
13 ** a written agreement between you and Nokia.
|
|
14 **
|
|
15 ** GNU Lesser General Public License Usage
|
|
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
17 ** General Public License version 2.1 as published by the Free Software
|
|
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
19 ** packaging of this file. Please review the following information to
|
|
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
22 **
|
|
23 ** In addition, as a special exception, Nokia gives you certain
|
|
24 ** additional rights. These rights are described in the Nokia Qt LGPL
|
|
25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
|
|
26 ** 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 are unsure which license is appropriate for your use, please
|
|
37 ** contact the sales department at qt-sales@nokia.com.
|
|
38 ** $QT_END_LICENSE$
|
|
39 **
|
|
40 ****************************************************************************/
|
73
|
41 module modelmenu;
|
45
|
42
|
|
43
|
77
|
44 import qt.gui.QMenu;
|
73
|
45 import qt.core.QAbstractItemModel;
|
45
|
46
|
94
|
47 import qt.core.QPersistentModelIndex;
|
|
48 //import qdebug;
|
45
|
49
|
|
50
|
|
51 // A QMenu that is dynamically populated from a QAbstractItemModel
|
|
52 class ModelMenu : public QMenu
|
|
53 {
|
77
|
54
|
74
|
55 mixin Signal!("activated", QModelIndex /*index*/);
|
94
|
56 mixin Signal!("linkHovered", string /*text*/);
|
45
|
57
|
|
58 public:
|
|
59
|
73
|
60 this(QWidget parent = null)
|
|
61 {
|
|
62 super(parent);
|
|
63 m_maxRows = 7;
|
|
64 m_firstSeparator = -1;
|
|
65 m_maxWidth = -1;
|
|
66 m_hoverRole = 0;
|
|
67 m_separatorRole = 0;
|
|
68 m_model = 0;
|
|
69 this.aboutToShow.connect(&this.aboutToShow);
|
|
70 }
|
|
71
|
|
72 void setModel(QAbstractItemModel model)
|
|
73 {
|
|
74 m_model = model;
|
|
75 }
|
45
|
76
|
73
|
77 QAbstractItemModel model()
|
|
78 {
|
|
79 return m_model;
|
|
80 }
|
45
|
81
|
73
|
82 void setMaxRows(int max)
|
|
83 {
|
|
84 m_maxRows = max;
|
|
85 }
|
45
|
86
|
73
|
87 int maxRows()
|
|
88 {
|
|
89 return m_maxRows;
|
|
90 }
|
45
|
91
|
73
|
92 void setFirstSeparator(int offset)
|
|
93 {
|
|
94 m_firstSeparator = offset;
|
|
95 }
|
45
|
96
|
73
|
97 int firstSeparator()
|
|
98 {
|
|
99 return m_firstSeparator;
|
|
100 }
|
45
|
101
|
73
|
102 void setRootIndex(QModelIndex index)
|
|
103 {
|
|
104 m_root = index;
|
|
105 }
|
|
106
|
|
107 QModelIndex rootIndex()
|
|
108 {
|
|
109 return m_root;
|
|
110 }
|
45
|
111
|
73
|
112 void setHoverRole(int role)
|
|
113 {
|
|
114 m_hoverRole = role;
|
|
115 }
|
|
116
|
|
117 int hoverRole()
|
|
118 {
|
|
119 return m_hoverRole;
|
|
120 }
|
45
|
121
|
73
|
122 void setSeparatorRole(int role)
|
|
123 {
|
|
124 m_separatorRole = role;
|
|
125 }
|
45
|
126
|
73
|
127 int separatorRole()
|
|
128 {
|
|
129 return m_separatorRole;
|
|
130 }
|
|
131
|
77
|
132 QAction makeAction(QIcon icon, string text, QObject parent)
|
73
|
133 {
|
74
|
134 auto fm = new QFontMetrics(font());
|
73
|
135 if (-1 == m_maxWidth)
|
|
136 m_maxWidth = fm.width(QLatin1Char('m')) * 30;
|
77
|
137 string smallText = fm.elidedText(text, Qt.ElideMiddle, m_maxWidth);
|
73
|
138 return new QAction(icon, smallText, parent);
|
|
139 }
|
45
|
140
|
|
141 protected:
|
|
142
|
73
|
143 // add any actions before the tree, return true if any actions are added.
|
|
144 bool prePopulated()
|
|
145 {
|
|
146 return false;
|
|
147 }
|
|
148
|
|
149 // add any actions after the tree
|
|
150 void postPopulated()
|
|
151 {
|
|
152 }
|
45
|
153
|
73
|
154 // put all of the children of parent into menu up to max
|
|
155 void createMenu(QModelIndex parent, int max, QMenu parentMenu = null, QMenu menu = null)
|
|
156 {
|
|
157 if (!menu) {
|
77
|
158 string title = parent.data().toString();
|
73
|
159 menu = new QMenu(title, this);
|
77
|
160 QIcon icon = cast(QIcon) parent.data(Qt.DecorationRole);
|
73
|
161 menu.setIcon(icon);
|
|
162 parentMenu.addMenu(menu);
|
94
|
163 auto v = new QVariant;
|
73
|
164 v.setValue(parent);
|
|
165 menu.menuAction().setData(v);
|
94
|
166 menu.aboutToShow.connect(&this.aboutToShow);
|
73
|
167 return;
|
|
168 }
|
45
|
169
|
73
|
170 int end = m_model.rowCount(parent);
|
|
171 if (max != -1)
|
|
172 end = qMin(max, end);
|
45
|
173
|
73
|
174 menu.triggered.connect(&this.triggered);
|
94
|
175 menu.linkHovered.connect(&this.linkHovered);
|
45
|
176
|
73
|
177 for (int i = 0; i < end; ++i) {
|
|
178 QModelIndex idx = m_model.index(i, 0, parent);
|
|
179 if (m_model.hasChildren(idx)) {
|
|
180 createMenu(idx, -1, menu);
|
|
181 } else {
|
|
182 if (m_separatorRole != 0 && idx.data(m_separatorRole).toBool())
|
|
183 addSeparator();
|
|
184 else
|
|
185 menu.addAction(makeAction(idx));
|
|
186 }
|
|
187 if (menu == this && i == m_firstSeparator - 1)
|
|
188 addSeparator();
|
|
189 }
|
|
190 }
|
45
|
191
|
|
192 private:
|
73
|
193
|
|
194 void aboutToShow()
|
|
195 {
|
77
|
196 if (QMenu menu = cast(QMenu) signalSender()) {
|
73
|
197 QVariant v = menu.menuAction().data();
|
77
|
198 if (v.canConvert!(QModelIndex)()) {
|
|
199 QModelIndex idx = cast(QModelIndex) v;
|
73
|
200 createMenu(idx, -1, menu, menu);
|
|
201 menu.aboutToShow.disconnect(&this.aboutToShow);
|
|
202 return;
|
|
203 }
|
|
204 }
|
|
205
|
|
206 clear();
|
|
207 if (prePopulated())
|
|
208 addSeparator();
|
|
209 int max = m_maxRows;
|
|
210 if (max != -1)
|
|
211 max += m_firstSeparator;
|
|
212 createMenu(m_root, max, this, this);
|
|
213 postPopulated();
|
|
214 }
|
|
215
|
|
216 void triggered(QAction action)
|
|
217 {
|
|
218 QVariant v = action.data();
|
77
|
219 if (v.canConvert!(QModelIndex)()) {
|
|
220 QModelIndex idx = cast(QModelIndex) v;
|
|
221 activated.emit(idx);
|
73
|
222 }
|
|
223 }
|
|
224
|
94
|
225 void linkHovered(QAction action)
|
73
|
226 {
|
|
227 QVariant v = action.data();
|
77
|
228 if (v.canConvert!(QModelIndex)()) {
|
|
229 QModelIndex idx = cast(QModelIndex) v;
|
|
230 string hoveredString = idx.data(m_hoverRole).toString();
|
73
|
231 if (!hoveredString.isEmpty())
|
94
|
232 linkHovered.emit(hoveredString);
|
73
|
233 }
|
|
234 }
|
|
235
|
|
236 private:
|
|
237
|
74
|
238 QAction makeAction(QModelIndex index)
|
73
|
239 {
|
74
|
240 QIcon icon = cast(QIcon) index.data(Qt.DecorationRole);
|
73
|
241 QAction action = makeAction(icon, index.data().toString(), this);
|
94
|
242 auto v = new QVariant;
|
73
|
243 v.setValue(index);
|
|
244 action.setData(v);
|
|
245 return action;
|
|
246 }
|
|
247
|
|
248 int m_maxRows;
|
|
249 int m_firstSeparator;
|
|
250 int m_maxWidth;
|
|
251 int m_hoverRole;
|
|
252 int m_separatorRole;
|
|
253 QAbstractItemModel m_model;
|
|
254 QPersistentModelIndex m_root;
|
45
|
255 }
|