Skip to content

Commit

Permalink
All none/all actions in toolbar menus can now toggle between none/all…
Browse files Browse the repository at this point in the history
… and selected state. Click "All" a second time to revert to the previous selection.

Closes #762
  • Loading branch information
albar965 committed Jul 25, 2022
1 parent 26b97cb commit 60ffaa8
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 159 deletions.
2 changes: 1 addition & 1 deletion src/airspace/airspacecontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ void AirspaceController::resetSettingsToDefault()

void AirspaceController::updateButtonsAndActions()
{
airspaceHandler->updateAll();
airspaceHandler->updateButtonsAndActions();
}

bool AirspaceController::hasAnyAirspaces() const
Expand Down
169 changes: 90 additions & 79 deletions src/airspace/airspacetoolbarhandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "common/maptypes.h"
#include "common/unit.h"
#include "gui/actionbuttonhandler.h"
#include "navapp.h"
#include "ui_mainwindow.h"

Expand Down Expand Up @@ -161,20 +162,31 @@ void AirspaceLabelAction::deleteWidget(QWidget *widget)

// =======================================================================================

AirspaceToolBarHandler::AirspaceToolBarHandler(MainWindow *parent)
: mainWindow(parent)
AirspaceToolBarHandler::AirspaceToolBarHandler(QWidget *parent)
: parentWidget(parent)
{
// Need a button handler for each toolbar button
buttonHandlerIcao = new atools::gui::ActionButtonHandler(parentWidget);
buttonHandlerFir = new atools::gui::ActionButtonHandler(parentWidget);
buttonHandlerRestricted = new atools::gui::ActionButtonHandler(parentWidget);
buttonHandlerSpecial = new atools::gui::ActionButtonHandler(parentWidget);
buttonHandlerOther = new atools::gui::ActionButtonHandler(parentWidget);

connect(NavApp::getMainUi()->actionShowAirspaces, &QAction::toggled, this, &AirspaceToolBarHandler::allAirspacesToggled);
}

AirspaceToolBarHandler::~AirspaceToolBarHandler()
{

delete buttonHandlerIcao;
delete buttonHandlerFir;
delete buttonHandlerRestricted;
delete buttonHandlerSpecial;
delete buttonHandlerOther;
}

void AirspaceToolBarHandler::allAirspacesToggled()
{
updateAll();
updateButtonsAndActions();
}

void AirspaceToolBarHandler::updateToolButtons()
Expand Down Expand Up @@ -204,22 +216,13 @@ void AirspaceToolBarHandler::updateToolButtons()

void AirspaceToolBarHandler::updateToolActions()
{
map::MapAirspaceFilter shown = NavApp::getShownMapAirspaces();

for(QAction *action : airspaceActions)
bool enable = NavApp::getMainUi()->actionShowAirspaces->isChecked();
bool hasAirspaces = NavApp::hasAnyAirspaces();
for(QToolButton *toolButton : airspaceToolButtons)
{
map::MapAirspaceFilter filterFromAction = action->data().value<map::MapAirspaceFilter>();

if(!(filterFromAction.flags & map::AIRSPACE_ALL_ON) && !(filterFromAction.flags & map::AIRSPACE_ALL_OFF))
{
action->blockSignals(true);
action->setChecked(filterFromAction.types & shown.types || filterFromAction.flags & shown.flags);
action->blockSignals(false);
}
for(QAction *action : toolButton->menu()->actions())
action->setEnabled(enable && hasAirspaces);
}

for(QAction *action : airspaceActions)
action->setEnabled(NavApp::getMainUi()->actionShowAirspaces->isChecked());
}

void AirspaceToolBarHandler::updateSliders()
Expand All @@ -230,15 +233,46 @@ void AirspaceToolBarHandler::updateSliders()
sliderActionAltMin->setEnabled(show);
}

void AirspaceToolBarHandler::updateAll()
void AirspaceToolBarHandler::actionsToFilterTypes(map::MapAirspaceFilter& currentFilter)
{
for(QToolButton *toolButton : airspaceToolButtons)
{
for(QAction *action : toolButton->menu()->actions())
{
map::MapAirspaceFilter filter = action->data().value<map::MapAirspaceFilter>();
if(filter.flags.testFlag(map::AIRSPACE_FLAG_NONE))
{
if(action->isChecked())
currentFilter.types |= filter.types;
else
currentFilter.types &= ~filter.types;
}
}
}
}

