Merge lp:~nick-dedekind/ubuntu-ui-toolkit/actionItem-mnemonics into lp:ubuntu-ui-toolkit/staging

Proposed by Nick Dedekind on 2016-12-13
Status: Needs review
Proposed branch: lp:~nick-dedekind/ubuntu-ui-toolkit/actionItem-mnemonics
Merge into: lp:ubuntu-ui-toolkit/staging
Diff against target: 740 lines (+319/-97)
8 files modified
components.api (+8/-1)
src/UbuntuToolkit/ubuntutoolkitmodule.cpp (+2/-0)
src/UbuntuToolkit/ucaction.cpp (+1/-77)
src/UbuntuToolkit/ucaction_p.h (+2/-1)
src/UbuntuToolkit/ucactionitem.cpp (+249/-17)
src/UbuntuToolkit/ucactionitem_p.h (+44/-0)
src/UbuntuToolkit/ucactionitem_p_p.h (+4/-0)
tests/unit/visual/tst_actionitem.11.qml (+9/-1)
To merge this branch: bzr merge lp:~nick-dedekind/ubuntu-ui-toolkit/actionItem-mnemonics
Reviewer Review Type Date Requested Status
Zsombor Egri 2016-12-13 Needs Information on 2016-12-15
Review via email: mp+313115@code.launchpad.net

Commit message

Moved Action mnemonic logic to the ActionItem.

Description of the change

Moved Action mnemonic logic to the ActionItem.
Added ActionItem.mnemonic for altering properties of the mnemonic logic.

To post a comment you must log in.
1329. By Nick Dedekind on 2016-12-13

removed action check

1330. By Nick Dedekind on 2016-12-13

removed extra coment block end

1331. By Nick Dedekind on 2016-12-13

Added mnemonic type

Zsombor Egri (zsombi) wrote :

Mostly clarification I need. Also few more tests to cover the group properties please.

review: Needs Information

Unmerged revisions

1331. By Nick Dedekind on 2016-12-13

Added mnemonic type

1330. By Nick Dedekind on 2016-12-13

removed extra coment block end

1329. By Nick Dedekind on 2016-12-13

removed action check

1328. By Nick Dedekind on 2016-12-13

merged with staging

1327. By Nick Dedekind on 2016-08-25

merged with trunk

1326. By Nick Dedekind on 2016-08-22

added qdoc check

1325. By Nick Dedekind on 2016-08-22

fixed 1.3 version of ActionItem

1324. By Nick Dedekind on 2016-08-22

merged with staging

1323. By Nick Dedekind on 2016-05-23

API fixes

1322. By Nick Dedekind on 2016-05-23

