Mercurial > projects > qtd
comparison demos/browser/modelmenu.d @ 73:7bfd46c330dc
more porting
author | mandel |
---|---|
date | Fri, 22 May 2009 10:59:00 +0000 |
parents | 71b382c10ef6 |
children | 37caa90ce503 |
comparison
equal
deleted
inserted
replaced
72:b149ef2cb18b | 73:7bfd46c330dc |
---|---|
36 ** If you are unsure which license is appropriate for your use, please | 36 ** If you are unsure which license is appropriate for your use, please |
37 ** contact the sales department at qt-sales@nokia.com. | 37 ** contact the sales department at qt-sales@nokia.com. |
38 ** $QT_END_LICENSE$ | 38 ** $QT_END_LICENSE$ |
39 ** | 39 ** |
40 ****************************************************************************/ | 40 ****************************************************************************/ |
41 | 41 module modelmenu; |
42 import QtGui.QMenu | 42 |
43 import QtCore.QAbstractItemModel; | 43 |
44 | 44 import qt.gui.QMenu |
45 import modelmenu; | 45 import qt.core.QAbstractItemModel; |
46 | 46 |
47 import QtCore.QAbstractItemModel; | 47 import qt.core.QAbstractItemModel; |
48 import qdebug; | 48 import qdebug; |
49 | |
50 | 49 |
51 | 50 |
52 // A QMenu that is dynamically populated from a QAbstractItemModel | 51 // A QMenu that is dynamically populated from a QAbstractItemModel |
53 class ModelMenu : public QMenu | 52 class ModelMenu : public QMenu |
54 { | 53 { |
55 Q_OBJECT | 54 |
56 | 55 mixin Signal!("activated", QModelIndex index); |
57 signals: | 56 mixin Signal!("hovered", QString text); |
58 void activated(const QModelIndex &index); | |
59 void hovered(const QString &text); | |
60 | 57 |
61 public: | 58 public: |
62 ModelMenu(QWidget *parent = null) | 59 |
63 { | 60 this(QWidget parent = null) |
64 super(parent); | 61 { |
65 m_maxRows = 7; | 62 super(parent); |
66 m_firstSeparator = -1; | 63 m_maxRows = 7; |
67 m_maxWidth = -1; | 64 m_firstSeparator = -1; |
68 m_hoverRole = 0; | 65 m_maxWidth = -1; |
69 m_separatorRole = 0; | 66 m_hoverRole = 0; |
70 m_model = 0; | 67 m_separatorRole = 0; |
71 connect(this, SIGNAL(aboutToShow()), this, SLOT(aboutToShow())); | 68 m_model = 0; |
69 this.aboutToShow.connect(&this.aboutToShow); | |
70 } | |
71 | |
72 void setModel(QAbstractItemModel model) | |
73 { | |
74 m_model = model; | |
75 } | |
76 | |
77 QAbstractItemModel model() | |
78 { | |
79 return m_model; | |
80 } | |
81 | |
82 void setMaxRows(int max) | |
83 { | |
84 m_maxRows = max; | |
85 } | |
86 | |
87 int maxRows() | |
88 { | |
89 return m_maxRows; | |
90 } | |
91 | |
92 void setFirstSeparator(int offset) | |
93 { | |
94 m_firstSeparator = offset; | |
95 } | |
96 | |
97 int firstSeparator() | |
98 { | |
99 return m_firstSeparator; | |
100 } | |
101 | |
102 void setRootIndex(QModelIndex index) | |
103 { | |
104 m_root = index; | |
105 } | |
106 | |
107 QModelIndex rootIndex() | |
108 { | |
109 return m_root; | |
110 } | |
111 | |
112 void setHoverRole(int role) | |
113 { | |
114 m_hoverRole = role; | |
115 } | |
116 | |
117 int hoverRole() | |
118 { | |
119 return m_hoverRole; | |
120 } | |
121 | |
122 void setSeparatorRole(int role) | |
123 { | |
124 m_separatorRole = role; | |
125 } | |
126 | |
127 int separatorRole() | |
128 { | |
129 return m_separatorRole; | |
130 } | |
131 | |
132 QAction makeAction(QIcon icon, QString text, QObject parent); | |
133 { | |
134 QFontMetrics fm(font()); | |
135 if (-1 == m_maxWidth) | |
136 m_maxWidth = fm.width(QLatin1Char('m')) * 30; | |
137 QString smallText = fm.elidedText(text, Qt.ElideMiddle, m_maxWidth); | |
138 return new QAction(icon, smallText, parent); | |
139 } | |
140 | |
141 protected: | |
142 | |
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 } | |
153 | |
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) { | |
158 QString title = parent.data().toString(); | |
159 menu = new QMenu(title, this); | |
160 QIcon icon = qvariant_cast<QIcon>(parent.data(Qt.DecorationRole)); | |
161 menu.setIcon(icon); | |
162 parentMenu.addMenu(menu); | |
163 QVariant v; | |
164 v.setValue(parent); | |
165 menu.menuAction().setData(v); | |
166 connect(menu, SIGNAL(aboutToShow()), this, SLOT(aboutToShow())); | |
167 return; | |
168 } | |
169 | |
170 int end = m_model.rowCount(parent); | |
171 if (max != -1) | |
172 end = qMin(max, end); | |
173 | |
174 menu.triggered.connect(&this.triggered); | |
175 menu.hovered.connect(&this.hovered); | |
176 | |
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 } | |
191 | |
192 private: | |
193 | |
194 void aboutToShow() | |
195 { | |
196 if (QMenu menu = qobject_cast<QMenu>(sender())) { | |
197 QVariant v = menu.menuAction().data(); | |
198 if (v.canConvert<QModelIndex>()) { | |
199 QModelIndex idx = qvariant_cast<QModelIndex>(v); | |
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(); | |
219 if (v.canConvert<QModelIndex>()) { | |
220 QModelIndex idx = qvariant_cast<QModelIndex>(v); | |
221 emit activated(idx); | |
222 } | |
223 } | |
224 | |
225 void hovered(QAction action) | |
226 { | |
227 QVariant v = action.data(); | |
228 if (v.canConvert<QModelIndex>()) { | |
229 QModelIndex idx = qvariant_cast<QModelIndex>(v); | |
230 QString hoveredString = idx.data(m_hoverRole).toString(); | |
231 if (!hoveredString.isEmpty()) | |
232 emit hovered(hoveredString); | |
233 } | |
234 } | |
235 | |
236 private: | |
237 | |
238 QAction makeAction(QModelIndex index); | |
239 { | |
240 QIcon icon = qvariant_cast<QIcon>(index.data(Qt.DecorationRole)); | |
241 QAction action = makeAction(icon, index.data().toString(), this); | |
242 QVariant v; | |
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; | |
72 } | 255 } |
73 | |
74 void setModel(QAbstractItemModel *model) | |
75 { | |
76 m_model = model; | |
77 } | |
78 | |
79 QAbstractItemModel *model() const | |
80 { | |
81 return m_model; | |
82 } | |
83 | |
84 void setMaxRows(int max) | |
85 { | |
86 m_maxRows = max; | |
87 } | |
88 | |
89 int maxRows() const | |
90 { | |
91 return m_maxRows; | |
92 } | |
93 | |
94 void setFirstSeparator(int offset) | |
95 { | |
96 m_firstSeparator = offset; | |
97 } | |
98 | |
99 int firstSeparator() const | |
100 { | |
101 return m_firstSeparator; | |
102 } | |
103 | |
104 void setRootIndex(const QModelIndex &index) | |
105 { | |
106 m_root = index; | |
107 } | |
108 QModelIndex rootIndex() const | |
109 { | |
110 return m_root; | |
111 } | |
112 | |
113 void setHoverRole(int role) | |
114 { | |
115 m_hoverRole = role; | |
116 } | |
117 int hoverRole() const | |
118 { | |
119 return m_hoverRole; | |
120 } | |
121 | |
122 void setSeparatorRole(int role) | |
123 { | |
124 m_separatorRole = role; | |
125 } | |
126 | |
127 int separatorRole() const | |
128 { | |
129 return m_separatorRole; | |
130 } | |
131 | |
132 QAction *makeAction(const QIcon &icon, const QString &text, QObject *parent); | |
133 { | |
134 QFontMetrics fm(font()); | |
135 if (-1 == m_maxWidth) | |
136 m_maxWidth = fm.width(QLatin1Char('m')) * 30; | |
137 QString smallText = fm.elidedText(text, Qt.ElideMiddle, m_maxWidth); | |
138 return new QAction(icon, smallText, parent); | |
139 } | |
140 | |
141 protected: | |
142 // add any actions before the tree, return true if any actions are added. | |
143 virtual bool prePopulated() | |
144 { | |
145 return false; | |
146 } | |
147 // add any actions after the tree | |
148 virtual void postPopulated() | |
149 { | |
150 } | |
151 | |
152 // put all of the children of parent into menu up to max | |
153 void createMenu(const QModelIndex &parent, int max, QMenu *parentMenu = null, QMenu *menu = null) | |
154 { | |
155 if (!menu) { | |
156 QString title = parent.data().toString(); | |
157 menu = new QMenu(title, this); | |
158 QIcon icon = qvariant_cast<QIcon>(parent.data(Qt.DecorationRole)); | |
159 menu.setIcon(icon); | |
160 parentMenu.addMenu(menu); | |
161 QVariant v; | |
162 v.setValue(parent); | |
163 menu.menuAction().setData(v); | |
164 connect(menu, SIGNAL(aboutToShow()), this, SLOT(aboutToShow())); | |
165 return; | |
166 } | |
167 | |
168 int end = m_model.rowCount(parent); | |
169 if (max != -1) | |
170 end = qMin(max, end); | |
171 | |
172 connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(triggered(QAction*))); | |
173 connect(menu, SIGNAL(hovered(QAction*)), this, SLOT(hovered(QAction*))); | |
174 | |
175 for (int i = 0; i < end; ++i) { | |
176 QModelIndex idx = m_model.index(i, 0, parent); | |
177 if (m_model.hasChildren(idx)) { | |
178 createMenu(idx, -1, menu); | |
179 } else { | |
180 if (m_separatorRole != 0 | |
181 && idx.data(m_separatorRole).toBool()) | |
182 addSeparator(); | |
183 else | |
184 menu.addAction(makeAction(idx)); | |
185 } | |
186 if (menu == this && i == m_firstSeparator - 1) | |
187 addSeparator(); | |
188 } | |
189 } | |
190 | |
191 private slots: | |
192 Q_DECLARE_METATYPE(QModelIndex) | |
193 void aboutToShow() | |
194 { | |
195 if (QMenu *menu = qobject_cast<QMenu*>(sender())) { | |
196 QVariant v = menu.menuAction().data(); | |
197 if (v.canConvert<QModelIndex>()) { | |
198 QModelIndex idx = qvariant_cast<QModelIndex>(v); | |
199 createMenu(idx, -1, menu, menu); | |
200 disconnect(menu, SIGNAL(aboutToShow()), this, SLOT(aboutToShow())); | |
201 return; | |
202 } | |
203 } | |
204 | |
205 clear(); | |
206 if (prePopulated()) | |
207 addSeparator(); | |
208 int max = m_maxRows; | |
209 if (max != -1) | |
210 max += m_firstSeparator; | |
211 createMenu(m_root, max, this, this); | |
212 postPopulated(); | |
213 } | |
214 | |
215 | |
216 void triggered(QAction *action) | |
217 { | |
218 QVariant v = action.data(); | |
219 if (v.canConvert<QModelIndex>()) { | |
220 QModelIndex idx = qvariant_cast<QModelIndex>(v); | |
221 emit activated(idx); | |
222 } | |
223 } | |
224 | |
225 void hovered(QAction *action) | |
226 { | |
227 QVariant v = action.data(); | |
228 if (v.canConvert<QModelIndex>()) { | |
229 QModelIndex idx = qvariant_cast<QModelIndex>(v); | |
230 QString hoveredString = idx.data(m_hoverRole).toString(); | |
231 if (!hoveredString.isEmpty()) | |
232 emit hovered(hoveredString); | |
233 } | |
234 } | |
235 | |
236 private: | |
237 QAction *makeAction(const QModelIndex &index); | |
238 { | |
239 QIcon icon = qvariant_cast<QIcon>(index.data(Qt.DecorationRole)); | |
240 QAction *action = makeAction(icon, index.data().toString(), this); | |
241 QVariant v; | |
242 v.setValue(index); | |
243 action.setData(v); | |
244 return action; | |
245 } | |
246 | |
247 int m_maxRows; | |
248 int m_firstSeparator; | |
249 int m_maxWidth; | |
250 int m_hoverRole; | |
251 int m_separatorRole; | |
252 QAbstractItemModel *m_model; | |
253 QPersistentModelIndex m_root; | |
254 } |