From 051aec272993820e23969e35fb61050ce9a112cd Mon Sep 17 00:00:00 2001 From: Aesylwinn Date: Mon, 25 Jul 2016 20:49:09 -0400 Subject: [PATCH] Added methods to keep text mentioning shortcuts up to date, fixed potential issue with widget relationship tracking, hopefully got rid of signed/unsigned errors (Qt4/5 issue) --- apps/opencs/model/prefs/shortcut.cpp | 29 +++++++ apps/opencs/model/prefs/shortcut.hpp | 11 +++ .../model/prefs/shortcuteventhandler.cpp | 1 + apps/opencs/model/prefs/shortcutmanager.cpp | 2 +- apps/opencs/view/doc/view.cpp | 1 + apps/opencs/view/render/orbitcameramode.cpp | 4 +- apps/opencs/view/render/worldspacewidget.cpp | 28 ++++--- apps/opencs/view/widget/pushbutton.cpp | 84 ++++++++++++++++++- apps/opencs/view/widget/pushbutton.hpp | 9 ++ apps/opencs/view/widget/scenetoolmode.cpp | 11 +++ apps/opencs/view/widget/scenetoolmode.hpp | 5 ++ 11 files changed, 168 insertions(+), 17 deletions(-) diff --git a/apps/opencs/model/prefs/shortcut.cpp b/apps/opencs/model/prefs/shortcut.cpp index c0682fed3..05f016604 100644 --- a/apps/opencs/model/prefs/shortcut.cpp +++ b/apps/opencs/model/prefs/shortcut.cpp @@ -2,6 +2,7 @@ #include +#include #include #include "state.hpp" @@ -19,6 +20,7 @@ namespace CSMPrefs , mLastPos(0) , mActivationStatus(AS_Inactive) , mModifierStatus(false) + , mAction(0) { assert (parent); @@ -38,6 +40,7 @@ namespace CSMPrefs , mLastPos(0) , mActivationStatus(AS_Inactive) , mModifierStatus(false) + , mAction(0) { assert (parent); @@ -107,6 +110,9 @@ namespace CSMPrefs mSequence = sequence; mCurrentPos = 0; mLastPos = sequence.count() - 1; + + if (mAction) + mAction->setText(mActionText + "\t" + toString()); } void Shortcut::setModifier(int modifier) @@ -129,6 +135,24 @@ namespace CSMPrefs mModifierStatus = status; } + void Shortcut::associateAction(QAction* action) + { + if (mAction) + { + disconnect(this, SLOT(actionDeleted())); + } + + mAction = action; + + if (mAction) + { + mActionText = mAction->text(); + mAction->setText(mActionText + "\t" + toString()); + + connect(mAction, SIGNAL(destroyed()), this, SLOT(actionDeleted())); + } + } + void Shortcut::signalActivated(bool state) { emit activated(state); @@ -152,4 +176,9 @@ namespace CSMPrefs { return QString(State::get().getShortcutManager().sequenceToString(std::make_pair(mSequence, mModifier)).data()); } + + void Shortcut::actionDeleted() + { + mAction = 0; + } } diff --git a/apps/opencs/model/prefs/shortcut.hpp b/apps/opencs/model/prefs/shortcut.hpp index 2df47f382..fa68e6f19 100644 --- a/apps/opencs/model/prefs/shortcut.hpp +++ b/apps/opencs/model/prefs/shortcut.hpp @@ -7,6 +7,7 @@ #include #include +class QAction; class QWidget; namespace CSMPrefs @@ -64,6 +65,9 @@ namespace CSMPrefs void setActivationStatus(ActivationStatus status); void setModifierStatus(bool status); + /// Appends the sequence to the QAction text, also keeps it up to date + void associateAction(QAction* action); + // Workaround for Qt4 signals being "protected" void signalActivated(bool state); void signalActivated(); @@ -88,6 +92,13 @@ namespace CSMPrefs ActivationStatus mActivationStatus; bool mModifierStatus; + QAction* mAction; + QString mActionText; + + private slots: + + void actionDeleted(); + signals: /// Triggered when the shortcut is activated or deactivated; can be determined from \p state diff --git a/apps/opencs/model/prefs/shortcuteventhandler.cpp b/apps/opencs/model/prefs/shortcuteventhandler.cpp index 341881367..93e2d85d3 100644 --- a/apps/opencs/model/prefs/shortcuteventhandler.cpp +++ b/apps/opencs/model/prefs/shortcuteventhandler.cpp @@ -137,6 +137,7 @@ namespace CSMPrefs if (parentIt != mWidgetShortcuts.end()) { mChildParentRelations.insert(std::make_pair(widget, parent)); + updateParent(parent); break; } diff --git a/apps/opencs/model/prefs/shortcutmanager.cpp b/apps/opencs/model/prefs/shortcutmanager.cpp index 300c2b61a..fff81fedc 100644 --- a/apps/opencs/model/prefs/shortcutmanager.cpp +++ b/apps/opencs/model/prefs/shortcutmanager.cpp @@ -92,7 +92,7 @@ namespace CSMPrefs std::string output; // KeySequence - for (int i = 0; i < data.first.count(); ++i) + for (int i = 0; i < (int)data.first.count(); ++i) { if (data.first[i] & ModMask) { diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index bc4230dfd..4e857db6c 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -64,6 +64,7 @@ void CSVDoc::View::setupFileMenu() file->addAction (mSave); CSMPrefs::Shortcut* saveShortcut = new CSMPrefs::Shortcut("document-save", this); + saveShortcut->associateAction(mSave); connect (saveShortcut, SIGNAL(activated()), this, SLOT(save())); mVerify = new QAction (tr ("&Verify"), this); diff --git a/apps/opencs/view/render/orbitcameramode.cpp b/apps/opencs/view/render/orbitcameramode.cpp index 286bab3e4..c7d980454 100644 --- a/apps/opencs/view/render/orbitcameramode.cpp +++ b/apps/opencs/view/render/orbitcameramode.cpp @@ -26,7 +26,8 @@ namespace CSVRender void OrbitCameraMode::activate(CSVWidget::SceneToolbar* toolbar) { - mCenterOnSelection = new QAction("Center on selected object\t" + mCenterShortcut->toString(), this); + mCenterOnSelection = new QAction("Center on selected object", this); + mCenterShortcut->associateAction(mCenterOnSelection); connect(mCenterOnSelection, SIGNAL(triggered()), this, SLOT(centerSelection())); mCenterShortcut->enable(true); @@ -34,6 +35,7 @@ namespace CSVRender void OrbitCameraMode::deactivate(CSVWidget::SceneToolbar* toolbar) { + mCenterShortcut->associateAction(0); mCenterShortcut->enable(false); } diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index fa2a755f2..dda665c31 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -163,30 +163,32 @@ CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector ( /// \todo consider user-defined button-mapping tool->addButton (":scenetoolbar/1st-person", "1st", "First Person" - "
  • Mouse-Look while holding the left button
  • " - "
  • WASD movement keys
  • " + "
    • Camera is held upright
    • " + "
    • Mouse-Look while holding {scene-navi-primary}
    • " + "
    • Movement keys: {free-forward}(forward), {free-left}(left), {free-backward}(back), {free-right}(right)
    • " + "
    • Strafing (also vertically) by holding {scene-navi-secondary}
    • " "
    • Mouse wheel moves the camera forward/backward
    • " - "
    • Strafing (also vertically) by holding the left mouse button and control
    • " - "
    • Camera is held upright
    • " - "
    • Hold shift to speed up movement
    • " + "
    • Hold {free-forward:mod} to speed up movement
    • " "
    "); tool->addButton (":scenetoolbar/free-camera", "free", "Free Camera" - "
    • Mouse-Look while holding the left button
    • " - "
    • Strafing (also vertically) via WASD or by holding the left mouse button and control
    • " + "
      • Mouse-Look while holding {scene-navi-primary}
      • " + "
      • Movement keys: {free-forward}(forward), {free-left}(left), {free-backward}(back), {free-right}(right)
      • " + "
      • Roll camera with {free-roll-left} and {free-roll-right} keys
      • " + "
      • Strafing (also vertically) by holding {scene-navi-secondary}
      • " "
      • Mouse wheel moves the camera forward/backward
      • " - "
      • Roll camera with Q and E keys
      • " - "
      • Hold shift to speed up movement
      • " + "
      • Hold {free-forward:mod} to speed up movement
      • " "
      "); tool->addButton( new CSVRender::OrbitCameraMode(this, QIcon(":scenetoolbar/orbiting-camera"), "Orbiting Camera" "
      • Always facing the centre point
      • " - "
      • Rotate around the centre point via WASD or by moving the mouse while holding the left button
      • " + "
      • Rotate around the centre point via {orbit-up}, {orbit-left}, {orbit-down}, {orbit-right} or by moving " + "the mouse while holding {scene-navi-primary}
      • " + "
      • Roll camera with {orbit-roll-left} and {orbit-roll-right} keys
      • " + "
      • Strafing (also vertically) by holding {scene-navi-secondary} (includes relocation of the centre point)
      • " "
      • Mouse wheel moves camera away or towards centre point but can not pass through it
      • " - "
      • Roll camera with Q and E keys
      • " - "
      • Strafing (also vertically) by holding the left mouse button and control (includes relocation of the centre point)
      • " - "
      • Hold shift to speed up movement
      • " + "
      • Hold {orbit-up:mod} to speed up movement
      • " "
      ", tool), "orbit"); diff --git a/apps/opencs/view/widget/pushbutton.cpp b/apps/opencs/view/widget/pushbutton.cpp index 424aaf68a..100f3bd43 100644 --- a/apps/opencs/view/widget/pushbutton.cpp +++ b/apps/opencs/view/widget/pushbutton.cpp @@ -3,9 +3,75 @@ #include #include +#include "../../model/prefs/state.hpp" + +void CSVWidget::PushButton::processShortcuts() +{ + const QChar SequenceStart = '{'; + const QChar SequenceEnd = '}'; + const QString ModifierSequence = QString::fromUtf8(":mod"); + + const QChar SettingSeparator = ';'; + + QStringList substrings; + + int prevIndex = 0; + int startIndex = mToolTip.indexOf(SequenceStart); + int endIndex = (startIndex != -1) ? mToolTip.indexOf(SequenceEnd, startIndex) : -1; + + // Process every valid shortcut escape sequence + while (startIndex != -1 && endIndex != -1) + { + int count = startIndex - prevIndex; + if (count > 0) + { + substrings.push_back(mToolTip.mid(prevIndex, count)); + } + + // Find sequence name + count = endIndex - startIndex - 1; + if (count > 0) + { + // Check if looking for modifier + int separatorIndex = mToolTip.indexOf(ModifierSequence, startIndex); + if (separatorIndex != -1 && separatorIndex < endIndex) + { + count = separatorIndex - startIndex - 1; + + QString settingName = mToolTip.mid(startIndex+1, count); + QString value = QString::fromUtf8( + CSMPrefs::State::get()["Key Bindings"][settingName.toUtf8().data()].toString().c_str()); + + substrings.push_back(value.right(value.size() - value.indexOf(SettingSeparator) - 1)); + } + else + { + QString settingName = mToolTip.mid(startIndex+1, count); + QString value = QString::fromUtf8( + CSMPrefs::State::get()["Key Bindings"][settingName.toUtf8().data()].toString().c_str()); + + // Don't want modifier + substrings.push_back(value.left(value.indexOf(SettingSeparator))); + } + + prevIndex = endIndex + 1; + } + + startIndex = mToolTip.indexOf(SequenceStart, endIndex); + endIndex = (startIndex != -1) ? mToolTip.indexOf(SequenceEnd, startIndex) : -1; + } + + if (prevIndex < mToolTip.size()) + { + substrings.push_back(mToolTip.mid(prevIndex)); + } + + mProcessedToolTip = substrings.join(""); +} + void CSVWidget::PushButton::setExtendedToolTip() { - QString tooltip = mToolTip; + QString tooltip = mProcessedToolTip; if (tooltip.isEmpty()) tooltip = "(Tool tip not implemented yet)"; @@ -77,13 +143,18 @@ CSVWidget::PushButton::PushButton (const QIcon& icon, Type type, const QString& connect (this, SIGNAL (toggled (bool)), this, SLOT (checkedStateChanged (bool))); } setCheckable (type==Type_Mode || type==Type_Toggle); + processShortcuts(); setExtendedToolTip(); + + connect (&CSMPrefs::State::get(), SIGNAL (settingChanged (const CSMPrefs::Setting *)), + this, SLOT (settingChanged (const CSMPrefs::Setting *))); } CSVWidget::PushButton::PushButton (Type type, const QString& tooltip, QWidget *parent) : QPushButton (parent), mKeepOpen (false), mType (type), mToolTip (tooltip) { setCheckable (type==Type_Mode || type==Type_Toggle); + processShortcuts(); setExtendedToolTip(); } @@ -94,7 +165,7 @@ bool CSVWidget::PushButton::hasKeepOpen() const QString CSVWidget::PushButton::getBaseToolTip() const { - return mToolTip; + return mProcessedToolTip; } CSVWidget::PushButton::Type CSVWidget::PushButton::getType() const @@ -106,3 +177,12 @@ void CSVWidget::PushButton::checkedStateChanged (bool checked) { setExtendedToolTip(); } + +void CSVWidget::PushButton::settingChanged (const CSMPrefs::Setting *setting) +{ + if (setting->getParent()->getKey() == "Key Bindings") + { + processShortcuts(); + setExtendedToolTip(); + } +} diff --git a/apps/opencs/view/widget/pushbutton.hpp b/apps/opencs/view/widget/pushbutton.hpp index 09cf22757..65df1b7e3 100644 --- a/apps/opencs/view/widget/pushbutton.hpp +++ b/apps/opencs/view/widget/pushbutton.hpp @@ -3,6 +3,11 @@ #include +namespace CSMPrefs +{ + class Setting; +} + namespace CSVWidget { class PushButton : public QPushButton @@ -24,9 +29,12 @@ namespace CSVWidget bool mKeepOpen; Type mType; QString mToolTip; + QString mProcessedToolTip; private: + // Uses {, :, and } as escape sequences for looking up shortcut settings + void processShortcuts(); void setExtendedToolTip(); protected: @@ -57,6 +65,7 @@ namespace CSVWidget private slots: void checkedStateChanged (bool checked); + void settingChanged (const CSMPrefs::Setting *setting); }; } diff --git a/apps/opencs/view/widget/scenetoolmode.cpp b/apps/opencs/view/widget/scenetoolmode.cpp index c91890c69..7b2ff64db 100644 --- a/apps/opencs/view/widget/scenetoolmode.cpp +++ b/apps/opencs/view/widget/scenetoolmode.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "scenetoolbar.hpp" #include "modebutton.hpp" @@ -133,6 +134,16 @@ void CSVWidget::SceneToolMode::setButton (const std::string& id) } } +bool CSVWidget::SceneToolMode::event(QEvent* event) +{ + if (event->type() == QEvent::ToolTip) + { + adjustToolTip(mCurrent); + } + + return SceneTool::event(event); +} + void CSVWidget::SceneToolMode::selected() { std::map::iterator iter = diff --git a/apps/opencs/view/widget/scenetoolmode.hpp b/apps/opencs/view/widget/scenetoolmode.hpp index 192b3ee78..90f1dc419 100644 --- a/apps/opencs/view/widget/scenetoolmode.hpp +++ b/apps/opencs/view/widget/scenetoolmode.hpp @@ -7,6 +7,7 @@ class QHBoxLayout; class QMenu; +class QEvent; namespace CSVWidget { @@ -43,6 +44,10 @@ namespace CSVWidget void setButton (std::map::iterator iter); + protected: + + bool event(QEvent* event); + public: SceneToolMode (SceneToolbar *parent, const QString& toolTip);