Added mnemonic test

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'components.api'
2--- components.api 2016-09-17 05:48:25 +0000
3+++ components.api 2016-12-13 14:24:00 +0000
4@@ -45,13 +45,14 @@
5 property bool active
6 function addAction(Action action)
7 function removeAction(Action action)
8-Ubuntu.Components.ActionItem 1.0 0.1 UCActionItem: StyledItem
9+Ubuntu.Components.ActionItem 1.3 1.0 0.1 UCActionItem: StyledItem
10 property Action action
11 property string iconName
12 property url iconSource
13 signal triggered(var value)
14 function trigger(var value)
15 function trigger()
16+ readonly property ActionMnemonic mnemonic 1.3
17 property string text
18 Ubuntu.Components.Styles.ActionItemProperties 1.3: QtObject
19 property color backgroundColor
20@@ -79,6 +80,10 @@
21 function removeAction(Action action)
22 function addLocalContext(ActionContext context)
23 function removeLocalContext(ActionContext context)
24+Ubuntu.Components.ActionMnemonic 1.3: QtObject
25+ property int modifier
26+ readonly property StandardKey sequence
27+ property bool visible
28 Ubuntu.Components.Popups.ActionSelectionPopover 1.0 0.1: Popover
29 property var actions
30 property Component delegate
31@@ -1597,6 +1602,7 @@
32 signal triggered(var value)
33 function trigger(var value)
34 function trigger()
35+ readonly property ActionMnemonic mnemonic
36 property string text
37 Ubuntu.Components.ToolbarButton 1.3: StyledItem
38 property Action action
39@@ -1605,6 +1611,7 @@
40 signal triggered(var value)
41 function trigger(var value)
42 function trigger()
43+ readonly property ActionMnemonic mnemonic
44 property string text
45 Ubuntu.Components.ToolbarItems 1.0 0.1: Item
46 property Item back
47
48=== modified file 'src/UbuntuToolkit/ubuntutoolkitmodule.cpp'
49--- src/UbuntuToolkit/ubuntutoolkitmodule.cpp 2016-09-29 10:19:06 +0000
50+++ src/UbuntuToolkit/ubuntutoolkitmodule.cpp 2016-12-13 14:24:00 +0000
51@@ -398,6 +398,8 @@
52 qmlRegisterType<UCMainViewBase>(uri, 1, 3, "MainViewBase");
53 qmlRegisterType<ActionList>(uri, 1, 3, "ActionList");
54 qmlRegisterType<ExclusiveGroup>(uri, 1, 3, "ExclusiveGroup");
55+ qmlRegisterType<UCActionItem, 1>(uri, 1, 3, "ActionItem");
56+ qmlRegisterType<UCActionMnemonic>();
57 }
58
59 void UbuntuToolkitModule::undefineModule()
60
61=== modified file 'src/UbuntuToolkit/ucaction.cpp'
62--- src/UbuntuToolkit/ucaction.cpp 2016-09-20 08:23:40 +0000
63+++ src/UbuntuToolkit/ucaction.cpp 2016-12-13 14:24:00 +0000
64@@ -138,20 +138,6 @@
65 *
66 * Examples: See \l Page
67 *
68- * \section2 Mnemonics
69- * Since Ubuntu.Components 1.3 Action supports mnemonics. Mnemonics are shortcuts
70- * defined in the \l text property, prefixed the shortcut letter with \&. For instance
71- * \c "\&Call" will bint the \c "Alt-C" shortcut to the action. When a mnemonic
72- * is detected on the Action and a keyboard is attached to the device, the \l text
73- * property will provide a formatted text having the mnemonic letter underscored.
74- * \qml
75- * Action {
76- * id: call
77- * iconName: "call"
78- * text: "&Call"
79- * }
80- * \endqml
81- *
82 * \section2 Checkable property
83 * Since Ubuntu.Components 1.3 Action supports the checkable/checked properties.
84 * \qml
85@@ -191,40 +177,10 @@
86 /*!
87 * \qmlproperty string Action::text
88 * The user visible primary label of the action.
89- *
90- * Mnemonics are shortcuts prefixed in the text with \&. If the text has multiple
91- * occurences of the \& character, the first one will be considered for the shortcut.
92- * However \&\& can be used for a single \& in the text, not as a mnemonic.
93- * The \& character cannot be used as shortcut.
94 */
95 QString UCAction::text()
96 {
97- QString displayText(m_text);
98- // if we have a mnemonic, underscore it
99- if (!m_mnemonic.isEmpty()) {
100-
101- QString mnemonic = "&" + m_mnemonic.toString().remove(QStringLiteral("Alt+"));
102- // patch special cases
103- mnemonic.replace(QStringLiteral("Space"), QStringLiteral(" "));
104- int mnemonicIndex = m_text.indexOf(mnemonic);
105- if (mnemonicIndex < 0) {
106- // try lower case
107- mnemonic = mnemonic.toLower();
108- mnemonicIndex = m_text.indexOf(mnemonic);
109- }
110- ACT_TRACE("MNEM" << mnemonic);
111- // FIXME: we need QInputDeviceInfo to detect the keyboard attechment
112- // https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-toolkit/+bug/1276808
113- if (QuickUtils::instance()->keyboardAttached()) {
114- // underscore the character
115- displayText.replace(mnemonicIndex, mnemonic.length(), "<u>" + mnemonic[1] + "</u>");
116- } else {
117- displayText.remove(mnemonicIndex, 1);
118- }
119- }
120- // Escape ampersands
121- displayText.replace(QStringLiteral("&&"), QStringLiteral("&amp;"));
122- return displayText;
123+ return m_text;
124 }
125 void UCAction::setText(const QString &text)
126 {
127@@ -232,7 +188,6 @@
128 return;
129 }
130 m_text = text;
131- setMnemonicFromText(m_text);
132 Q_EMIT textChanged();
133 }
134 void UCAction::resetText()
135@@ -240,25 +195,6 @@
136 setText(QString());
137 }
138
139-void UCAction::setMnemonicFromText(const QString &text)
140-{
141- QKeySequence sequence = QKeySequence::mnemonic(text);
142- if (sequence == m_mnemonic) {
143- return;
144- }
145- if (!m_mnemonic.isEmpty()) {
146- QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(0, this, m_mnemonic);
147- }
148-
149- m_mnemonic = sequence;
150-
151- if (!m_mnemonic.isEmpty()) {
152- ACT_TRACE("MNEMONIC SET" << m_mnemonic.toString());
153- Qt::ShortcutContext context = Qt::WindowShortcut;
154- QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(this, m_mnemonic, context, shortcutContextMatcher);
155- }
156-}
157-
158 /*!
159 * \qmlproperty string Action::keywords
160 * Additional user visible keywords for the action.
161@@ -287,10 +223,6 @@
162 , m_checked(false)
163 {
164 generateName();
165- // FIXME: we need QInputDeviceInfo to detect the keyboard attechment
166- // https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-toolkit/+bug/1276808
167- connect(QuickUtils::instance(), &QuickUtils::keyboardAttachedChanged,
168- this, &UCAction::onKeyboardAttached);
169 }
170
171 UCAction::~UCAction()
172@@ -609,14 +541,6 @@
173 return true;
174 }
175
176-// trigger text changes whenever HW keyboad is attached/detached
177-void UCAction::onKeyboardAttached()
178-{
179- if (!m_mnemonic.isEmpty()) {
180- Q_EMIT textChanged();
181- }
182-}
183-
184 /*!
185 * \qmlmethod Action::trigger(var value)
186 * Checks the \c value against the action \l parameterType and triggers the action.
187
188=== modified file 'src/UbuntuToolkit/ucaction_p.h'
189--- src/UbuntuToolkit/ucaction_p.h 2016-09-09 17:49:07 +0000
190+++ src/UbuntuToolkit/ucaction_p.h 2016-12-13 14:24:00 +0000
191@@ -32,6 +32,8 @@
192
193 UT_NAMESPACE_BEGIN
194
195+Q_DECLARE_LOGGING_CATEGORY(ucAction)
196+
197 // the function detects whether QML has an overridden trigger() slot available
198 // and invokes the one with the appropriate signature
199 template<class T>
200@@ -185,7 +187,6 @@
201 void generateName();
202 void setMnemonicFromText(const QString &text);
203 bool event(QEvent *event) override;
204- void onKeyboardAttached();
205 };
206
207 UT_NAMESPACE_END
208
209=== modified file 'src/UbuntuToolkit/ucactionitem.cpp'
210--- src/UbuntuToolkit/ucactionitem.cpp 2016-09-12 09:03:50 +0000
211+++ src/UbuntuToolkit/ucactionitem.cpp 2016-12-13 14:24:00 +0000
212@@ -15,16 +15,65 @@
213 */
214
215 #include "ucactionitem_p_p.h"
216-
217-#define foreach Q_FOREACH
218-#include <QtQml/private/qqmlbinding_p.h>
219-#undef foreach
220-
221 #include "ucaction_p.h"
222+#include "ucactioncontext_p.h"
223 #include "ucstyleditembase_p_p.h"
224+#include "quickutils_p.h"
225+
226+#include <QtQuick/qquickwindow.h>
227+#include <private/qguiapplication_p.h>
228
229 UT_NAMESPACE_BEGIN
230
231+#define ACT_TRACE(params) qCDebug(ucAction) << params
232+
233+bool itemShortcutContextMatcher(QObject* object, Qt::ShortcutContext context)
234+{
235+ UCActionItem* actionItem = static_cast<UCActionItem*>(object);
236+ UCAction* action = actionItem->action();
237+ if (!action || !action->isEnabled()) {
238+ return false;
239+ }
240+
241+ switch (context) {
242+ case Qt::ApplicationShortcut:
243+ return true;
244+ case Qt::WindowShortcut: {
245+ QObject* window = actionItem->window();
246+ bool activatable = window && window == QGuiApplication::focusWindow();
247+
248+ if (activatable) {
249+ QQuickItem *pl = actionItem;
250+ activatable = false;
251+ while (pl) {
252+ UCActionContextAttached *attached = static_cast<UCActionContextAttached*>(
253+ qmlAttachedPropertiesObject<UCActionContext>(pl, false));
254+ if (attached) {
255+ activatable = attached->context()->active();
256+ if (!activatable) {
257+ ACT_TRACE(action << "Inactive context found" << attached->context());
258+ break;
259+ }
260+ }
261+ pl = pl->parentItem();
262+ }
263+ if (!activatable) {
264+ // check if the action is in an active context
265+ UCActionContext *context = qobject_cast<UCActionContext*>(action->parent());
266+ activatable = context && context->active();
267+ }
268+ }
269+ if (activatable) {
270+ ACT_TRACE("SELECTED ACTION" << action);
271+ }
272+
273+ return activatable;
274+ }
275+ default: break;
276+ }
277+ return false;
278+}
279+
280 UCActionItemPrivate::UCActionItemPrivate()
281 : action(Q_NULLPTR)
282 , flags(0)
283@@ -36,6 +85,9 @@
284 Q_Q(UCActionItem);
285 QObject::connect(q, &UCActionItem::enabledChanged, q, &UCActionItem::enabledChanged2);
286 QObject::connect(q, &UCActionItem::visibleChanged, q, &UCActionItem::visibleChanged2);
287+
288+ QObject::connect(&mnemonic, SIGNAL(visibleChanged()), q, SLOT(_q_textBinding()));
289+ QObject::connect(&mnemonic, SIGNAL(modifierChanged()), q, SLOT(_q_updateMnemonic()));
290 }
291
292 /*!
293@@ -50,6 +102,20 @@
294 * If \l action is set, the values of the other properties will by default
295 * be identical to the \l Action's property values. Setting the other properties
296 * will override the properties copied from the \l Action.
297+ *
298+ * \section2 Mnemonics
299+ * Since Ubuntu.Components 1.3 ActionItem supports mnemonics. Mnemonics are shortcuts
300+ * defined in the \l text property, prefixed the shortcut letter with \&. For instance
301+ * \c "\&Call" will bint the \c "Alt-C" shortcut to the action. When a mnemonic
302+ * is detected on the ActionItem and a keyboard is attached to the device, the \l text
303+ * property will provide a formatted text having the mnemonic letter underscored.
304+ * \qml
305+ * ActionItem {
306+ * id: call
307+ * iconName: "call"
308+ * text: "&Call"
309+ * }
310+ * \endqml
311 */
312
313 /*!
314@@ -60,6 +126,11 @@
315 : UCStyledItemBase(*(new UCActionItemPrivate), parent)
316 {
317 d_func()->init();
318+
319+ // FIXME: we need QInputDeviceInfo to detect the keyboard attechment
320+ // https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-toolkit/+bug/1276808
321+ connect(QuickUtils::instance(), SIGNAL(keyboardAttachedChanged()),
322+ this, SLOT(_q_onKeyboardAttached()), Qt::DirectConnection);
323 }
324
325 UCActionItem::UCActionItem(UCActionItemPrivate &dd, QQuickItem *parent)
326@@ -68,6 +139,29 @@
327 d_func()->init();
328 }
329
330+bool UCActionItem::event(QEvent *e)
331+{
332+ Q_D(UCActionItem);
333+ if (e->type() == QEvent::Shortcut) {
334+ if (!d->action) {
335+ return false;
336+ }
337+
338+ // when we reach this point, we can be sure the Action is used
339+ // by a component belonging to an active ActionContext.
340+ QShortcutEvent *shortcut_event(static_cast<QShortcutEvent*>(e));
341+ if (shortcut_event->isAmbiguous()) {
342+ qmlInfo(this) << "Ambiguous shortcut: " << shortcut_event->key().toString();
343+ return false;
344+ }
345+
346+ // do not call trigger() directly but invoke, as it may get overridden in QML
347+ invokeTrigger<UCAction>(d->action, QVariant());
348+ return true;
349+ }
350+ return UCStyledItemBase::event(e);
351+}
352+
353 bool UCActionItemPrivate::hasBindingOnProperty(const QString &name)
354 {
355 Q_Q(UCActionItem);
356@@ -109,6 +203,51 @@
357 invokeTrigger<UCAction>(action, value);
358 }
359
360+// update the text property
361+void UCActionItemPrivate::_q_textBinding()
362+{
363+ if (flags & CustomText) {
364+ return;
365+ }
366+ _q_updateMnemonic();
367+ Q_EMIT q_func()->textChanged();
368+}
369+
370+// trigger text changes whenever HW keyboad is attached/detached
371+void UCActionItemPrivate::_q_onKeyboardAttached()
372+{
373+ if (!mnemonic.sequence().isEmpty()) {
374+ Q_EMIT q_func()->textChanged();
375+ }
376+}
377+
378+void UCActionItemPrivate::_q_updateMnemonic()
379+{
380+ Q_Q(UCActionItem);
381+
382+ const QString displayText = action ? action->text() : QString();
383+
384+ QKeySequence sequence = QKeySequence::mnemonic(displayText);
385+ if (!sequence.isEmpty()) {
386+ sequence = sequence[0] & ~Qt::ALT; // QKeySequence::mnemonic adds alt.
387+ sequence = sequence[0] | mnemonic.modifier();
388+ }
389+
390+ if (sequence == mnemonic.sequence()) {
391+ return;
392+ }
393+ if (!mnemonic.sequence().isEmpty()) {
394+ QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(0, q, mnemonic.sequence());
395+ }
396+
397+ mnemonic.setSequence(sequence);
398+
399+ if (!sequence.isEmpty()) {
400+ Qt::ShortcutContext context = Qt::WindowShortcut;
401+ QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(q, sequence, context, itemShortcutContextMatcher);
402+ }
403+}
404+
405 // setter called when bindings from QML set the value. Internal functions will
406 // all use the setVisible setter, so initialization and (re)parenting related
407 // visible alteration won't set the custom flag
408@@ -124,12 +263,15 @@
409 setEnabled(enabled);
410 }
411
412+UCActionMnemonic *UCActionItem::mnemonic()
413+{
414+ Q_D(UCActionItem);
415+ return &d->mnemonic;
416+}
417+
418 void UCActionItemPrivate::updateProperties()
419 {
420 Q_Q(UCActionItem);
421- if (!(flags & CustomText)) {
422- Q_EMIT q->textChanged();
423- }
424 if (!(flags & CustomIconSource)) {
425 Q_EMIT q->iconSourceChanged();
426 }
427@@ -154,8 +296,8 @@
428 q, SLOT(_q_enabledBinding()), Qt::DirectConnection);
429 }
430 if (!(flags & CustomText)) {
431- QObject::connect(action, &UCAction::textChanged,
432- q, &UCActionItem::textChanged, Qt::DirectConnection);
433+ QObject::connect(action, SIGNAL(textChanged()),
434+ q, SLOT(_q_textBinding()), Qt::DirectConnection);
435 }
436 if (!(flags & CustomIconSource)) {
437 QObject::connect(action, &UCAction::iconSourceChanged,
438@@ -178,8 +320,8 @@
439 q, SLOT(_q_enabledBinding()));
440 }
441 if (!(flags & CustomText)) {
442- QObject::disconnect(action, &UCAction::textChanged,
443- q, &UCActionItem::textChanged);
444+ QObject::disconnect(action, SIGNAL(textChanged()),
445+ q, SLOT(_q_textBinding()));
446 }
447 if (!(flags & CustomIconSource)) {
448 QObject::disconnect(action, &UCAction::iconSourceChanged,
449@@ -189,6 +331,11 @@
450 QObject::disconnect(action, &UCAction::iconNameChanged,
451 q, &UCActionItem::iconNameChanged);
452 }
453+
454+ if (!mnemonic.sequence().isEmpty()) {
455+ QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(0, q, mnemonic.sequence());
456+ mnemonic.setSequence(QKeySequence());
457+ }
458 }
459 }
460
461@@ -220,12 +367,18 @@
462 }
463 d->_q_visibleBinding();
464 d->_q_enabledBinding();
465+ d->_q_textBinding();
466 d->updateProperties();
467 }
468
469 /*!
470 * \qmlproperty string ActionItem::text
471 * The title of the actionItem. Defaults to the \c action.text.
472+ *
473+ * Mnemonics are shortcuts prefixed in the text with \&. If the text has multiple
474+ * occurences of the \& character, the first one will be considered for the shortcut.
475+ * However \&\& can be used for a single \& in the text, not as a mnemonic.
476+ * The \& character cannot be used as shortcut.
477 */
478 QString UCActionItem::text()
479 {
480@@ -233,7 +386,40 @@
481 if (d->flags & UCActionItemPrivate::CustomText) {
482 return d->text;
483 }
484- return d->action ? d->action->text() : QString();
485+
486+ if (!d->action) {
487+ return QString();
488+ }
489+
490+ QString displayText(d->action->text());
491+
492+ // if we have a mnemonic, underscore it
493+ if (!d->mnemonic.sequence().isEmpty()) {
494+ const QString modifier = QKeySequence(d->mnemonic.modifier()).toString();
495+
496+ QString mnemonic = "&" + d->mnemonic.sequence().toString().remove(modifier);
497+ // patch special cases
498+ mnemonic.replace(QStringLiteral("Space"), QStringLiteral(" "));
499+ int mnemonicIndex = displayText.indexOf(mnemonic);
500+ if (mnemonicIndex < 0) {
501+ // try lower case
502+ mnemonic = mnemonic.toLower();
503+ mnemonicIndex = displayText.indexOf(mnemonic);
504+ }
505+
506+ // FIXME: we need QInputDeviceInfo to detect the keyboard attechment
507+ // https://bugs.launchpad.net/ubuntu/+source/ubuntu-ui-toolkit/+bug/1276808
508+ if (d->mnemonic.visible() && QuickUtils::instance()->keyboardAttached()) {
509+ // underscore the character
510+ displayText.replace(mnemonicIndex, mnemonic.length(), "<u>" + mnemonic[1] + "</u>");
511+ } else {
512+ displayText.remove(mnemonicIndex, 1);
513+ }
514+ }
515+
516+ // Escape ampersands
517+ displayText.replace(QStringLiteral("&&"), QStringLiteral("&amp;"));
518+ return displayText;
519 }
520 void UCActionItem::setText(const QString &text)
521 {
522@@ -241,8 +427,8 @@
523
524 if (d->action && !(d->flags & UCActionItemPrivate::CustomText)) {
525 // disconnect change signal from Action
526- disconnect(d->action, &UCAction::textChanged,
527- this, &UCActionItem::textChanged);
528+ disconnect(d->action, SIGNAL(textChanged()),
529+ this, SLOT(_q_textBinding()));
530 }
531 d->flags |= UCActionItemPrivate::CustomText;
532
533@@ -259,8 +445,8 @@
534 d->flags &= ~UCActionItemPrivate::CustomText;
535 if (d->action) {
536 // re-connect change signal from Action
537- connect(d->action, &UCAction::textChanged,
538- this, &UCActionItem::textChanged, Qt::DirectConnection);
539+ connect(d->action, SIGNAL(textChanged()),
540+ this, SLOT(_q_textBinding()), Qt::DirectConnection);
541 }
542 Q_EMIT textChanged();
543 }
544@@ -382,6 +568,52 @@
545 }
546 }
547
548+UCActionMnemonic::UCActionMnemonic(QObject *parent)
549+ : QObject(parent)
550+ , m_visible(true)
551+ , m_modifier(Qt::ALT)
552+{
553+}
554+
555+bool UCActionMnemonic::visible() const
556+{
557+ return m_visible;
558+}
559+
560+void UCActionMnemonic::setVisible(bool visible)
561+{
562+ if (visible != m_visible) {
563+ m_visible = visible;
564+ Q_EMIT visibleChanged();
565+ }
566+}
567+
568+int UCActionMnemonic::modifier() const
569+{
570+ return m_modifier;
571+}
572+
573+void UCActionMnemonic::setModifier(int modifier)
574+{
575+ if (modifier != m_modifier) {
576+ m_modifier = modifier;
577+ Q_EMIT modifierChanged();
578+ }
579+}
580+
581+const QKeySequence& UCActionMnemonic::sequence() const
582+{
583+ return m_sequence;
584+}
585+
586+void UCActionMnemonic::setSequence(const QKeySequence &sequence)
587+{
588+ if (m_sequence != sequence) {
589+ m_sequence = sequence;
590+ Q_EMIT sequenceChanged();
591+ }
592+}
593+
594 UT_NAMESPACE_END
595
596 #include "moc_ucactionitem_p.cpp"
597
598=== modified file 'src/UbuntuToolkit/ucactionitem_p.h'
599--- src/UbuntuToolkit/ucactionitem_p.h 2016-09-09 17:49:07 +0000
600+++ src/UbuntuToolkit/ucactionitem_p.h 2016-12-13 14:24:00 +0000
601@@ -23,6 +23,7 @@
602
603 class UCAction;
604 class UCActionItemPrivate;
605+class UCActionMnemonic;
606 class UBUNTUTOOLKIT_EXPORT UCActionItem : public UCStyledItemBase
607 {
608 Q_OBJECT
609@@ -35,6 +36,13 @@
610 Q_PROPERTY(QUrl iconSource READ iconSource WRITE setIconSource RESET resetIconSource NOTIFY iconSourceChanged)
611 Q_PROPERTY(QString iconName READ iconName WRITE setIconName RESET resetIconName NOTIFY iconNameChanged)
612
613+ // 1.3
614+#ifndef Q_QDOC
615+ Q_PROPERTY(UT_PREPEND_NAMESPACE(UCActionMnemonic) *mnemonic READ mnemonic CONSTANT FINAL REVISION 1)
616+#else
617+ Q_PROPERTY(UCActionMnemonic *mnemonic READ mnemonic CONSTANT FINAL REVISION 1)
618+#endif
619+
620 // overrides
621 Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled2 NOTIFY enabledChanged2)
622 Q_PROPERTY(bool visible READ isVisible WRITE setVisible2 NOTIFY visibleChanged2 FINAL)
623@@ -56,6 +64,8 @@
624 void setVisible2(bool visible);
625 void setEnabled2(bool enabled);
626
627+ UCActionMnemonic* mnemonic();
628+
629 Q_SIGNALS:
630 void actionChanged();
631 void textChanged();
632@@ -72,10 +82,44 @@
633 protected:
634 UCActionItem(UCActionItemPrivate &, QQuickItem *parent);
635
636+ bool event(QEvent *event) override;
637+
638 Q_DECLARE_PRIVATE(UCActionItem)
639 Q_PRIVATE_SLOT(d_func(), void _q_visibleBinding())
640 Q_PRIVATE_SLOT(d_func(), void _q_enabledBinding())
641 Q_PRIVATE_SLOT(d_func(), void _q_invokeActionTrigger(const QVariant &value))
642+ Q_PRIVATE_SLOT(d_func(), void _q_textBinding())
643+ Q_PRIVATE_SLOT(d_func(), void _q_onKeyboardAttached())
644+ Q_PRIVATE_SLOT(d_func(), void _q_updateMnemonic())
645+};
646+
647+class UBUNTUTOOLKIT_EXPORT UCActionMnemonic : public QObject
648+{
649+ Q_OBJECT
650+ Q_PROPERTY(bool visible READ visible WRITE setVisible NOTIFY visibleChanged)
651+ Q_PROPERTY(int modifier READ modifier WRITE setModifier NOTIFY modifierChanged)
652+ Q_PROPERTY(QKeySequence sequence READ sequence NOTIFY sequenceChanged)
653+public:
654+ UCActionMnemonic(QObject* parent = 0);
655+
656+ bool visible() const;
657+ void setVisible(bool visible);
658+
659+ int modifier() const;
660+ void setModifier(int modifier);
661+
662+ const QKeySequence& sequence() const;
663+ void setSequence(const QKeySequence& sequence);
664+
665+Q_SIGNALS:
666+ void visibleChanged();
667+ void modifierChanged();
668+ void sequenceChanged();
669+
670+private:
671+ bool m_visible;
672+ int m_modifier;
673+ QKeySequence m_sequence;
674 };
675
676 UT_NAMESPACE_END
677
678=== modified file 'src/UbuntuToolkit/ucactionitem_p_p.h'
679--- src/UbuntuToolkit/ucactionitem_p_p.h 2016-09-09 17:49:07 +0000
680+++ src/UbuntuToolkit/ucactionitem_p_p.h 2016-12-13 14:24:00 +0000
681@@ -45,6 +45,9 @@
682 void _q_visibleBinding();
683 void _q_enabledBinding();
684 void _q_invokeActionTrigger(const QVariant &value);
685+ void _q_textBinding();
686+ void _q_onKeyboardAttached();
687+ void _q_updateMnemonic();
688
689 enum {
690 CustomText = 0x01,
691@@ -58,6 +61,7 @@
692 QUrl iconSource;
693 UCAction *action;
694 quint8 flags;
695+ UCActionMnemonic mnemonic;
696 };
697
698 UT_NAMESPACE_END
699
700=== modified file 'tests/unit/visual/tst_actionitem.11.qml'
701--- tests/unit/visual/tst_actionitem.11.qml 2016-06-15 13:46:51 +0000
702+++ tests/unit/visual/tst_actionitem.11.qml 2016-12-13 14:24:00 +0000
703@@ -16,7 +16,7 @@
704
705 import QtQuick 2.0
706 import QtTest 1.0
707-import Ubuntu.Components 1.1
708+import Ubuntu.Components 1.3
709
710 Item {
711 id: main
712@@ -58,6 +58,7 @@
713 Action {
714 id: action2
715 objectName: "action2"
716+ text: "&mnemonicActionText"
717 }
718
719 Loader {
720@@ -86,6 +87,7 @@
721 function cleanup() {
722 loader.sourceComponent = null;
723 item1.action = null;
724+ item1.text = undefined;
725 action1.visible = true;
726 action1.enabled = true;
727 action2.visible = true;
728@@ -116,6 +118,12 @@
729 compare(item1.text, "", "text can be unset")
730 }
731
732+ function test_action_mnemonic() {
733+ QuickUtils.keyboardAttached = true;
734+ item1.action = action2;
735+ compare(item1.text, "<u>m</u>nemonicActionText", "Text uses action text mnemonics");
736+ }
737+
738 // NOTE: This test must be run AFTER test_action(), otherwise setting the action will
739 // will not update the iconSource
740 function test_iconSource() {

Subscribers

People subscribed via source and target branches