Skip to content

Commit

Permalink
UI|Home: Usability improvements for profile management
Browse files Browse the repository at this point in the history
Highlight newly created profile. Automatically focus the package search
filter in the Packages dialog.
  • Loading branch information
skyjake committed Mar 27, 2016
1 parent 0c88ab4 commit 1f5513b
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 22 deletions.
2 changes: 2 additions & 0 deletions doomsday/apps/client/include/ui/widgets/homeitemwidget.h
Expand Up @@ -45,6 +45,8 @@ class HomeItemWidget : public de::GuiWidget
void useColorTheme(ColorTheme style);
void useColorTheme(ColorTheme unselected, ColorTheme selected);

void acquireFocus();

signals:
void mouseActivity();
void doubleClicked();
Expand Down
8 changes: 7 additions & 1 deletion doomsday/apps/client/include/ui/widgets/homemenuwidget.h
Expand Up @@ -40,7 +40,13 @@ class HomeMenuWidget : public de::MenuWidget
*/
int selectedIndex() const;

void setSelectedIndex(int index);
/**
* @brief setSelectedIndex
* @param index
*
* @return The highlighted widget, if one was highlighted. Otherwise, returns nullptr.
*/
void setSelectedIndex(int index, bool focus = false);

protected slots:
void mouseActivityInItem();
Expand Down
3 changes: 3 additions & 0 deletions doomsday/apps/client/include/ui/widgets/packageswidget.h
Expand Up @@ -20,6 +20,7 @@
#define DENG_CLIENT_UI_HOME_PACKAGESWIDGET_H

#include <de/ButtonWidget>
#include <de/LineEditWidget>
#include <de/IPersistent>

class HomeItemWidget;
Expand Down Expand Up @@ -60,6 +61,8 @@ class PackagesWidget : public de::GuiWidget, public de::IPersistent

void populate();

de::LineEditWidget &searchTermsEditor();

// Implements IPersistent.
void operator >> (de::PersistentState &toState) const;
void operator << (de::PersistentState const &fromState);
Expand Down
5 changes: 3 additions & 2 deletions doomsday/apps/client/src/ui/dialogs/createprofiledialog.cpp
Expand Up @@ -152,9 +152,10 @@ CreateProfileDialog *CreateProfileDialog::editProfile(String const &gameFamily,
auto *dlg = new CreateProfileDialog(gameFamily);
dlg->d->editing = true;
dlg->d->oldName = profile.name();
dlg->title() .setText(tr("Edit Profile"));
dlg->message().setText(tr("Game profile name:"));
dlg->title().setText(tr("Edit Profile"));
dlg->message().hide();
dlg->buttonWidget(Id1)->setText(_E(b) + tr("OK"));
dlg->fetchFrom(profile);
dlg->updateLayout();
return dlg;
}
2 changes: 2 additions & 0 deletions doomsday/apps/client/src/ui/dialogs/packagesdialog.cpp
Expand Up @@ -407,4 +407,6 @@ void PackagesDialog::preparePanelForOpening()
{
DialogWidget::preparePanelForOpening();
d->populate();

root().setFocus(&d->browser->searchTermsEditor());
}
59 changes: 44 additions & 15 deletions doomsday/apps/client/src/ui/home/gamecolumnwidget.cpp
Expand Up @@ -58,7 +58,7 @@ DENG_GUI_PIMPL(GameColumnWidget)
: d(d)
, profile(&gameProfile)
{
setData(game().id());
//setData(game().id());
profile->audienceForDeletion += this;
}

Expand All @@ -73,7 +73,7 @@ DENG_GUI_PIMPL(GameColumnWidget)
return DoomsdayApp::games()[profile->game()];
}

String gameId() const { return data().toString(); }
//String gameId() const { return data().toString(); }

void update() const { notifyChange(); }

Expand Down Expand Up @@ -125,6 +125,9 @@ DENG_GUI_PIMPL(GameColumnWidget)
newProfileButton->setSizePolicy(ui::Filled, ui::Expand);
newProfileButton->setTextAlignment(ui::AlignRight);
newProfileButton->setOpacity(actionOpacity());

// Clicking the New Profile button creates a new profile. It gets added to the
// menu via observers.
newProfileButton->setActionFn([this] ()
{
auto *dlg = new CreateProfileDialog(this->gameFamily);
Expand All @@ -134,12 +137,11 @@ DENG_GUI_PIMPL(GameColumnWidget)
{
// Adding the profile has the side effect that a widget is
// created for it.
DoomsdayApp::gameProfiles().add(dlg->makeProfile());

sortItems();
//menu->setSelectedIndex(menu->childCount() - 1); // depends on "New Profile" being at the end
auto *added = dlg->makeProfile();
DoomsdayApp::gameProfiles().add(added);
}
});

newProfileButton->rule()
.setInput(Rule::Left, area.contentRule().left())
.setInput(Rule::Width, area.contentRule().width())
Expand All @@ -157,11 +159,18 @@ DENG_GUI_PIMPL(GameColumnWidget)
App::config("home.showUnplayableGames").audienceForChange() -= this;
}

ui::Item const *findItem(String const &id) const
ui::Item const *findProfileItem(GameProfile const &profile) const
{
auto const pos = menu->items().findData(id);
if(pos == ui::Data::InvalidPos) return nullptr;
return &menu->items().at(pos);
for(dsize i = 0; i < menu->items().size(); ++i)
{
ui::Item const &item = menu->items().at(i);
qDebug() << i << item.label();
if(!item.semantics().testFlag(ui::Item::Separator))
{
if(item.as<ProfileItem>().profile == &profile) return &item;
}
}
return nullptr;
}

