Skip to content

Commit

Permalink
Client|UI: Auto-hide the alert notification (default: 3 mins)
Browse files Browse the repository at this point in the history
The config variable is 'Config.alert.autoHide'.

IssueID #1848
  • Loading branch information
skyjake committed Oct 27, 2014
1 parent c75e882 commit e6d0caa
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 1 deletion.
2 changes: 2 additions & 0 deletions doomsday/client/include/ui/dialogs/alertdialog.h
Expand Up @@ -65,6 +65,8 @@ class AlertDialog : public de::DialogWidget
public slots:
void showListOfAlerts();
void showLogFilterSettings();
void hideNotification();
void hideTimeChanged();

protected:
void finish(int result);
Expand Down
3 changes: 3 additions & 0 deletions doomsday/client/net.dengine.client.pack/modules/appconfig.de
Expand Up @@ -46,6 +46,9 @@ def setDefaults(d)
audio = Log.WARNING
input = Log.WARNING
network = Log.WARNING

# Alert notification dismissed after 3 minutes by default.
autoHide = 3 * 60
end

# Input defaults.
Expand Down
107 changes: 106 additions & 1 deletion doomsday/client/src/ui/dialogs/alertdialog.cpp
Expand Up @@ -23,16 +23,25 @@

#include <de/FIFO>
#include <de/App>
#include <de/ChoiceWidget>

#include <de/DialogContentStylist>
#include <de/NotificationAreaWidget>
#include <de/SequentialLayout>
#include <de/SignalAction>
#include <de/ui/ListData>
#include <de/ui/ActionItem>

#include <QTimer>

using namespace de;

static String const VAR_AUTOHIDE = "alert.autoHide";

DENG_GUI_PIMPL(AlertDialog)
, DENG2_OBSERVES(ChildWidgetOrganizer, WidgetCreation)
, DENG2_OBSERVES(ChildWidgetOrganizer, WidgetUpdate)
, DENG2_OBSERVES(Variable, Change)
{
/// Data model item representing an alert in the list.
class AlertItem : public ui::ActionItem
Expand Down Expand Up @@ -78,6 +87,9 @@ DENG_GUI_PIMPL(AlertDialog)
MenuWidget *alerts;
bool clearOnDismiss;
TextStyling styling;
QTimer hideTimer; ///< Automatically hides the notification.
ChoiceWidget *hideTimes;
DialogContentStylist stylist;

dsize maxCount;
typedef FIFO<AlertItem> Pending;
Expand Down Expand Up @@ -108,13 +120,43 @@ DENG_GUI_PIMPL(AlertDialog)

alerts->organizer().audienceForWidgetCreation() += this;
alerts->organizer().audienceForWidgetUpdate() += this;

// Set up the automatic hide timer.
QObject::connect(&hideTimer, SIGNAL(timeout()), thisPublic, SLOT(hideNotification()));
hideTimer.setSingleShot(true);
App::config(VAR_AUTOHIDE).audienceForChange() += this;
}

~Instance()
{
App::config(VAR_AUTOHIDE).audienceForChange() -= this;
}

NotificationAreaWidget &notifs()
{
return ClientWindow::main().notifications();
}

int autoHideAfterSeconds() const
{
return App::config().geti(VAR_AUTOHIDE, 3 * 60);
}

void variableValueChanged(Variable &, Value const &)
{
// Update the auto-hide timer.
if(!autoHideAfterSeconds())
{
// Never autohide.
hideTimer.stop();
}
else
{
hideTimer.setInterval(autoHideAfterSeconds() * 1000);
if(!hideTimer.isActive()) hideTimer.start();
}
}

void queueAlert(String const &msg, Level level)
{
pending.put(new AlertItem(msg, level));
Expand Down Expand Up @@ -205,6 +247,17 @@ DENG_GUI_PIMPL(AlertDialog)
notification->setImageColor(style().colors().colorf("accent"));

notifs().showOrHide(notification, true);

// Restart the autohiding timer.
if(autoHideAfterSeconds() > 0)
{
hideTimer.start(autoHideAfterSeconds() * 1000);
}
}

void hideNotification()
{
notifs().hideChild(*notification);
}

/**
Expand All @@ -216,11 +269,25 @@ DENG_GUI_PIMPL(AlertDialog)
if(alerts->items().isEmpty())
{
// No alerts to show.
notifs().hideChild(*notification);
hideNotification();
return true; // was hidden
}
return false;
}

void updateHideTimeSelection()
{
int const time = autoHideAfterSeconds();
ui::DataPos pos = hideTimes->items().findData(time);
if(pos != ui::Data::InvalidPos)
{
hideTimes->setSelected(pos);
}
else
{
hideTimes->setSelected(hideTimes->items().findData(0));
}
}
};

AlertDialog::AlertDialog(String const &/*name*/) : d(new Instance(this))
Expand All @@ -233,6 +300,34 @@ AlertDialog::AlertDialog(String const &/*name*/) : d(new Instance(this))
<< new DialogButtonItem(DialogWidget::Action | DialogWidget::Id1,
style().images().image("gear"),
new SignalAction(this, SLOT(showLogFilterSettings())));

// Auto-hide setting, positioned next to the Gear button.
// These are not part of the dialog proper, but should be styled like regular
// dialog contents.
d->stylist.setContainer(*this);
ButtonWidget const &gearButton = *buttonWidget(DialogWidget::Id1);

auto *lab = LabelWidget::newWithText(tr("Hide After:"), this);

add(d->hideTimes = new ChoiceWidget);
d->hideTimes->items()
<< new ChoiceItem(tr("1 min"), 60)
<< new ChoiceItem(tr("3 mins"), 3 * 60)
<< new ChoiceItem(tr("5 mins"), 5 * 60)
<< new ChoiceItem(tr("10 mins"), 10 * 60)
<< new ChoiceItem(tr("Never"), 0);
d->updateHideTimeSelection();

lab->rule()
.setInput(Rule::Left, gearButton.rule().right())
.setInput(Rule::AnchorY, gearButton.rule().midY())
.setAnchorPoint(Vector2f(0, .5f));

d->hideTimes->rule()
.setInput(Rule::Left, lab->rule().right())
.setInput(Rule::Top, lab->rule().top());

connect(d->hideTimes, SIGNAL(selectionChangedByUser(uint)), this, SLOT(hideTimeChanged()));
}

void AlertDialog::newAlert(String const &message, Level level)
Expand Down Expand Up @@ -270,6 +365,16 @@ void AlertDialog::showLogFilterSettings()
st->exec(root());
}

void AlertDialog::hideNotification()
{
d->hideNotification();
}

void AlertDialog::hideTimeChanged()
{
App::config().set(VAR_AUTOHIDE, d->hideTimes->selectedItem().data().toInt());
}

void AlertDialog::finish(int result)
{
DialogWidget::finish(result);
Expand Down

0 comments on commit e6d0caa

Please sign in to comment.