void AirspaceToolBarHandler::filterTypesToActions(const map::MapAirspaceFilter& currentFilter)
{
for(QToolButton *toolButton : airspaceToolButtons)
{
for(QAction *action : toolButton->menu()->actions())
{
map::MapAirspaceFilter filter = action->data().value<map::MapAirspaceFilter>();
if(filter.flags.testFlag(map::AIRSPACE_FLAG_NONE))
action->setChecked(filter.types & currentFilter.types);
}
}
}

void AirspaceToolBarHandler::updateButtonsAndActions()
{
// Copy currently selected altitude values to sliders
map::MapAirspaceFilter filter = NavApp::getShownMapAirspaces();
sliderActionAltMin->setAltitudeFt(filter.minAltitudeFt);
sliderActionAltMax->setAltitudeFt(filter.maxAltitudeFt);

/* Check or uncheck menu actions with blocked signal based on NavApp::getShownMapAirspaces() */
updateToolActions();
/* Set action check states depending on filter types */
filterTypesToActions(filter);

/* Update button depressed state or not */
updateToolButtons();
Expand All @@ -250,43 +284,17 @@ void AirspaceToolBarHandler::updateAll()
updateSliderLabel();
}

void AirspaceToolBarHandler::actionAllNoneOrTypeTriggered()
void AirspaceToolBarHandler::toolbarActionTriggered(QAction *)
{
qDebug() << Q_FUNC_INFO;

QAction *sendAction = dynamic_cast<QAction *>(sender());
if(sendAction != nullptr)
{
map::MapAirspaceFilter typeFromAction = sendAction->data().value<map::MapAirspaceFilter>();
map::MapAirspaceFilter newFilter = NavApp::getShownMapAirspaces();

if(typeFromAction.flags & map::AIRSPACE_ALL_ON)
newFilter.types |= typeFromAction.types;
else if(typeFromAction.flags & map::AIRSPACE_ALL_OFF)
newFilter.types &= ~typeFromAction.types;
else
{
for(QAction *action : airspaceActions)
{
map::MapAirspaceFilter filter = action->data().value<map::MapAirspaceFilter>();

if(!(filter.flags & map::AIRSPACE_ALL_ON) && !(filter.flags & map::AIRSPACE_ALL_OFF))
{
if(action->isChecked())
newFilter.types |= filter.types;
else
newFilter.types &= ~filter.types;
}
}
}
// Extract filter types and insert into current filter
map::MapAirspaceFilter currentFilter = NavApp::getShownMapAirspaces();
actionsToFilterTypes(currentFilter);
emit updateAirspaceTypes(currentFilter);

// Remove the button only flags
newFilter.flags &= ~map::AIRSPACE_ALL_ON;
newFilter.flags &= ~map::AIRSPACE_ALL_OFF;

emit updateAirspaceTypes(newFilter);
updateAll();
}
/* Update button depressed state or not */
updateToolButtons();
}

void AirspaceToolBarHandler::actionRadioGroupTriggered(QAction *action)
Expand Down Expand Up @@ -391,35 +399,37 @@ void AirspaceToolBarHandler::altSliderChanged()

