--- /dev/null
+#include "AddAccessoriesSwitchesPageModel.hpp"
+
+#include "UniversalSwitchConstants.hpp"
+
+AddAccessoriesSwitchesPageModel::AddAccessoriesSwitchesPageModel()
+{
+ dBusClient_ = DBus::DBusClient{BUS, PATH, IFACE, DBus::ConnectionType::SESSION};
+}
+
+AddAccessoriesSwitchesPageModel::~AddAccessoriesSwitchesPageModel()
+{
+ cancelCaptureSwitch();
+}
+
+void AddAccessoriesSwitchesPageModel::captureSwitch(std::function<void(std::string)> onCapture, std::string providerId)
+{
+ dBusClient_.method<std::string(std::string)>("captureSwitch").timeout(DBus::InfinitiveTimeout).asyncCall([onCapture](DBus::ValueOrError<std::string> msg) {
+ if (msg) {
+ onCapture(std::get<0>(msg));
+ } else {
+ ERROR("Error on function captureSwitch asyncCall");
+ ERROR("failed '%s'", msg.getError().message.c_str());
+ }
+ },
+ providerId);
+}
+
+void AddAccessoriesSwitchesPageModel::cancelCaptureSwitch()
+{
+ auto reply = dBusClient_.method<DBus::ValueOrError<>()>("cancelCaptureSwitch").call();
+ if (!reply) {
+ ERROR("Error on function cancelCaptureSwitch call");
+ ERROR("%s", reply.getError().message.c_str());
+ }
+}
+
+bool AddAccessoriesSwitchesPageModel::isConfigured(const std::string &switchId)
+{
+ auto reply = dBusClient_.method<DBus::ValueOrError<std::vector<std::tuple<std::string, std::string, std::string, ChangeType>>>()>("getAllSwitchConfigurationItems").call();
+ if (reply) {
+ for (auto &item : std::get<0>(reply))
+ if (std::get<0>(item) == switchId)
+ return true;
+ } else {
+ ERROR("Error on function getAllSwitchConfigurationItems call");
+ ERROR("%s", reply.getError().message.c_str());
+ ASSERT(0, "unable to know that switch is configured");
+ }
+ return false;
+}
--- /dev/null
+#ifndef ADD_ACCESSORIES_SWITCHES_PAGE_MODEL_HPP
+#define ADD_ACCESSORIES_SWITCHES_PAGE_MODEL_HPP
+
+#include "DBus.hpp"
+#include "ObservableProperty.hpp"
+#include "UniversalSwitchTypes.hpp"
+#include "VConf.hpp"
+
+#include <chrono>
+
+class AddAccessoriesSwitchesPageModel
+{
+ public:
+ AddAccessoriesSwitchesPageModel();
+ ~AddAccessoriesSwitchesPageModel();
+ void captureSwitch(std::function<void(std::string)> onCapture, std::string providerId);
+ void cancelCaptureSwitch();
+ bool isConfigured(const std::string &switchId);
+
+ private:
+ DBus::DBusClient dBusClient_;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#include "UpdateAccessoriesSwitchPageModel.hpp"
+
+#include "UniversalSwitchConstants.hpp"
+
+UpdateAccessoriesSwitchPageModel::UpdateAccessoriesSwitchPageModel()
+{
+}
+
+SwitchConfigurationItem UpdateAccessoriesSwitchPageModel::getDetailsForSwitchConfigurationItem(const std::string &switchId)
+{
+ auto reply = DBus::DBusClient{BUS, PATH, IFACE, DBus::ConnectionType::SESSION}.method<DBus::ValueOrError<std::vector<std::tuple<std::string, std::string, std::string>>>()>("getAllSwitchConfigurationItems").call();
+ if (reply) {
+ for (auto &item : std::get<0>(reply))
+ if (std::get<0>(item) == switchId)
+ return SwitchConfigurationItem{std::get<0>(item), std::get<1>(item), std::get<2>(item)};
+ } else {
+ ERROR("Error on function getAllSwitchConfigurationItems call");
+ ERROR("%s", reply.getError().message.c_str());
+ }
+ return {};
+}
+
+InfoType UpdateAccessoriesSwitchPageModel::getActivityDetails(const std::string &activityId)
+{
+ auto dBusClient = DBus::DBusClient{BUS, PATH, IFACE, DBus::ConnectionType::SESSION};
+ auto reply = dBusClient.method<DBus::ValueOrError<std::vector<std::tuple<std::string, std::string, std::string>>>()>("getBindableActivityTypes").call();
+ if (reply) {
+ for (auto &activity : std::get<0>(reply))
+ if (std::get<0>(activity) == activityId)
+ return InfoType{std::get<0>(activity), std::get<1>(activity), std::get<2>(activity)};
+ } else {
+ ERROR("Error on function getBindableActivityTypes call");
+ ERROR("%s", reply.getError().message.c_str());
+ }
+ return {};
+}
+
+void UpdateAccessoriesSwitchPageModel::updateSwitch(const SwitchConfigurationItem &item)
+{
+ auto dBusClient = DBus::DBusClient{BUS, PATH, IFACE, DBus::ConnectionType::SESSION};
+ auto reply = dBusClient.method<DBus::ValueOrError<>(std::string, std::string, std::string)>("updateSwitchConfigurationItem").call(item.switchId, item.userName, item.activityType);
+ if (reply)
+ DEBUG("Switch: %s updated successfully", item.switchId.c_str());
+ else {
+ ERROR("Error on function updateSwitchConfigurationItem call");
+ ERROR("%s", reply.getError().message.c_str());
+ }
+}
\ No newline at end of file
--- /dev/null
+#ifndef UPDATE_ACCESSORIES_SWITCH_PAGE_MODEL_HPP
+#define UPDATE_ACCESSORIES_SWITCH_PAGE_MODEL_HPP
+
+#include "DBus.hpp"
+#include "ObservableProperty.hpp"
+#include "UniversalSwitchTypes.hpp"
+#include "VConf.hpp"
+
+#include <chrono>
+
+class UpdateAccessoriesSwitchPageModel
+{
+ public:
+ UpdateAccessoriesSwitchPageModel();
+ SwitchConfigurationItem getDetailsForSwitchConfigurationItem(const std::string &switchId);
+ InfoType getActivityDetails(const std::string &actionId);
+ void updateSwitch(const SwitchConfigurationItem &item);
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#include "AddAccessoriesSwitchesPagePresenter.hpp"
+
+#include "AlreadyMappedSwitchModalPresenter.hpp"
+#include "AppContext.hpp"
+#include "EntryNameModalPresenter.hpp"
+#include "Singleton.hpp"
+#include "UniversalSwitchConstants.hpp"
+
+AddAccessoriesSwitchesPagePresenter::AddAccessoriesSwitchesPagePresenter()
+{
+ setTitle("IDS_ACCS_UNIVERSAL_SWITCH_ADD_SWITCH_ACCESSORIES_TITLE");
+ labelText_ = "IDS_ACCS_UNIVERSAL_SWITCH_ADD_SWITCH_ACCESSORIES_DESC";
+}
+
+void AddAccessoriesSwitchesPagePresenter::onTop()
+{
+ model_.captureSwitch([this](auto switchId) {
+ this->onSwitchCapture(switchId);
+ },
+ ACCESSIBILITY_UNIVERSAL_SWITCH_ACCESSORIES_SWITCH_PROVIDER);
+}
+
+void AddAccessoriesSwitchesPagePresenter::notOnTop()
+{
+ model_.cancelCaptureSwitch();
+}
+
+void AddAccessoriesSwitchesPagePresenter::onSwitchCapture(const std::string &switchId)
+{
+ notOnTop();
+ if (model_.isConfigured(switchId))
+ Singleton<AppContext>::instance().pushModal(std::make_unique<AlreadyMappedSwitchModalPresenter>());
+ else
+ Singleton<AppContext>::instance().pushModal(std::make_unique<EntryNameModalPresenter>(switchId));
+}
--- /dev/null
+#ifndef ADD_ACCESSORIES_SWITCHES_PAGE_PRESENTER
+#define ADD_ACCESSORIES_SWITCHES_PAGE_PRESENTER
+
+#include "AddAccessoriesSwitchesPageModel.hpp"
+#include "LabelPresenter.hpp"
+
+class AddAccessoriesSwitchesPagePresenter : public LabelPresenter
+{
+ public:
+ AddAccessoriesSwitchesPagePresenter();
+
+ private:
+ void onTop() override;
+ void notOnTop() override;
+ void onSwitchCapture(const std::string &switchId);
+ AddAccessoriesSwitchesPageModel model_;
+};
+
+#endif
\ No newline at end of file
#include "AddSwitchPagePresenter.hpp"
+#include "AddAccessoriesSwitchesPagePresenter.hpp"
#include "AppContext.hpp"
#include "CameraSwitchesPagePresenter.hpp"
#include "SelectActionPagePresenter.hpp"
void AddSwitchPagePresenter::createPageForAccessoriesProvider()
{
- //Singleton<AppContext>::instance().push(std::make_unique<AccessoriesProviderPagePresenter>());
+ Singleton<AppContext>::instance().push(std::make_unique<AddAccessoriesSwitchesPagePresenter>());
}
void AddSwitchPagePresenter::createPageForCameraProvider()
--- /dev/null
+#include "AlreadyMappedSwitchModalPresenter.hpp"
+
+AlreadyMappedSwitchModalPresenter::AlreadyMappedSwitchModalPresenter()
+{
+ setTitle("IDS_ACCS_UNIVERSAL_SWITCH_UNABLE_TO_ADD");
+ text_ = "IDS_ACCS_UNIVERSAL_SWITCH_ALREADY_ADDED";
+ cancelText_ = "IDS_ACCS_UNIVERSAL_SWITCH_OK";
+}
--- /dev/null
+#ifndef ALREADY_MAPPED_SWITCH_MODAL_PRESENTER
+#define ALREADY_MAPPED_SWITCH_MODAL_PRESENTER
+
+#include "ModalPresenter.hpp"
+
+class AlreadyMappedSwitchModalPresenter : public ModalPresenter
+{
+ public:
+ AlreadyMappedSwitchModalPresenter();
+};
+
+#endif
\ No newline at end of file
void AppContext::push(std::unique_ptr<Presenter> presenter)
{
+ if (presentersStack_.size() > 0)
+ presentersStack_.back()->notOnTop();
presentersStack_.push_back(std::move(presenter));
+ presentersStack_.back()->onTop();
presenterToBroadcast_ = presentersStack_.back().get();
countOfPagesToPop_ = 1;
notify();
else
countOfPagesToPop_ = countOfPagesToPop;
+ if (presentersStack_.size() > 0)
+ presentersStack_.back()->notOnTop();
+
for (auto i = 0u; i < countOfPagesToPop_; ++i)
presentersStack_.pop_back();
- if (presentersStack_.empty())
+ if (presentersStack_.empty()) {
ui_app_exit();
- else
+ } else {
+ presentersStack_.back()->onTop();
notify();
+ }
}
Presenter *AppContext::back()
void AppContext::pushModal(std::unique_ptr<ModalPresenter> presenter)
{
+ if (presentersStack_.size() > 0)
+ presentersStack_.back()->notOnTop();
modalPresentersStack_.push_back(std::move(presenter));
modalPresenterToBroadcast_ = modalPresentersStack_.back().get();
notifyAboutModal();
void AppContext::popModal()
{
+ if (presentersStack_.size() > 0)
+ presentersStack_.back()->onTop();
+ modalPresentersStack_.pop_back();
modalPresenterToBroadcast_ = nullptr;
notifyAboutModal();
- modalPresentersStack_.pop_back();
}
ModalPresenter *AppContext::modalsBack()
void popModal();
ModalPresenter *modalsBack();
bool modalsEmpty();
+ std::unordered_map<std::string, std::string> sharedPreferences;
private:
std::vector<std::unique_ptr<Presenter>> presentersStack_;
--- /dev/null
+#include "EntryNameModalPresenter.hpp"
+
+#include "AppContext.hpp"
+#include "SelectActionPagePresenter.hpp"
+#include "Singleton.hpp"
+
+EntryNameModalPresenter::EntryNameModalPresenter(std::string switchId)
+{
+ setTitle("IDS_ACCS_UNIVERSAL_SWITCH_ADD_SWITCH");
+ entryAction_ = addAction(std::make_unique<Action>("modalEntry", "IDS_ACCS_UNIVERSAL_SWITCH_ADD_SWITCH_NAME", std::function<void(Action *)>{}));
+ doneText_ = "IDS_ACCS_UNIVERSAL_SWITCH_SAVE";
+ cancelText_ = "IDS_ACCS_UNIVERSAL_SWITCH_CANCEL";
+ doneCb_ = [this, switchId]() {
+ auto switchUserName = this->entryAction_->title_.value();
+ if (!switchUserName.empty()) {
+ Singleton<AppContext>::instance().popModal();
+ Singleton<AppContext>::instance().push(std::make_unique<SelectActionPagePresenter>(switchId, switchUserName, ChangeType::ADD, 2));
+ }
+ };
+}
\ No newline at end of file
--- /dev/null
+#ifndef ENTRY_NAME_MODAL_PRESENTER_HPP
+#define ENTRY_NAME_MODAL_PRESENTER_HPP
+
+#include "ModalPresenter.hpp"
+
+class EntryNameModalPresenter : public ModalPresenter
+{
+ public:
+ EntryNameModalPresenter(std::string switchId);
+
+ private:
+ Action *entryAction_ = nullptr;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#ifndef LABEL_PRESENTER
+#define LABEL_PRESENTER
+
+#include "ObservableProperty.hpp"
+#include "Presenter.hpp"
+
+class LabelPresenter : public Presenter
+{
+ public:
+ ObservableProperty<std::string> labelText_;
+
+ protected:
+ using Presenter::Presenter;
+};
+
+#endif
\ No newline at end of file
return groups_;
}
-Action *ListPresenter::getAction(const std::string &actionId) const
-{
- auto it = actions_.find(actionId);
- if (it == actions_.end()) {
- // DEBUG("Action with id: %s doesn't exist", actionId.c_str());
- return nullptr;
- }
- return it->second.get();
-}
-
-Action *ListPresenter::addAction(std::unique_ptr<Action> action)
-{
- auto ret = actions_.insert_or_assign(action->actionId_, std::move(action));
- ASSERT(ret.second, "Action cannot be added");
-
- return ret.first->second.get();
-}
-
void ListPresenter::setOnListUpdateCallback(std::function<void()> callback)
{
onListUpdate_ = std::move(callback);
#ifndef LIST_PRESENTER_HPP
#define LIST_PRESENTER_HPP
-#include "Action.hpp"
#include "ListGroup.hpp"
#include "Observable.hpp"
#include "Presenter.hpp"
-#include <unordered_map>
-
class ListPresenter : public Presenter, public Observable<>
{
public:
const std::vector<ListGroup> &getListGroups() const;
- Action *getAction(const std::string &actionId) const;
- Action *addAction(std::unique_ptr<Action> action);
void setOnListUpdateCallback(std::function<void()> callback);
protected:
std::function<void()> onListUpdate_;
std::vector<ListGroup> groups_;
- std::unordered_map<std::string, std::unique_ptr<Action>> actions_;
};
#endif
\ No newline at end of file
std::string ModalPresenter::getDoneText()
{
return doneText_;
+}
+
+std::string ModalPresenter::getCancelText()
+{
+ return cancelText_;
}
\ No newline at end of file
std::function<void()> getCancelCb();
std::string getText();
std::string getDoneText();
+ std::string getCancelText();
protected:
using Presenter::Presenter;
std::function<void()> cancelCb_;
std::string text_;
std::string doneText_;
+ std::string cancelText_;
};
#endif
\ No newline at end of file
void Presenter::onAppResume()
{}
+
+void Presenter::onTop()
+{}
+
+void Presenter::notOnTop()
+{}
+
+Action *Presenter::getAction(const std::string &actionId) const
+{
+ auto it = actions_.find(actionId);
+ if (it == actions_.end()) {
+ return nullptr;
+ }
+ return it->second.get();
+}
+
+Action *Presenter::addAction(std::unique_ptr<Action> action)
+{
+ return actions_.insert_or_assign(action->actionId_, std::move(action)).first->second.get();
+}
\ No newline at end of file
#ifndef PRESENTER_HPP
#define PRESENTER_HPP
+#include "Action.hpp"
#include "GenlistItem.hpp"
#include "TranslatedString.hpp"
#include <functional>
+#include <unordered_map>
#include <vector>
class Presenter
const std::function<void()> getOnPopCallback() const;
virtual void onAppPause();
virtual void onAppResume();
+ virtual void onTop();
+ virtual void notOnTop();
+ Action *getAction(const std::string &actionId) const;
+ Action *addAction(std::unique_ptr<Action> action);
protected:
Presenter(TranslatedString title = {}, std::function<void()> onPopCallback = {});
TranslatedString title_;
std::function<void()> onPopCallback_;
+ std::unordered_map<std::string, std::unique_ptr<Action>> actions_;
};
#endif
\ No newline at end of file
if (switchesToRemove_.size() == switches_.size() && model_.isUniversalSwitchActive_.value()) {
text_ = "IDS_ACCS_UNIVERSAL_SWITCH_DELETE_ALL_SWITCHES_DESC";
} else {
- text_ = std::to_string(switchesToRemove_.size()) + " " + "IDS_ACCS_UNIVERSAL_SWITCH_DELETE_SWITCHES_DESC";
+ text_ = std::to_string(switchesToRemove_.size()) + " " + TranslatedString{"IDS_ACCS_UNIVERSAL_SWITCH_DELETE_SWITCHES_DESC"}.str();
}
doneText_ = "IDS_ACCS_DELETE";
+ cancelText_ = "IDS_ST_BUTTON_CANCEL";
doneCb_ = [this]() {
model_.removeSwitches(switchesToRemove_);
#include "AppContext.hpp"
-SelectActionPagePresenter::SelectActionPagePresenter(std::string switchId, std::string userName, ChangeType changeType, size_t countOfPagesToPop)
+SelectActionPagePresenter::SelectActionPagePresenter(std::string switchId, std::string userName, ChangeType changeType, size_t countOfPagesToPop, std::string activityId, bool locally)
: switchId_(std::move(switchId)), userName_(std::move(userName)), changeType_(changeType), countOfPagesToPop_(countOfPagesToPop)
{
setTitle("IDS_ACCS_UNIVERSAL_SWITCH_SELECT_ACTION");
activity.name,
std::string{},
[=](auto item) {
- this->addOrUpdateSwitchConfigurationItem(activity.id);
+ this->addOrUpdateSwitchConfigurationItem(activity.id, locally);
},
- ListItem::WidgetType::radio));
+ ListItem::WidgetType::radio,
+ std::function<void(ListItem * item)>{},
+ std::function<void(ListItem * item)>{},
+ activityId == activity.id));
}
}
-void SelectActionPagePresenter::addOrUpdateSwitchConfigurationItem(const std::string &activityType)
+void SelectActionPagePresenter::addOrUpdateSwitchConfigurationItem(const std::string &activityType, bool locally)
{
switch (changeType_) {
case ChangeType::ADD:
model_.addSwitch({switchId_, userName_, activityType});
break;
case ChangeType::UPDATE:
- model_.updateSwitch({switchId_, userName_, activityType});
+ if (locally)
+ Singleton<AppContext>::instance().sharedPreferences.insert_or_assign(switchId_, activityType);
+ else
+ model_.updateSwitch({switchId_, userName_, activityType});
break;
default:
ASSERT(0, "Unhandled change type");
class SelectActionPagePresenter : public ListPresenter
{
public:
- SelectActionPagePresenter(std::string switchId, std::string userName, ChangeType changeType, size_t countOfPagesToPop);
+ SelectActionPagePresenter(std::string switchId, std::string userName, ChangeType changeType, size_t countOfPagesToPop, std::string activityId = {}, bool locally = false);
private:
- void addOrUpdateSwitchConfigurationItem(const std::string &activityType);
+ void addOrUpdateSwitchConfigurationItem(const std::string &activityType, bool locally);
const std::string switchId_;
const std::string userName_;
ChangeType changeType_;
#include "RemoveSwitchesPagePresenter.hpp"
#include "SelectActionPagePresenter.hpp"
#include "UniversalSwitchConstants.hpp"
+#include "UpdateAccessoriesSwitchPagePresenter.hpp"
SwitchesPagePresenter::SwitchesPagePresenter()
{
oneSwitch.userName,
model_.getActivityName(oneSwitch.activityType),
[this, oneSwitch](auto item) {
- this->createUpdatePage(oneSwitch.switchId, oneSwitch.userName);
+ this->createUpdatePage(oneSwitch);
}));
}
items.push_back(std::make_unique<ListItem>(
ACCESSIBILITY_UNIVERSAL_SWITCH_PLUS_ICON));
}
-void SwitchesPagePresenter::createUpdatePage(const std::string &switchId, const std::string &userName)
+void SwitchesPagePresenter::createUpdatePage(const SwitchConfigurationItem &item)
{
- auto providerName = utils::stringSplitByDelimiter(switchId, '_')[0];
+ auto providerName = utils::stringSplitByDelimiter(item.switchId, '_')[0];
if (providerName == ACCESSIBILITY_UNIVERSAL_SWITCH_SCREEN_SWITCH_PROVIDER) {
- Singleton<AppContext>::instance().push(std::make_unique<SelectActionPagePresenter>(switchId, userName, ChangeType::UPDATE, 0));
+ Singleton<AppContext>::instance().push(std::make_unique<SelectActionPagePresenter>(item.switchId, item.userName, ChangeType::UPDATE, 0, item.activityType));
return;
}
if (providerName == ACCESSIBILITY_UNIVERSAL_SWITCH_ACCESSORIES_SWITCH_PROVIDER) {
+ Singleton<AppContext>::instance().push(std::make_unique<UpdateAccessoriesSwitchPagePresenter>(item.switchId));
return;
}
if (providerName == ACCESSIBILITY_UNIVERSAL_SWITCH_CAMERA_SWITCH_PROVIDER) {
- Singleton<AppContext>::instance().push(std::make_unique<SelectActionPagePresenter>(switchId, userName, ChangeType::UPDATE, 0));
+ Singleton<AppContext>::instance().push(std::make_unique<SelectActionPagePresenter>(item.switchId, item.userName, ChangeType::UPDATE, 0, item.activityType));
return;
}
}
private:
void addItemsToList();
- void createUpdatePage(const std::string &switchId, const std::string &userName);
+ void createUpdatePage(const SwitchConfigurationItem &item);
void updateSwitchDeleteAction();
SwitchesPageModel model_;
Action *deleteSwitchesAction_ = nullptr;
--- /dev/null
+#include "UpdateAccessoriesSwitchPagePresenter.hpp"
+
+#include "AppContext.hpp"
+#include "SelectActionPagePresenter.hpp"
+
+UpdateAccessoriesSwitchPagePresenter::UpdateAccessoriesSwitchPagePresenter(std::string switchId) : switchId_(std::move(switchId))
+{
+ cancelAction_ = addAction(std::make_unique<Action>("cancelAction",
+ "IDS_ACCS_UNIVERSAL_SWITCH_CANCEL",
+ [this](auto action) {
+ Singleton<AppContext>::instance().pop();
+ }));
+ saveAction_ = addAction(std::make_unique<Action>("saveAction",
+ "IDS_ACCS_UNIVERSAL_SWITCH_SAVE",
+ [this](auto action) {
+ if (!entryItem_->entryText_.value().empty()) {
+ model_.updateSwitch(SwitchConfigurationItem{switchId_, entryItem_->entryText_.value(), activityId_});
+ Singleton<AppContext>::instance().pop();
+ }
+ }));
+ groups_.emplace_back("");
+ auto &items = groups_.back().items_;
+
+ items.push_back(std::make_unique<ListItem>(
+ "IDS_ACCS_UNIVERSAL_SWITCH_NAME",
+ std::string{},
+ std::function<void(ListItem *)>{},
+ ListItem::WidgetType::entry));
+
+ entryItem_ = items.back().get();
+ auto switchInfo = model_.getDetailsForSwitchConfigurationItem(switchId_);
+ entryItem_->entryText_ = switchInfo.userName;
+ activityId_ = switchInfo.activityType;
+
+ items.push_back(std::make_unique<ListItem>(
+ "IDS_ACCS_UNIVERSAL_SWITCH_ACTION",
+ model_.getActivityDetails(switchInfo.activityType).name,
+ [this](auto item) {
+ Singleton<AppContext>::instance().push(std::make_unique<SelectActionPagePresenter>(switchId_, entryItem_->entryText_.value(), ChangeType::UPDATE, 0, activityId_, true));
+ },
+ ListItem::WidgetType::none,
+ std::function<void(ListItem *)>{},
+ std::function<void(ListItem *)>{},
+ false));
+ actionItem_ = items.back().get();
+}
+
+void UpdateAccessoriesSwitchPagePresenter::onTop()
+{
+ auto &sharedPreferences = Singleton<AppContext>::instance().sharedPreferences;
+ auto val = sharedPreferences.find(switchId_);
+ if (val != sharedPreferences.end()) {
+ activityId_ = val->second;
+ actionItem_->description_ = model_.getActivityDetails(activityId_).name;
+ }
+}
+
+UpdateAccessoriesSwitchPagePresenter::~UpdateAccessoriesSwitchPagePresenter()
+{
+ Singleton<AppContext>::instance().sharedPreferences.erase(switchId_);
+}
\ No newline at end of file
--- /dev/null
+#ifndef UPDATE_ACCESSORIES_SWITCH_PAGE_PRESENTER
+#define UPDATE_ACCESSORIES_SWITCH_PAGE_PRESENTER
+
+#include "ListPresenter.hpp"
+#include "UpdateAccessoriesSwitchPageModel.hpp"
+
+class UpdateAccessoriesSwitchPagePresenter : public ListPresenter
+{
+ public:
+ UpdateAccessoriesSwitchPagePresenter(std::string switchId);
+ ~UpdateAccessoriesSwitchPagePresenter();
+
+ private:
+ void onTop() override;
+ std::string switchId_;
+ std::string activityId_;
+ Action *saveAction_ = nullptr;
+ Action *cancelAction_ = nullptr;
+ ListItem *entryItem_ = nullptr;
+ ListItem *actionItem_ = nullptr;
+ UpdateAccessoriesSwitchPageModel model_;
+};
+
+#endif
\ No newline at end of file
{
return create(eldbus_proxy_method_call_new(get(proxy), funcName.c_str()));
}
- MessagePtr eldbus_proxy_send_and_block_impl(const ProxyPtr &proxy, const MessagePtr &msg) override
+ MessagePtr eldbus_proxy_send_and_block_impl(const ProxyPtr &proxy, const MessagePtr &msg, double timeout) override
{
- return create(eldbus_proxy_send_and_block(get(proxy), release(msg), ELDBUS_CALL_TIMEOUT));
+ return create(eldbus_proxy_send_and_block(get(proxy), release(msg), timeout < 0 ? ELDBUS_TIMEOUT_INFINITE : timeout * 1000));
}
bool eldbus_message_error_get_impl(const MessagePtr &msg, std::string &name, std::string &text) override
{
delete d;
}
- PendingPtr eldbus_proxy_send_impl(const ProxyPtr &proxy, const MessagePtr &msg, const SendCallback &callback) override
+ PendingPtr eldbus_proxy_send_impl(const ProxyPtr &proxy, const MessagePtr &msg, const SendCallback &callback, double timeout) override
{
auto cb = new SendCallback{callback};
- auto pending = eldbus_proxy_send(get(proxy), release(msg), callAsyncCb, cb, ELDBUS_CALL_TIMEOUT);
+ auto pending = eldbus_proxy_send(get(proxy), release(msg), callAsyncCb, cb, timeout < 0 ? ELDBUS_TIMEOUT_INFINITE : timeout * 1000);
if (pending) {
eldbus_pending_free_cb_add(pending, pendingFreeCb, cb);
} else {
virtual MessageIterPtr eldbus_message_iter_get_and_next_by_type_impl(const MessageIterPtr &it, int type) = 0;
virtual MessageIterPtr eldbus_message_iter_get_impl(const MessagePtr &it, bool write) = 0;
virtual MessagePtr eldbus_proxy_method_call_new_impl(const ProxyPtr &proxy, const std::string &funcName) = 0;
- virtual MessagePtr eldbus_proxy_send_and_block_impl(const ProxyPtr &proxy, const MessagePtr &msg) = 0;
+ virtual MessagePtr eldbus_proxy_send_and_block_impl(const ProxyPtr &proxy, const MessagePtr &msg, double timeout) = 0;
virtual bool eldbus_message_error_get_impl(const MessagePtr &msg, std::string &name, std::string &text) = 0;
virtual std::string eldbus_message_signature_get_impl(const MessagePtr &msg) = 0;
using SendCallback = std::function<void(const MessagePtr &msg)>;
- virtual PendingPtr eldbus_proxy_send_impl(const ProxyPtr &proxy, const MessagePtr &msg, const SendCallback &callback) = 0;
+ virtual PendingPtr eldbus_proxy_send_impl(const ProxyPtr &proxy, const MessagePtr &msg, const SendCallback &callback, double timeout) = 0;
virtual std::string eldbus_proxy_interface_get_impl(const ProxyPtr &) = 0;
virtual void eldbus_proxy_signal_handler_add_impl(const ProxyPtr &proxy, const std::string &member, const std::function<void(const MessagePtr &)> &cb) = 0;
virtual std::string eldbus_message_iter_signature_get_impl(const MessageIterPtr &iter) = 0;
MessageIterPtr eldbus_message_iter_get_and_next_by_type_impl(const MessageIterPtr &it, int type) override;
MessageIterPtr eldbus_message_iter_get_impl(const MessagePtr &it, bool write) override;
MessagePtr eldbus_proxy_method_call_new_impl(const ProxyPtr &proxy, const std::string &funcName) override;
- MessagePtr eldbus_proxy_send_and_block_impl(const ProxyPtr &proxy, const MessagePtr &msg) override;
+ MessagePtr eldbus_proxy_send_and_block_impl(const ProxyPtr &proxy, const MessagePtr &msg, double timeout) override;
bool eldbus_message_error_get_impl(const MessagePtr &msg, std::string &name, std::string &text) override;
std::string eldbus_message_signature_get_impl(const MessagePtr &msg) override;
- PendingPtr eldbus_proxy_send_impl(const ProxyPtr &proxy, const MessagePtr &msg, const SendCallback &callback) override;
+ PendingPtr eldbus_proxy_send_impl(const ProxyPtr &proxy, const MessagePtr &msg, const SendCallback &callback, double timeout) override;
std::string eldbus_proxy_interface_get_impl(const ProxyPtr &) override;
void eldbus_proxy_signal_handler_add_impl(const ProxyPtr &proxy, const std::string &member, const std::function<void(const MessagePtr &)> &cb) override;
std::string eldbus_message_iter_signature_get_impl(const MessageIterPtr &iter) override;
DBusWrapper::ProxyPtr proxy, propertiesProxy;
};
template <typename RETTYPE, typename... ARGS>
- RETTYPE call(CallId callId, const ConnectionState &connectionState, bool property, const std::string &funcName, const ARGS &... args)
+ RETTYPE call(CallId callId, const ConnectionState &connectionState, bool property, double timeout, const std::string &funcName, const ARGS &... args)
{
const auto &proxy = property ? connectionState.propertiesProxy : connectionState.proxy;
if (!proxy) {
}
detail::packValues(callId, msg, args...);
- auto reply = DBUS_W->eldbus_proxy_send_and_block_impl(proxy, msg);
+ auto reply = DBUS_W->eldbus_proxy_send_and_block_impl(proxy, msg, timeout);
DBUS_DEBUG("call %d: calling '%s' done", callId.id, funcName.c_str());
if (!reply) {
DBUS_DEBUG("call %d: failed", callId.id);
}
template <typename RETTYPE, typename... ARGS>
- void asyncCall(CallId callId, const ConnectionState &connectionState, bool property, const std::string &funcName, std::function<void(RETTYPE)> callback, const ARGS &... args)
+ void asyncCall(CallId callId, const ConnectionState &connectionState, bool property, double timeout, const std::string &funcName, std::function<void(RETTYPE)> callback, const ARGS &... args)
{
const auto &proxy = property ? connectionState.propertiesProxy : connectionState.proxy;
if (!proxy) {
callback(detail::unpackValues<RETTYPE>(callId, reply));
}
}
- });
+ },
+ timeout);
if (pending) {
DBUS_DEBUG("call %d: call sent", callId.id);
} else {
using ConnectionType = DBusWrapper::ConnectionType;
+ struct InfinitiveTimeout_
+ {
+ };
+ static constexpr InfinitiveTimeout_ InfinitiveTimeout;
+
/**
* @brief Class representing client's end of DBUS connection
*
* Allows (synchronous and asynchronos) setting / getting properties.
* Allows registering signals.
*/
+
class DBusClient
{
/// \cond
std::string funcName;
std::string info;
std::shared_ptr<ConnectionInfo> connectionInfo;
+ double timeout_ = 1.0;
/// \endcond
/**
{
detail::CallId callId;
detail::displayDebugCallInfo(callId, funcName, info, connectionInfo->interfaceName);
- return detail::call<RetType>(callId, connectionState, false, funcName, args...);
+ return detail::call<RetType>(callId, connectionState, false, timeout_, funcName, args...);
+ }
+
+ auto &timeout(double d)
+ {
+ timeout_ = d;
+ return *this;
}
+ auto &timeout(InfinitiveTimeout_)
+ {
+ timeout_ = -1;
+ return *this;
+ }
/**
* @brief Executes asynchronous call on DBUS's method
*
{
detail::CallId callId;
detail::displayDebugCallInfo(callId, funcName, info, connectionInfo->interfaceName);
- detail::asyncCall<RetType>(callId, connectionState, false, funcName, std::move(callback), args...);
+ detail::asyncCall<RetType>(callId, connectionState, false, timeout_, funcName, std::move(callback), args...);
}
};
{
elm_entry_cursor_end_set(uniqueObj_.get());
}
+
+void Entry::setSingleline(bool singleline)
+{
+ elm_entry_single_line_set(uniqueObj_.get(), singleline ? EINA_TRUE : EINA_FALSE);
+}
+
+bool Entry::isSingleline()
+{
+ return elm_entry_single_line_get(uniqueObj_.get()) != EINA_FALSE;
+}
void setEntryText(const TranslatedString &text);
std::string getEntryText();
void moveCursorToEnd();
+ void setSingleline(bool singleline);
+ bool isSingleline();
protected:
using Widget::Widget;
auto entry = Widget::make<Entry>(layout);
layout->setPartContent("elm.swallow.content", entry);
entry->setEntryText(entryText_);
+ entry->setSingleline(true);
entry->setEvasSmartCallback("changed,user", [=]() {
this->entryText_ = entry->getEntryText();
if (onContentValueChanged_) {
--- /dev/null
+#include "LabelView.hpp"
+
+#include "AppContext.hpp"
+#include "Button.hpp"
+#include "NavigationContext.hpp"
+#include "Singleton.hpp"
+
+#define EDJ_ACCESSORY "edje/accessibility-smart-switch-accessory.edj"
+#define GRP_ACCESSORY "accessory"
+#define PRT_ACCESSORY_LABEL "accessory_label"
+
+LabelView::LabelView(const NavigationContext &context, Presenter *presenter)
+ : NaviframeView(context), labelPresenter_(static_cast<LabelPresenter *>(presenter))
+{
+ auto naviframe = context.getNaviframe();
+ layout_ = Widget::make<Layout>(naviframe, EDJ_ACCESSORY, GRP_ACCESSORY);
+ layout_->setText(PRT_ACCESSORY_LABEL, labelPresenter_->labelText_.value());
+
+ labelPresenter_->labelText_.attach([this](auto value) {
+ layout_->setText(PRT_ACCESSORY_LABEL, value);
+ });
+ backItem_ = Widget::make<Button>(context.getNaviframe(),
+ []() { Singleton<AppContext>::instance().pop(); },
+ "IDS_ST_BUTTON_BACK",
+ Button::BACK_BUTTON_ARROW_STYLE);
+ naviframeItem_ = naviframe->pushBack(labelPresenter_->getTitle(), layout_, {}, backItem_);
+}
\ No newline at end of file
--- /dev/null
+#ifndef LABEL_VIEW
+#define LABEL_VIEW
+
+#include "Label.hpp"
+#include "LabelPresenter.hpp"
+#include "Layout.hpp"
+#include "NaviframeView.hpp"
+
+class LabelView : public NaviframeView
+{
+ public:
+ LabelView(const NavigationContext &context, Presenter *presenter);
+
+ protected:
+ LabelPresenter *labelPresenter_;
+ Layout *layout_;
+ Widget *backItem_ = nullptr;
+};
+
+#endif
\ No newline at end of file
{
ASSERT(listPresenter_, "ListPresenter required");
- auto naviframe = context.getNaviframe();
- genlist_ = Widget::make<Genlist>(naviframe);
+ naviframe_ = context.getNaviframe();
+ genlist_ = Widget::make<Genlist>(naviframe_);
genlist_->setMode(ELM_LIST_COMPRESS);
genlist_->setStyle("dialogue");
addItemsToGenlist();
});
+ if (!isToolbarNeeded())
+ handleNonToolbarActionsBeforeNaviframePush();
+
+ auto style = isToolbarNeeded() ? "tabbar/notitle" : std::string{};
+ naviframeItem_ = naviframe_->pushBack(listPresenter_->getTitle(), genlist_, {}, backItem_, style);
+
+ if (isToolbarNeeded())
+ handleToolbarActions();
+ else
+ handleNonToolbarActionsAfterNaviframePush();
+}
+
+ListView::~ListView()
+{
+ if (titleRightButton_) {
+ auto parent = titleRightButton_->getParent();
+ parent->removeChild(titleRightButton_);
+ }
+ if (toolbar_) {
+ auto parent = toolbar_->getParent();
+ parent->removeChild(toolbar_);
+ }
+}
+
+bool ListView::isToolbarNeeded()
+{
+ auto cancelAction = listPresenter_->getAction("cancelAction");
+ auto saveAction = listPresenter_->getAction("saveAction");
+ return cancelAction || saveAction;
+}
+
+void ListView::handleToolbarActions()
+{
+ auto cancelAction = listPresenter_->getAction("cancelAction");
+ auto saveAction = listPresenter_->getAction("saveAction");
+ toolbar_ = Widget::make<Toolbar>(naviframe_);
+ if (cancelAction) {
+ toolbar_->addItem(cancelAction->title_.value(), [=]() {
+ cancelAction->onInvoke_(cancelAction);
+ });
+ }
+ if (saveAction) {
+ toolbar_->addItem(saveAction->title_.value(), [=]() {
+ saveAction->onInvoke_(saveAction);
+ });
+ }
+ if (naviframeItem_)
+ naviframeItem_.setPartContent("tabbar", toolbar_);
+}
+
+void ListView::handleNonToolbarActionsBeforeNaviframePush()
+{
if (auto action = listPresenter_->getAction("selectAll")) {
- auto checkbox = Widget::make<Check>(context.getNaviframe());
+ auto checkbox = Widget::make<Check>(naviframe_);
checkbox->setState(action->state_.value());
checkbox->setEvasSmartCallback("changed", [this, action, checkbox]() {
action->state_ = checkbox->getState();
auto wrappedOnClick = [this, action]() {
action->onInvoke_(action);
};
- backItem_ = Widget::make<Button>(context.getNaviframe(),
+ backItem_ = Widget::make<Button>(naviframe_,
wrappedOnClick,
"IDS_ST_BUTTON_BACK",
Button::BACK_BUTTON_ARROW_STYLE);
backItem_->disable(!val);
});
} else {
- backItem_ = Widget::make<Button>(context.getNaviframe(),
+ backItem_ = Widget::make<Button>(naviframe_,
[]() { Singleton<AppContext>::instance().pop(); },
"IDS_ST_BUTTON_BACK",
Button::BACK_BUTTON_ARROW_STYLE);
}
}
+}
- naviframeItem_ = naviframe->pushBack(listPresenter_->getTitle(), genlist_, {}, backItem_);
-
+void ListView::handleNonToolbarActionsAfterNaviframePush()
+{
if (auto action = listPresenter_->getAction("titleRightAction")) {
- titleRightButton_ = Widget::make<Button>(context.getNaviframe(), [this, action]() {
+ titleRightButton_ = Widget::make<Button>(naviframe_, [this, action]() {
action->onInvoke_(action);
},
"<font_size=30>" + TranslatedString{action->title_.value()}.str() + "</font_size>",
action->enabled_.attach([this](auto val) {
titleRightButton_->disable(!val);
});
- naviframe->setPartContent("title_right_btn", titleRightButton_);
- }
-}
-
-ListView::~ListView()
-{
- if (titleRightButton_) {
- auto parent = titleRightButton_->getParent();
- parent->removeChild(titleRightButton_);
+ naviframe_->setPartContent("title_right_btn", titleRightButton_);
}
}
genlistItem = genlist_->appendItem({style,
it->title_.value(),
it->description_.value(),
- it->onItemSelection_ ? wrappedOnItemSelection : std::function<void(GenlistItem *)>{},
+ wrappedOnItemSelection,
it->iconPath_,
type},
groupItem);
genlistItem = genlist_->appendItem({style,
it->title_.value(),
it->description_.value(),
- it->onItemSelection_ ? wrappedOnItemSelection : std::function<void(GenlistItem *)>{},
- it->onWidgetSelection_ ? wrappedOnWidgetSelection : std::function<void(GenlistItem *)>{},
- it->onWidgetChanged_ ? wrappedOnWidgetChanged : std::function<void(GenlistItem *)>{},
+ wrappedOnItemSelection,
+ wrappedOnWidgetSelection,
+ wrappedOnWidgetChanged,
type},
groupItem);
#include "ListPresenter.hpp"
#include "NaviframeView.hpp"
#include "Presenter.hpp"
+#include "Toolbar.hpp"
#include <unordered_map>
private:
void addItemsToGenlist();
+ bool isToolbarNeeded();
+ void handleToolbarActions();
+ void handleNonToolbarActionsBeforeNaviframePush();
+ void handleNonToolbarActionsAfterNaviframePush();
GenlistItem::WidgetType translateType(ListItem::WidgetType t);
ListPresenter *listPresenter_ = nullptr;
std::unordered_map<GenlistItem *, ListItem *> itemsMapping_;
Widget *backItem_ = nullptr;
Button *titleRightButton_ = nullptr;
+ Toolbar *toolbar_ = nullptr;
+ Naviframe *naviframe_ = nullptr;
};
#endif
\ No newline at end of file
#include "ModalView.hpp"
+#include "AppContext.hpp"
#include "Button.hpp"
#include "NavigationContext.hpp"
-#include "Popup.hpp"
+#include "Singleton.hpp"
+
+#define EDJ_ACCESSORY_POPUP "edje/accessibility-smart-switch-accessory-popup.edj"
+#define GRP_ACCESSORY_POPUP "accessory_popup"
+#define PRT_ACCESSORY_POPUP_LABEL "accessory_popup_label"
+#define PRT_ACCESSORY_POPUP_ENTRY "accessory_popup_entry"
ModalView::ModalView(const NavigationContext &context, ModalPresenter *presenter)
: View(context), presenter_(presenter)
{
auto naviframe = context.getNaviframe();
- auto popup = Widget::make<Popup>(naviframe, presenter_->getTitle());
- popup->setOrientation(ELM_POPUP_ORIENT_CENTER);
+ popup_ = Widget::make<Popup>(naviframe, presenter_->getTitle());
+ popup_->setOrientation(ELM_POPUP_ORIENT_CENTER);
- popup->setText(presenter_->getText());
+ auto text = presenter_->getText();
+ if (auto action = presenter_->getAction("modalEntry")) {
+ layout_ = Widget::make<Layout>(popup_, EDJ_ACCESSORY_POPUP, GRP_ACCESSORY_POPUP);
+ entry_ = Widget::make<Entry>(layout_);
+ entry_->setWeightHint(EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ if (!text.empty())
+ entry_->setEntryText(text);
+ if (!action->title_.value().empty())
+ entry_->setPartText("guide", action->title_.value());
+ entry_->setEvasSmartCallback("changed,user", [=]() {
+ action->title_ = entry_->getEntryText();
+ if (action->onInvoke_)
+ action->onInvoke_(action);
+ });
+ layout_->setPartContent(PRT_ACCESSORY_POPUP_ENTRY, entry_);
+ popup_->setContent(layout_);
+ } else {
+ if (!text.empty())
+ popup_->setText(text);
+ }
- auto removeCb = [p = popup, nf = naviframe, this]() {
+ auto removeCb = [this]() {
auto c = presenter_->getCancelCb();
if (c)
c();
- nf->removeChild(p);
+ else
+ Singleton<AppContext>::instance().popModal();
};
- popup->setEextEventCallback(EEXT_CALLBACK_BACK, removeCb);
- popup->setEvasSmartCallback("dismissed", removeCb);
- popup->setEvasSmartCallback("block,clicked", removeCb);
+ popup_->setEextEventCallback(EEXT_CALLBACK_BACK, removeCb);
+ popup_->setEvasSmartCallback("dismissed", removeCb);
+ popup_->setEvasSmartCallback("block,clicked", removeCb);
- auto cancelBtn = Widget::make<Button>(popup, removeCb, "IDS_ST_BUTTON_CANCEL", "bottom");
- popup->setPartContent("button1", cancelBtn);
+ auto cancelText = presenter_->getCancelText();
+ if (!cancelText.empty()) {
+ auto cancelBtn = Widget::make<Button>(popup_, removeCb, cancelText, "bottom");
+ popup_->setPartContent("button1", cancelBtn);
+ }
- auto doneBtn = Widget::make<Button>(popup, [this, p = popup, nf = naviframe]() {
- auto c = presenter_->getDoneCb();
- if (c)
- c();
- nf->removeChild(p);
- },
- presenter->getDoneText(),
- "bottom");
- popup->setPartContent("button2", doneBtn);
+ auto doneText = presenter_->getDoneText();
+ if (!doneText.empty()) {
+ auto doneBtn = Widget::make<Button>(popup_, [this]() {
+ auto c = presenter_->getDoneCb();
+ if (c)
+ c();
+ else
+ Singleton<AppContext>::instance().popModal();
+ },
+ doneText,
+ "bottom");
+ popup_->setPartContent(cancelText.empty() ? "button1" : "button2", doneBtn);
+ }
+}
+
+ModalView::~ModalView()
+{
+ if (popup_) {
+ auto parent = popup_->getParent();
+ parent->removeChild(popup_);
+ }
}
\ No newline at end of file
#ifndef MODAL_VIEW_HPP
#define MODAL_VIEW_HPP
+#include "Entry.hpp"
+#include "Layout.hpp"
#include "ModalPresenter.hpp"
+#include "Popup.hpp"
#include "View.hpp"
class ModalView : public View
{
public:
ModalView(const NavigationContext &context, ModalPresenter *presenter);
+ ~ModalView();
protected:
+ Popup *popup_ = nullptr;
+ Layout *layout_ = nullptr;
+ Entry *entry_ = nullptr;
ModalPresenter *presenter_ = nullptr;
};
#include "AppContext.hpp"
#include "Conformant.hpp"
+#include "LabelPresenter.hpp"
+#include "LabelView.hpp"
#include "ListPresenter.hpp"
#include "ListView.hpp"
#include "Singleton.hpp"
return;
}
+ if (auto lp = dynamic_cast<LabelPresenter *>(presenter)) {
+ viewsStack_.push_back(std::make_unique<LabelView>(*this, lp));
+ return;
+ }
+
ASSERT(0, "Presenter not supported");
}