4 #include "gui/menus/menuaction.h"
11 #include <QStringList>
21 namespace swift::gui::menus
23 CMenuAction::CMenuAction(
const QIcon &icon,
const QString &title,
const QString &path,
bool separator)
24 : m_icon(icon), m_title(title), m_path(path.trimmed()), m_separator(separator)
30 : m_action(action), m_icon(action->icon()), m_title(action->text()), m_path(path.trimmed()),
31 m_separator(separator)
36 if (!m_action) {
return false; }
42 if (m_action) { m_action->
setChecked(checked); }
47 if (!m_action) {
return false; }
53 if (m_action) { m_action->
setEnabled(enabled); }
68 Q_ASSERT_X(m_action, Q_FUNC_INFO,
"No action");
80 static const CMenuAction subdir(CIcons::appModels16(),
"Consolidate models",
93 static const CMenuAction subdir(CIcons::appAircraft16(),
"Render models",
100 static const CMenuAction subdir(CIcons::appAircraft16(),
"Display models",
107 static const CMenuAction subdir(CIcons::appAircraft16(),
"Data transfer",
122 if (m_path.
endsWith(
'/')) {
return {}; }
124 return m_path.
mid(i + 1);
133 std::reverse(myActions.begin(), myActions.end());
136 if (action.isSeparator()) { actions.
append(action); }
137 else if (action.isSubMenu() || !action.getQAction()) { menus.
append(action); }
140 if (action.isCheckableQAction()) { checkableActions.
append(action); }
141 else { actions.
append(action); }
144 actions.
append(checkableActions);
166 if (a.isSubMenu() || !a.getQAction()) { menuActions.
append(a); }
173 if (!m_actions.contains(path)) {
return false; }
199 Q_ASSERT_X(exisitingMenu.
size() > 1, Q_FUNC_INFO,
"Redundant menu entries");
200 Q_ASSERT_X(existingAction.
getTitle() != title, Q_FUNC_INFO,
"Title mismatch");
202 return existingAction;
212 Q_ASSERT_X(!menuAction.
getPath().
isEmpty(), Q_FUNC_INFO,
"Need path");
213 m_actions.insert(menuAction.
getPath(), menuAction);
221 for (
const CMenuAction &action : actions.m_actions)
250 if (action) {
return this->
addAction(action, path); }
251 return this->
addAction(text, path, slot, shortcut);
257 if (action) {
return this->
addAction(action, path); }
258 return this->
addAction(text, path, actionOwner, slot, shortcut);
264 if (action) {
return this->
addAction(action, path); }
265 return this->
addAction(icon, text, path, slot, shortcut);
271 if (action) {
return this->
addAction(action, path); }
272 Q_ASSERT_X(actionOwner, Q_FUNC_INFO,
"Need action owner");
273 return this->
addAction(icon, text, path, actionOwner, slot, shortcut);
279 return this->
addAction(
QIcon(), text, path, actionOwner, shortcut);
286 actionIcon.
isNull() ?
new QAction(text, actionOwner) :
new QAction(actionIcon, text, actionOwner);
305 return this->
addAction(actionIcon, text, path,
nullptr);
311 return this->
addAction(actionIcon, text, path, slot.object(), slot, shortcut);
317 return this->
addAction(
QIcon(), text, path, slot.object(), slot, shortcut);
323 return this->
addAction(
QIcon(), text, path, actionOwner, slot, shortcut);
328 if (m_actions.isEmpty()) {
return; }
334 for (
const QString &key : keys)
336 bool handledSeparator =
false;
337 const int pathDepth = CMenuActions::pathDepth(key);
341 this->splitSubMenus(key, actions, menus);
347 if (!menu.
isEmpty() && separateGroups)
351 (isSameKeyRoot(key, lastKey));
353 handledSeparator =
true;
356 int noActionsWithoutPath = 0;
357 QMenu *currentMenu =
nullptr;
360 for (
const CMenuAction &menuAction : std::as_const(actions))
365 currentMenu = currentMenuForAction(menu, menuAction, menus, subMenus, key, pathDepth);
367 Q_ASSERT_X(currentMenu, Q_FUNC_INFO,
"Missing menu");
368 Q_ASSERT_X(menuAction.isSubMenu() || menuAction.isSeparator() || menuAction.getQAction(), Q_FUNC_INFO,
371 if (menuAction.isSeparator())
378 if (menuAction.hasNoPath())
380 noActionsWithoutPath++;
383 if ((!handledSeparator || noActionsWithoutPath > 1) && menuAction.hasNoPathWithSeparator())
386 handledSeparator =
false;
391 currentMenu->
addAction(menuAction.getQAction());
394 if (menuAction.getQAction() && !menuAction.getQAction()->parent())
396 menuAction.getQAction()->
setParent(&menu);
416 if (!a.getQAction()) {
continue; }
417 qActions.
append(a.getQAction());
437 const bool canConnectDb =
439 const QString text(canConnectDb ?
"Stash tools" :
"Stash tools (Warning: no DB!)");
493 const QString &key,
int pathDepth)
495 if (pathDepth < 1) {
return &menu; }
496 QMenu *parentMenu = &menu;
501 parentMenu = findUpwardsInMenus(key, subMenus);
502 if (!parentMenu) { parentMenu = &menu; }
506 QMenu *subMenu =
nullptr;
510 const CMenuAction menuFound(menus.
first());
511 subMenu = parentMenu->
addMenu(menuFound.getIcon(), menuFound.getTitle());
513 Q_ASSERT_X(subMenu, Q_FUNC_INFO,
"Could not create sub menu");
515 if (subMenu) { subMenu->
setParent(parentMenu); }
517 if (pathDepth > 0 && subMenu) { subMenus.
insert(key, subMenu); }
521 int CMenuActions::pathDepth(
const QString &path)
523 if (path.
isEmpty()) {
return 0; }
524 int c = path.
count(
'/');
525 return c > 0 ? c : 0;
530 if (!currentPath.
contains(
'/')) {
return {}; }
532 return currentPath.
left(i);
538 if (i < 0) {
return {}; }
542 bool CMenuActions::isSameKeyRoot(
const QString &key1,
const QString &key2)
545 if (i1 < 0) {
return false; }
547 if (i2 < 0 || i1 != i2) {
return false; }
548 return key1.
left(i1) == key2.
left(i2);
556 if (menus.
contains(k)) {
return menus[k]; }
CWebDataServices * getWebDataServices() const
Get the web data services.
bool hasSuccesfullyConnectedSwiftDb() const
Has already successfully connect swift DB?
Callable wrapper for a member function with function signature F.
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
Free functions in swift::misc.
bool isCheckable() const const
bool isEnabled() const const
void setShortcut(const QKeySequence &shortcut)
void triggered(bool checked)
QSize actualSize(QWindow *window, const QSize &size, QIcon::Mode mode, QIcon::State state) const const
QPixmap pixmap(QWindow *window, const QSize &size, QIcon::Mode mode, QIcon::State state) const const
bool isNull() const const
void append(QList< T > &&value)
bool isEmpty() const const
qsizetype size() const const
bool contains(const Key &key) const const
QMap< Key, T >::iterator insert(QMap< Key, T >::const_iterator pos, const Key &key, const T &value)
bool isEmpty() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void setParent(QObject *parent)
qsizetype count() const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype lastIndexOf(QChar ch, Qt::CaseSensitivity cs) const const
QString left(qsizetype n) &&
QString mid(qsizetype position, qsizetype n) &&