void AirspaceToolBarHandler::createToolButtons()
{
createAirspaceToolButton(":/littlenavmap/resources/icons/airspaceicao.svg",
createAirspaceToolButton(buttonHandlerIcao, ":/littlenavmap/resources/icons/airspaceicao.svg",
tr("Select ICAO airspaces"),
{map::CLASS_A, map::CLASS_B, map::CLASS_C, map::CLASS_D, map::CLASS_E,
map::CLASS_F, map::CLASS_G}, {});

createAirspaceToolButton(":/littlenavmap/resources/icons/airspacefir.svg",
createAirspaceToolButton(buttonHandlerFir, ":/littlenavmap/resources/icons/airspacefir.svg",
tr("Select FIR airspaces"),
{map::FIR, map::UIR}, {});

createAirspaceToolButton(":/littlenavmap/resources/icons/airspacerestr.svg",
createAirspaceToolButton(buttonHandlerRestricted, ":/littlenavmap/resources/icons/airspacerestr.svg",
tr("Select MOA, restricted, prohibited and danger airspaces"),
{map::MOA, map::RESTRICTED, map::PROHIBITED, map::GLIDERPROHIBITED, map::DANGER}, {});

createAirspaceToolButton(":/littlenavmap/resources/icons/airspacespec.svg",
createAirspaceToolButton(buttonHandlerSpecial, ":/littlenavmap/resources/icons/airspacespec.svg",
tr("Select warning, alert and training airspaces"),
{map::WARNING, map::CAUTION, map::ALERT, map::TRAINING}, {});

createAirspaceToolButton(":/littlenavmap/resources/icons/airspaceother.svg",
createAirspaceToolButton(buttonHandlerOther, ":/littlenavmap/resources/icons/airspaceother.svg",
tr("Select centers and other airspaces"),
{map::CENTER, map::TOWER, map::GCA, map::MCTR, map::TRSA, map::CLEARANCE, map::GROUND,
map::DEPARTURE, map::APPROACH, map::NATIONAL_PARK, map::MODEC, map::RADAR, map::WAVEWINDOW,
map::ONLINE_OBSERVER}, {});

createAirspaceToolButton(":/littlenavmap/resources/icons/airspacealt.svg", tr("Select altitude limitations for airspace display"),
createAirspaceToolButton(nullptr, ":/littlenavmap/resources/icons/airspacealt.svg",
tr("Select altitude limitations for airspace display"),
{}, {map::AIRSPACE_ALTITUDE_ALL, map::AIRSPACE_ALTITUDE_FLIGHTPLAN, map::AIRSPACE_ALTITUDE_SET},
true /* groupActions */, true /* minMaxAltitude */);
}

void AirspaceToolBarHandler::createAirspaceToolButton(const QString& icon, const QString& buttonHelp,
void AirspaceToolBarHandler::createAirspaceToolButton(atools::gui::ActionButtonHandler *buttonHandler, const QString& icon,
const QString& buttonHelp,
const std::initializer_list<map::MapAirspaceTypes>& types,
const std::initializer_list<map::MapAirspaceFlags>& flags,
bool groupActions, bool minMaxAltitude)
Expand Down Expand Up @@ -457,27 +467,27 @@ void AirspaceToolBarHandler::createAirspaceToolButton(const QString& icon, const
// Add all on / all off menu items ======================================
if(!groupActions)
{
QAction *action = new QAction(tr("&All"), buttonMenu);
action->setToolTip(tr("Show all airspaces in this category"));
action->setStatusTip(action->toolTip());
QAction *actionAll = new QAction(tr("&All"), buttonMenu);
actionAll->setToolTip(tr("Toggle all / current selection of airspaces"));
actionAll->setStatusTip(actionAll->toolTip());
map::MapAirspaceFilter filterOn;
filterOn.types = allTypes;
filterOn.flags = map::AIRSPACE_ALL_ON | allFlags;
action->setData(QVariant::fromValue(filterOn));
buttonMenu->addAction(action);
airspaceActions.append(action);
connect(action, &QAction::triggered, this, &AirspaceToolBarHandler::actionAllNoneOrTypeTriggered);

action = new QAction(tr("&None"), buttonMenu);
action->setToolTip(tr("Hide all airspaces in this category"));
action->setStatusTip(action->toolTip());
actionAll->setData(QVariant::fromValue(filterOn));
buttonHandler->setAllAction(actionAll);
buttonMenu->addAction(actionAll);
connect(buttonHandler, &atools::gui::ActionButtonHandler::actionAllTriggered, this, &AirspaceToolBarHandler::toolbarActionTriggered);

QAction *actionNone = new QAction(tr("&None"), buttonMenu);
actionNone->setToolTip(tr("Toggle none / current selection of airspaces"));
actionNone->setStatusTip(actionNone->toolTip());
map::MapAirspaceFilter filterOff;
filterOff.types = allTypes;
filterOff.flags = map::AIRSPACE_ALL_OFF | allFlags;
action->setData(QVariant::fromValue(filterOff));
buttonMenu->addAction(action);
airspaceActions.append(action);
connect(action, &QAction::triggered, this, &AirspaceToolBarHandler::actionAllNoneOrTypeTriggered);
actionNone->setData(QVariant::fromValue(filterOff));
buttonHandler->setNoneAction(actionNone);
buttonMenu->addAction(actionNone);
connect(buttonHandler, &atools::gui::ActionButtonHandler::actionNoneTriggered, this, &AirspaceToolBarHandler::toolbarActionTriggered);

buttonMenu->addSeparator();
}
Expand Down Expand Up @@ -507,7 +517,6 @@ void AirspaceToolBarHandler::createAirspaceToolButton(const QString& icon, const

action->setData(QVariant::fromValue(f));
buttonMenu->addAction(action);
airspaceActions.append(action);
ui->menuViewAirspaces->addAction(action);
}
}
Expand All @@ -529,11 +538,13 @@ void AirspaceToolBarHandler::createAirspaceToolButton(const QString& icon, const

action->setData(QVariant::fromValue(f));

buttonHandler->addOtherAction(action);
buttonMenu->addAction(action);
airspaceActions.append(action);
connect(action, &QAction::triggered, this, &AirspaceToolBarHandler::actionAllNoneOrTypeTriggered);
ui->menuViewAirspaces->addAction(action);
}

// Signal for all actions in handler
connect(buttonHandler, &atools::gui::ActionButtonHandler::actionOtherTriggered, this, &AirspaceToolBarHandler::toolbarActionTriggered);
}

if(minMaxAltitude)
Expand Down
40 changes: 24 additions & 16 deletions src/airspace/airspacetoolbarhandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,43 +35,51 @@ class AirspaceAltSliderAction;
class AirspaceLabelAction;
}

namespace atools {
namespace gui {
class ActionButtonHandler;
}
}

/* Manages the airspace toolbar, its tool buttons and all the actions in the drop down menus */
class AirspaceToolBarHandler :
public QObject
{
Q_OBJECT

public:
AirspaceToolBarHandler(MainWindow *parent);
explicit AirspaceToolBarHandler(QWidget *parent);
virtual ~AirspaceToolBarHandler() override;

void createToolButtons();

/* Updates all */
void updateAll();

const QVector<QToolButton *>& getAirspaceToolButtons() const
{
return airspaceToolButtons;
}
/* Updates all buttons and actions from the current airspace filter. */
void updateButtonsAndActions();

signals:
void updateAirspaceTypes(map::MapAirspaceFilter filter);

private:
void createAirspaceToolButton(const QString& icon, const QString& buttonHelp,
/* Create one toolbar button with all menus */
void createAirspaceToolButton(atools::gui::ActionButtonHandler *buttonHandler, const QString& icon, const QString& buttonHelp,
const std::initializer_list<map::MapAirspaceTypes>& types,
const std::initializer_list<map::MapAirspaceFlags>& flags,
bool groupActions = false, bool minMaxAltitude = false);

/* Extract filter types from action check states */
void actionsToFilterTypes(map::MapAirspaceFilter& currentFilter);

/* Set action check states depending on filter types */
void filterTypesToActions(const map::MapAirspaceFilter& currentFilter);

/* Update button depressed state or not */
void updateToolButtons();

/* Check or uncheck menu actions with blocked signal based on NavApp::getShownMapAirspaces() */
/* Enable or disable actions based on master airpace action */
void updateToolActions();

/* Extract flags from not grouped actions all/none/type and emit updateAirspaceTypes() */
void actionAllNoneOrTypeTriggered();
void toolbarActionTriggered(QAction *);

/* Radio group button clicked. emit updateAirspaceTypes() */
void actionRadioGroupTriggered(QAction *action);
Expand All @@ -88,9 +96,6 @@ class AirspaceToolBarHandler :
/* Update altitude label from slider values */
void updateSliderLabel();

/* List of all actions */
QVector<QAction *> airspaceActions;

/* List of actions that are not grouped */
QVector<QToolButton *> airspaceToolButtons;

Expand All @@ -99,11 +104,14 @@ class AirspaceToolBarHandler :

/* Flags and types for each button */
QVector<map::MapAirspaceFilter> airspaceToolButtonFilters;
MainWindow *mainWindow;
QWidget *parentWidget;

/* Widget wrapper allowing to put an arbitrary widget into a menu */
asinternal::AirspaceAltSliderAction *sliderActionAltMin = nullptr, *sliderActionAltMax = nullptr;
asinternal::AirspaceLabelAction *labelActionAirspace = nullptr;

atools::gui::ActionButtonHandler *buttonHandlerIcao, *buttonHandlerFir, *buttonHandlerRestricted, *buttonHandlerSpecial,
*buttonHandlerOther;
};

namespace asinternal {
Expand All @@ -117,7 +125,7 @@ class AirspaceAltSliderAction
Q_OBJECT

public:
AirspaceAltSliderAction(QObject *parent, bool maxSliderParam);
explicit AirspaceAltSliderAction(QObject *parent, bool maxSliderParam);

int getAltitudeFt() const;

Expand Down
Loading

0 comments on commit 60ffaa8

Please sign in to comment.