GamePanelButtonWidget &widgetForItem(ui::Item const &item) const
Expand All @@ -183,7 +192,7 @@ DENG_GUI_PIMPL(GameColumnWidget)
return count;
}

void addItemForProfile(GameProfile &profile)
bool addItemForProfile(GameProfile &profile)
{
auto const &games = DoomsdayApp::games();
if(games.contains(profile.game()))
Expand All @@ -192,17 +201,27 @@ DENG_GUI_PIMPL(GameColumnWidget)
{
menu->items() << new ProfileItem(this, profile);
addOrRemoveSubheading();
return true;
}
}
return false;
}

void profileAdded(Profiles::AbstractProfile &prof)
{
// This may be called from another thread.
mainCall.enqueue([this, &prof] ()
{
addItemForProfile(prof.as<GameProfile>());
sortItems();
if(addItemForProfile(prof.as<GameProfile>()))
{
sortItems();

// Highlight the newly added item.
auto const *newItem = findProfileItem(prof.as<GameProfile>());
DENG2_ASSERT(newItem);
menu->setSelectedIndex(menu->items().find(*newItem),
true /*set focus*/);
}
});
}

Expand Down Expand Up @@ -351,6 +370,10 @@ DENG_GUI_PIMPL(GameColumnWidget)
{
profileItem->profile->setPackages(StringList());
profileItem->update();
}))
<< new ui::ActionItem(tr("Duplicate"), new CallbackAction([this] ()
{

}));

// Items for user profiles.
Expand All @@ -361,10 +384,15 @@ DENG_GUI_PIMPL(GameColumnWidget)
deleteSub->items()
<< new ui::Item(ui::Item::Separator, tr("Are you sure?"))
<< new ui::ActionItem(tr("Delete Profile"),
new CallbackAction([this, profileItem, popup] ()
new CallbackAction([this, button, profileItem, popup] ()
{
popup->detachAnchor();
delete profileItem->profile;
// Animate the widget to fade it away.
TimeDelta const SPAN = 0.2;
button->setOpacity(0, SPAN);
QTimer::singleShot(SPAN.asMilliSeconds(), [profileItem] () {
delete profileItem->profile;
});
}))
<< new ui::ActionItem(tr("Cancel"), new Action);

Expand All @@ -374,6 +402,7 @@ DENG_GUI_PIMPL(GameColumnWidget)
{
auto *dlg = CreateProfileDialog::editProfile(gameFamily, *profileItem->profile);
dlg->setAnchorAndOpeningDirection(button->label().rule(), ui::Up);
dlg->setAnchorX(button->rule().midX()); // keep centered in column
dlg->setDeleteAfterDismissed(true);
if(dlg->exec(root()))
{
Expand Down
7 changes: 6 additions & 1 deletion doomsday/apps/client/src/ui/widgets/homeitemwidget.cpp
Expand Up @@ -34,7 +34,7 @@ DENG_GUI_PIMPL(HomeItemWidget)

void acquireFocus()
{
owner.root().setFocus(owner.d->background);
owner.acquireFocus();
emit owner.mouseActivity();
}

Expand Down Expand Up @@ -275,6 +275,11 @@ void HomeItemWidget::useColorTheme(ColorTheme unselected, ColorTheme selected)
d->updateColors();
}

void HomeItemWidget::acquireFocus()
{
root().setFocus(d->background);
}

void HomeItemWidget::addButton(ButtonWidget *button)
{
// Common styling.
Expand Down
10 changes: 7 additions & 3 deletions doomsday/apps/client/src/ui/widgets/homemenuwidget.cpp
Expand Up @@ -33,8 +33,11 @@ DENG_GUI_PIMPL(HomeMenuWidget)

void widgetCreatedForItem(GuiWidget &widget, ui::Item const &)
{
QObject::connect(&widget, SIGNAL(mouseActivity()),
thisPublic, SLOT(mouseActivityInItem()));
if(widget.is<HomeItemWidget>())
{
QObject::connect(&widget, SIGNAL(mouseActivity()),
thisPublic, SLOT(mouseActivityInItem()));
}
}
};

Expand Down Expand Up @@ -71,7 +74,7 @@ int HomeMenuWidget::selectedIndex() const
return d->selectedIndex;
}

void HomeMenuWidget::setSelectedIndex(int index)
void HomeMenuWidget::setSelectedIndex(int index, bool focus)
{
if(index >= 0 && index < childWidgets().size())
{
Expand All @@ -81,6 +84,7 @@ void HomeMenuWidget::setSelectedIndex(int index)
{
d->selectedIndex = index;
widget->setSelected(true);
if(focus) widget->acquireFocus();
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions doomsday/apps/client/src/ui/widgets/packageswidget.cpp
Expand Up @@ -495,6 +495,11 @@ void PackagesWidget::populate()
d->populate();
}

LineEditWidget &PackagesWidget::searchTermsEditor()
{
return *d->search;
}

void PackagesWidget::operator >> (PersistentState &toState) const
{
if(name().isEmpty()) return;
Expand Down

0 comments on commit 1f5513b

Please sign in to comment.