diff options
Diffstat (limited to '')
-rw-r--r-- | xbmc/events/AddonEvent.cpp | 48 | ||||
-rw-r--r-- | xbmc/events/AddonEvent.h | 39 | ||||
-rw-r--r-- | xbmc/events/AddonManagementEvent.cpp | 74 | ||||
-rw-r--r-- | xbmc/events/AddonManagementEvent.h | 43 | ||||
-rw-r--r-- | xbmc/events/BaseEvent.cpp | 107 | ||||
-rw-r--r-- | xbmc/events/BaseEvent.h | 53 | ||||
-rw-r--r-- | xbmc/events/CMakeLists.txt | 18 | ||||
-rw-r--r-- | xbmc/events/EventLog.cpp | 230 | ||||
-rw-r--r-- | xbmc/events/EventLog.h | 62 | ||||
-rw-r--r-- | xbmc/events/EventLogManager.cpp | 28 | ||||
-rw-r--r-- | xbmc/events/EventLogManager.h | 26 | ||||
-rw-r--r-- | xbmc/events/IEvent.h | 47 | ||||
-rw-r--r-- | xbmc/events/MediaLibraryEvent.cpp | 116 | ||||
-rw-r--r-- | xbmc/events/MediaLibraryEvent.h | 32 | ||||
-rw-r--r-- | xbmc/events/NotificationEvent.h | 34 | ||||
-rw-r--r-- | xbmc/events/UniqueEvent.h | 32 | ||||
-rw-r--r-- | xbmc/events/windows/CMakeLists.txt | 7 | ||||
-rw-r--r-- | xbmc/events/windows/GUIViewStateEventLog.cpp | 35 | ||||
-rw-r--r-- | xbmc/events/windows/GUIViewStateEventLog.h | 29 | ||||
-rw-r--r-- | xbmc/events/windows/GUIWindowEventLog.cpp | 307 | ||||
-rw-r--r-- | xbmc/events/windows/GUIWindowEventLog.h | 37 |
21 files changed, 1404 insertions, 0 deletions
diff --git a/xbmc/events/AddonEvent.cpp b/xbmc/events/AddonEvent.cpp new file mode 100644 index 0000000..459c37d --- /dev/null +++ b/xbmc/events/AddonEvent.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2015-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "AddonEvent.h" + +CAddonEvent::CAddonEvent(const ADDON::AddonPtr& addon, const CVariant& description) + : CUniqueEvent(addon->Name(), description, addon->Icon()), m_addon(addon) +{ } + +CAddonEvent::CAddonEvent(const ADDON::AddonPtr& addon, + const CVariant& description, + const CVariant& details) + : CUniqueEvent(addon->Name(), description, addon->Icon(), details), m_addon(addon) +{ } + +CAddonEvent::CAddonEvent(const ADDON::AddonPtr& addon, + const CVariant& description, + const CVariant& details, + const CVariant& executionLabel) + : CUniqueEvent(addon->Name(), description, addon->Icon(), details, executionLabel), m_addon(addon) +{ } + +CAddonEvent::CAddonEvent(const ADDON::AddonPtr& addon, + EventLevel level, + const CVariant& description) + : CUniqueEvent(addon->Name(), description, addon->Icon(), level), m_addon(addon) +{ } + +CAddonEvent::CAddonEvent(const ADDON::AddonPtr& addon, + EventLevel level, + const CVariant& description, + const CVariant& details) + : CUniqueEvent(addon->Name(), description, addon->Icon(), details, level), m_addon(addon) +{ } + +CAddonEvent::CAddonEvent(const ADDON::AddonPtr& addon, + EventLevel level, + const CVariant& description, + const CVariant& details, + const CVariant& executionLabel) + : CUniqueEvent(addon->Name(), description, addon->Icon(), details, executionLabel, level), + m_addon(addon) +{ } diff --git a/xbmc/events/AddonEvent.h b/xbmc/events/AddonEvent.h new file mode 100644 index 0000000..84154f1 --- /dev/null +++ b/xbmc/events/AddonEvent.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2015-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "addons/IAddon.h" +#include "events/UniqueEvent.h" + +class CAddonEvent : public CUniqueEvent +{ +public: + CAddonEvent(const ADDON::AddonPtr& addon, const CVariant& description); + CAddonEvent(const ADDON::AddonPtr& addon, const CVariant& description, const CVariant& details); + CAddonEvent(const ADDON::AddonPtr& addon, + const CVariant& description, + const CVariant& details, + const CVariant& executionLabel); + CAddonEvent(const ADDON::AddonPtr& addon, EventLevel level, const CVariant& description); + CAddonEvent(const ADDON::AddonPtr& addon, + EventLevel level, + const CVariant& description, + const CVariant& details); + CAddonEvent(const ADDON::AddonPtr& addon, + EventLevel level, + const CVariant& description, + const CVariant& details, + const CVariant& executionLabel); + ~CAddonEvent() override = default; + + const char* GetType() const override { return "AddonEvent"; } + +protected: + ADDON::AddonPtr m_addon; +}; diff --git a/xbmc/events/AddonManagementEvent.cpp b/xbmc/events/AddonManagementEvent.cpp new file mode 100644 index 0000000..6d97915 --- /dev/null +++ b/xbmc/events/AddonManagementEvent.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2015-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "AddonManagementEvent.h" + +#include "addons/gui/GUIDialogAddonInfo.h" +#include "filesystem/AddonsDirectory.h" +#include "guilib/LocalizeStrings.h" +#include "utils/URIUtils.h" + +CAddonManagementEvent::CAddonManagementEvent(const ADDON::AddonPtr& addon, + const CVariant& description) + : CAddonEvent(addon, description) +{ } + +CAddonManagementEvent::CAddonManagementEvent(const ADDON::AddonPtr& addon, + const CVariant& description, + const CVariant& details) + : CAddonEvent(addon, description, details) +{ } + +CAddonManagementEvent::CAddonManagementEvent(const ADDON::AddonPtr& addon, + const CVariant& description, + const CVariant& details, + const CVariant& executionLabel) + : CAddonEvent(addon, description, details, executionLabel) +{ } + +CAddonManagementEvent::CAddonManagementEvent(const ADDON::AddonPtr& addon, + EventLevel level, + const CVariant& description) + : CAddonEvent(addon, level, description) +{ } + +CAddonManagementEvent::CAddonManagementEvent(const ADDON::AddonPtr& addon, + EventLevel level, + const CVariant& description, + const CVariant& details) + : CAddonEvent(addon, level, description, details) +{ } + +CAddonManagementEvent::CAddonManagementEvent(const ADDON::AddonPtr& addon, + EventLevel level, + const CVariant& description, + const CVariant& details, + const CVariant& executionLabel) + : CAddonEvent(addon, level, description, details, executionLabel) +{ } + +std::string CAddonManagementEvent::GetExecutionLabel() const +{ + std::string executionLabel = CAddonEvent::GetExecutionLabel(); + if (!executionLabel.empty()) + return executionLabel; + + return g_localizeStrings.Get(24139); +} + +bool CAddonManagementEvent::Execute() const +{ + if (!CanExecute()) + return false; + + CFileItemPtr addonItem = XFILE::CAddonsDirectory::FileItemFromAddon(m_addon, URIUtils::AddFileToFolder("addons://", m_addon->ID())); + if (addonItem == nullptr) + return false; + + return CGUIDialogAddonInfo::ShowForItem(addonItem); +} diff --git a/xbmc/events/AddonManagementEvent.h b/xbmc/events/AddonManagementEvent.h new file mode 100644 index 0000000..f6f0744 --- /dev/null +++ b/xbmc/events/AddonManagementEvent.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "events/AddonEvent.h" + +class CAddonManagementEvent : public CAddonEvent +{ +public: + CAddonManagementEvent(const ADDON::AddonPtr& addon, const CVariant& description); + CAddonManagementEvent(const ADDON::AddonPtr& addon, + const CVariant& description, + const CVariant& details); + CAddonManagementEvent(const ADDON::AddonPtr& addon, + const CVariant& description, + const CVariant& details, + const CVariant& executionLabel); + CAddonManagementEvent(const ADDON::AddonPtr& addon, + EventLevel level, + const CVariant& description); + CAddonManagementEvent(const ADDON::AddonPtr& addon, + EventLevel level, + const CVariant& description, + const CVariant& details); + CAddonManagementEvent(const ADDON::AddonPtr& addon, + EventLevel level, + const CVariant& description, + const CVariant& details, + const CVariant& executionLabel); + ~CAddonManagementEvent() override = default; + + const char* GetType() const override { return "AddonManagementEvent"; } + std::string GetExecutionLabel() const override; + + bool CanExecute() const override { return m_addon != NULL; } + bool Execute() const override; +}; diff --git a/xbmc/events/BaseEvent.cpp b/xbmc/events/BaseEvent.cpp new file mode 100644 index 0000000..d90207d --- /dev/null +++ b/xbmc/events/BaseEvent.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2015-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "BaseEvent.h" + +#include "guilib/LocalizeStrings.h" +#include "utils/StringUtils.h" + +#include <chrono> +#include <inttypes.h> + +CBaseEvent::CBaseEvent(const std::string& identifier, const CVariant& label, const CVariant& description, EventLevel level /* = EventLevel::Information */) + : m_level(level), + m_identifier(identifier), + m_icon(), + m_label(label), + m_description(description), + m_details(), + m_executionLabel(), + m_timestamp(GetInternalTimestamp()), + m_dateTime(CDateTime::GetCurrentDateTime()) +{ } + +CBaseEvent::CBaseEvent(const std::string& identifier, const CVariant& label, const CVariant& description, const std::string& icon, EventLevel level /* = EventLevel::Information */) + : m_level(level), + m_identifier(identifier), + m_icon(icon), + m_label(label), + m_description(description), + m_details(), + m_executionLabel(), + m_timestamp(GetInternalTimestamp()), + m_dateTime(CDateTime::GetCurrentDateTime()) +{ } + +CBaseEvent::CBaseEvent(const std::string& identifier, const CVariant& label, const CVariant& description, const std::string& icon, const CVariant& details, EventLevel level /* = EventLevel::Information */) + : m_level(level), + m_identifier(identifier), + m_icon(icon), + m_label(label), + m_description(description), + m_details(details), + m_executionLabel(), + m_timestamp(GetInternalTimestamp()), + m_dateTime(CDateTime::GetCurrentDateTime()) +{ } + +CBaseEvent::CBaseEvent(const std::string& identifier, const CVariant& label, const CVariant& description, const std::string& icon, const CVariant& details, const CVariant& executionLabel, EventLevel level /* = EventLevel::Information */) + : m_level(level), + m_identifier(identifier), + m_icon(icon), + m_label(label), + m_description(description), + m_details(details), + m_executionLabel(executionLabel), + m_timestamp(GetInternalTimestamp()), + m_dateTime(CDateTime::GetCurrentDateTime()) +{ } + +uint64_t CBaseEvent::GetInternalTimestamp() +{ + return std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::steady_clock::now()).time_since_epoch().count(); +} + +std::string CBaseEvent::GetLabel() const +{ + return VariantToLocalizedString(m_label); +} + +std::string CBaseEvent::GetDescription() const +{ + return VariantToLocalizedString(m_description); +} + +std::string CBaseEvent::GetDetails() const +{ + return VariantToLocalizedString(m_details); +} + +std::string CBaseEvent::GetExecutionLabel() const +{ + return VariantToLocalizedString(m_executionLabel); +} + +std::string CBaseEvent::VariantToLocalizedString(const CVariant& variant) +{ + if (variant.isString()) + return variant.asString(); + + if (variant.isInteger() && variant.asInteger() > 0) + return g_localizeStrings.Get(static_cast<uint32_t>(variant.asInteger())); + if (variant.isUnsignedInteger() && variant.asUnsignedInteger() > 0) + return g_localizeStrings.Get(static_cast<uint32_t>(variant.asUnsignedInteger())); + + return ""; +} + +void CBaseEvent::ToSortable(SortItem& sortable, Field field) const +{ + if (field == FieldDate) + sortable[FieldDate] = StringUtils::Format("{:020}", m_timestamp); +} diff --git a/xbmc/events/BaseEvent.h b/xbmc/events/BaseEvent.h new file mode 100644 index 0000000..80919b9 --- /dev/null +++ b/xbmc/events/BaseEvent.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2015-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "XBDateTime.h" +#include "events/IEvent.h" +#include "utils/Variant.h" + +class CBaseEvent : public IEvent +{ +public: + ~CBaseEvent() override = default; + + std::string GetIdentifier() const override { return m_identifier; } + EventLevel GetLevel() const override { return m_level; } + std::string GetLabel() const override; + std::string GetIcon() const override { return m_icon; } + std::string GetDescription() const override; + std::string GetDetails() const override; + std::string GetExecutionLabel() const override; + CDateTime GetDateTime() const override { return m_dateTime; } + + bool CanExecute() const override { return !GetExecutionLabel().empty(); } + + void ToSortable(SortItem& sortable, Field field) const override; + +protected: + CBaseEvent(const std::string& identifier, const CVariant& label, const CVariant& description, EventLevel level = EventLevel::Information); + CBaseEvent(const std::string& identifier, const CVariant& label, const CVariant& description, const std::string& icon, EventLevel level = EventLevel::Information); + CBaseEvent(const std::string& identifier, const CVariant& label, const CVariant& description, const std::string& icon, const CVariant& details, EventLevel level = EventLevel::Information); + CBaseEvent(const std::string& identifier, const CVariant& label, const CVariant& description, const std::string& icon, const CVariant& details, const CVariant& executionLabel, EventLevel level = EventLevel::Information); + + EventLevel m_level; + std::string m_identifier; + std::string m_icon; + CVariant m_label; + CVariant m_description; + CVariant m_details; + CVariant m_executionLabel; + +private: + static std::string VariantToLocalizedString(const CVariant& variant); + static uint64_t GetInternalTimestamp(); + + uint64_t m_timestamp; // high res internal time stamp + CDateTime m_dateTime; // user interface time stamp +}; diff --git a/xbmc/events/CMakeLists.txt b/xbmc/events/CMakeLists.txt new file mode 100644 index 0000000..1a490e0 --- /dev/null +++ b/xbmc/events/CMakeLists.txt @@ -0,0 +1,18 @@ +set(SOURCES AddonEvent.cpp + AddonManagementEvent.cpp + BaseEvent.cpp + EventLog.cpp + EventLogManager.cpp + MediaLibraryEvent.cpp) + +set(HEADERS AddonEvent.h + AddonManagementEvent.h + BaseEvent.h + EventLog.h + EventLogManager.h + IEvent.h + MediaLibraryEvent.h + NotificationEvent.h + UniqueEvent.h) + +core_add_library(events) diff --git a/xbmc/events/EventLog.cpp b/xbmc/events/EventLog.cpp new file mode 100644 index 0000000..89eff93 --- /dev/null +++ b/xbmc/events/EventLog.cpp @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2015-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "EventLog.h" + +#include "FileItem.h" +#include "GUIUserMessages.h" +#include "ServiceBroker.h" +#include "dialogs/GUIDialogKaiToast.h" +#include "dialogs/GUIDialogSelect.h" +#include "filesystem/EventsDirectory.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/WindowIDs.h" +#include "profiles/ProfileManager.h" +#include "settings/Settings.h" +#include "settings/SettingsComponent.h" + +#include <mutex> +#include <utility> + +std::string CEventLog::EventLevelToString(EventLevel level) +{ + switch (level) + { + case EventLevel::Basic: + return "basic"; + + case EventLevel::Warning: + return "warning"; + + case EventLevel::Error: + return "error"; + + case EventLevel::Information: + default: + break; + } + + return "information"; +} + +EventLevel CEventLog::EventLevelFromString(const std::string& level) +{ + if (level == "basic") + return EventLevel::Basic; + if (level == "warning") + return EventLevel::Warning; + if (level == "error") + return EventLevel::Error; + + return EventLevel::Information; +} + +Events CEventLog::Get() const +{ + return m_events; +} + +Events CEventLog::Get(EventLevel level, bool includeHigherLevels /* = false */) const +{ + Events events; + + std::unique_lock<CCriticalSection> lock(m_critical); + for (const auto& eventPtr : m_events) + { + if (eventPtr->GetLevel() == level || + (includeHigherLevels && eventPtr->GetLevel() > level)) + events.push_back(eventPtr); + } + + return events; +} + +EventPtr CEventLog::Get(const std::string& eventPtrIdentifier) const +{ + if (eventPtrIdentifier.empty()) + return EventPtr(); + + std::unique_lock<CCriticalSection> lock(m_critical); + const auto& eventPtr = m_eventsMap.find(eventPtrIdentifier); + if (eventPtr == m_eventsMap.end()) + return EventPtr(); + + return eventPtr->second; +} + +void CEventLog::Add(const EventPtr& eventPtr) +{ + if (eventPtr == nullptr || eventPtr->GetIdentifier().empty() || + !CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_EVENTLOG_ENABLED) || + (eventPtr->GetLevel() == EventLevel::Information && !CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_EVENTLOG_ENABLED_NOTIFICATIONS))) + return; + + std::unique_lock<CCriticalSection> lock(m_critical); + if (m_eventsMap.find(eventPtr->GetIdentifier()) != m_eventsMap.end()) + return; + + // store the event + m_events.push_back(eventPtr); + m_eventsMap.insert(std::make_pair(eventPtr->GetIdentifier(), eventPtr)); + + SendMessage(eventPtr, GUI_MSG_EVENT_ADDED); +} + +void CEventLog::Add(const EventPtr& eventPtr, bool withNotification, bool withSound /* = true */) +{ + if (!withNotification) + Add(eventPtr); + else + AddWithNotification(eventPtr, withSound); +} + +void CEventLog::AddWithNotification(const EventPtr& eventPtr, + unsigned int displayTime /* = NOTIFICATION_DISPLAY_TIME */, + unsigned int messageTime /* = NOTIFICATION_MESSAGE_TIME */, + bool withSound /* = true */) +{ + if (eventPtr == nullptr) + return; + + Add(eventPtr); + + // queue the eventPtr as a kai toast notification + if (!eventPtr->GetIcon().empty()) + CGUIDialogKaiToast::QueueNotification(eventPtr->GetIcon(), eventPtr->GetLabel(), eventPtr->GetDescription(), displayTime, withSound, messageTime); + else + { + CGUIDialogKaiToast::eMessageType type = CGUIDialogKaiToast::Info; + if (eventPtr->GetLevel() == EventLevel::Warning) + type = CGUIDialogKaiToast::Warning; + else if (eventPtr->GetLevel() == EventLevel::Error) + type = CGUIDialogKaiToast::Error; + + CGUIDialogKaiToast::QueueNotification(type, eventPtr->GetLabel(), eventPtr->GetDescription(), displayTime, withSound, messageTime); + } +} + +void CEventLog::AddWithNotification(const EventPtr& eventPtr, bool withSound) +{ + AddWithNotification(eventPtr, NOTIFICATION_DISPLAY_TIME, NOTIFICATION_MESSAGE_TIME, withSound); +} + +void CEventLog::Remove(const EventPtr& eventPtr) +{ + if (eventPtr == nullptr) + return; + + Remove(eventPtr->GetIdentifier()); +} + +void CEventLog::Remove(const std::string& eventPtrIdentifier) +{ + if (eventPtrIdentifier.empty()) + return; + + std::unique_lock<CCriticalSection> lock(m_critical); + const auto& itEvent = m_eventsMap.find(eventPtrIdentifier); + if (itEvent == m_eventsMap.end()) + return; + + EventPtr eventPtr = itEvent->second; + m_eventsMap.erase(itEvent); + m_events.erase(std::remove(m_events.begin(), m_events.end(), eventPtr), m_events.end()); + + SendMessage(eventPtr, GUI_MSG_EVENT_REMOVED); +} + +void CEventLog::Clear() +{ + std::unique_lock<CCriticalSection> lock(m_critical); + m_events.clear(); + m_eventsMap.clear(); +} + +void CEventLog::Clear(EventLevel level, bool includeHigherLevels /* = false */) +{ + EventsList eventsCopy = m_events; + for (const auto& eventPtr : eventsCopy) + { + + if (eventPtr->GetLevel() == level || + (includeHigherLevels && eventPtr->GetLevel() > level)) + Remove(eventPtr); + } +} + +bool CEventLog::Execute(const std::string& eventPtrIdentifier) +{ + if (eventPtrIdentifier.empty()) + return false; + + std::unique_lock<CCriticalSection> lock(m_critical); + const auto& itEvent = m_eventsMap.find(eventPtrIdentifier); + if (itEvent == m_eventsMap.end()) + return false; + + return itEvent->second->Execute(); +} + +void CEventLog::ShowFullEventLog(EventLevel level /* = EventLevel::Basic */, bool includeHigherLevels /* = true */) +{ + // put together the path + std::string path = "events://"; + if (level != EventLevel::Basic || !includeHigherLevels) + { + // add the level to the path + path += EventLevelToString(level); + // add whether to include higher levels or not to the path + if (includeHigherLevels) + path += "+"; + } + + // activate the full eventPtr log window + std::vector<std::string> params; + params.push_back(path); + params.emplace_back("return"); + CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow(WINDOW_EVENT_LOG, params); +} + +void CEventLog::SendMessage(const EventPtr& eventPtr, int message) +{ + CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, message, 0, XFILE::CEventsDirectory::EventToFileItem(eventPtr)); + CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg); +} diff --git a/xbmc/events/EventLog.h b/xbmc/events/EventLog.h new file mode 100644 index 0000000..035e448 --- /dev/null +++ b/xbmc/events/EventLog.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2015-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "events/IEvent.h" +#include "threads/CriticalSection.h" + +#include <map> +#include <string> +#include <vector> + +#define NOTIFICATION_DISPLAY_TIME 5000 +#define NOTIFICATION_MESSAGE_TIME 1000 + +typedef std::vector<EventPtr> Events; + +class CEventLog +{ +public: + CEventLog() = default; + CEventLog(const CEventLog&) = delete; + CEventLog& operator=(CEventLog const&) = delete; + ~CEventLog() = default; + + Events Get() const; + Events Get(EventLevel level, bool includeHigherLevels = false) const; + EventPtr Get(const std::string& eventIdentifier) const; + + void Add(const EventPtr& event); + void Add(const EventPtr& event, bool withNotification, bool withSound = true); + void AddWithNotification(const EventPtr& event, + unsigned int displayTime = NOTIFICATION_DISPLAY_TIME, + unsigned int messageTime = NOTIFICATION_MESSAGE_TIME, + bool withSound = true); + void AddWithNotification(const EventPtr& event, bool withSound); + void Remove(const EventPtr& event); + void Remove(const std::string& eventIdentifier); + void Clear(); + void Clear(EventLevel level, bool includeHigherLevels = false); + + bool Execute(const std::string& eventIdentifier); + + static std::string EventLevelToString(EventLevel level); + static EventLevel EventLevelFromString(const std::string& level); + + void ShowFullEventLog(EventLevel level = EventLevel::Basic, bool includeHigherLevels = true); + +private: + void SendMessage(const EventPtr& event, int message); + + typedef std::vector<EventPtr> EventsList; + typedef std::map<std::string, EventPtr> EventsMap; + EventsList m_events; + EventsMap m_eventsMap; + mutable CCriticalSection m_critical; +}; diff --git a/xbmc/events/EventLogManager.cpp b/xbmc/events/EventLogManager.cpp new file mode 100644 index 0000000..d56b88a --- /dev/null +++ b/xbmc/events/EventLogManager.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "EventLogManager.h" + +#include "EventLog.h" + +#include <mutex> +#include <utility> + +CEventLog& CEventLogManager::GetEventLog(unsigned int profileId) +{ + std::unique_lock<CCriticalSection> lock(m_eventMutex); + + auto eventLog = m_eventLogs.find(profileId); + if (eventLog == m_eventLogs.end()) + { + m_eventLogs.insert(std::make_pair(profileId, std::unique_ptr<CEventLog>(new CEventLog))); + eventLog = m_eventLogs.find(profileId); + } + + return *eventLog->second; +} diff --git a/xbmc/events/EventLogManager.h b/xbmc/events/EventLogManager.h new file mode 100644 index 0000000..033dbc0 --- /dev/null +++ b/xbmc/events/EventLogManager.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "threads/CriticalSection.h" + +#include <map> +#include <memory> + +class CEventLog; + +class CEventLogManager +{ +public: + CEventLog &GetEventLog(unsigned int profileId); + +private: + std::map<unsigned int, std::unique_ptr<CEventLog>> m_eventLogs; + CCriticalSection m_eventMutex; +}; diff --git a/xbmc/events/IEvent.h b/xbmc/events/IEvent.h new file mode 100644 index 0000000..4ff8c02 --- /dev/null +++ b/xbmc/events/IEvent.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "utils/ISortable.h" + +#include <memory> +#include <string> + +class CDateTime; + +enum class EventLevel +{ + Basic = 0, + Information = 1, + Warning = 2, + Error = 3, +}; + +class IEvent : public ISortable +{ +public: + virtual ~IEvent() = default; + + virtual const char* GetType() const = 0; + virtual std::string GetIdentifier() const = 0; + virtual EventLevel GetLevel() const = 0; + virtual std::string GetLabel() const = 0; + virtual std::string GetIcon() const = 0; + virtual std::string GetDescription() const = 0; + virtual std::string GetDetails() const = 0; + virtual std::string GetExecutionLabel() const = 0; + virtual CDateTime GetDateTime() const = 0; + + virtual bool CanExecute() const = 0; + virtual bool Execute() const = 0; + + void ToSortable(SortItem& sortable, Field field) const override = 0; +}; + +typedef std::shared_ptr<const IEvent> EventPtr; diff --git a/xbmc/events/MediaLibraryEvent.cpp b/xbmc/events/MediaLibraryEvent.cpp new file mode 100644 index 0000000..c079f5d --- /dev/null +++ b/xbmc/events/MediaLibraryEvent.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2015-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "MediaLibraryEvent.h" + +#include "ServiceBroker.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/LocalizeStrings.h" +#include "guilib/WindowIDs.h" +#include "utils/URIUtils.h" + +CMediaLibraryEvent::CMediaLibraryEvent(const MediaType& mediaType, const std::string& mediaPath, const CVariant& label, const CVariant& description, EventLevel level /* = EventLevel::Information */) + : CUniqueEvent(label, description, level), + m_mediaType(mediaType), + m_mediaPath(mediaPath) +{ } + +CMediaLibraryEvent::CMediaLibraryEvent(const MediaType& mediaType, const std::string& mediaPath, const CVariant& label, const CVariant& description, const std::string& icon, EventLevel level /* = EventLevel::Information */) + : CUniqueEvent(label, description, icon, level), + m_mediaType(mediaType), + m_mediaPath(mediaPath) +{ } + +CMediaLibraryEvent::CMediaLibraryEvent(const MediaType& mediaType, const std::string& mediaPath, const CVariant& label, const CVariant& description, const std::string& icon, const CVariant& details, EventLevel level /* = EventLevel::Information */) + : CUniqueEvent(label, description, icon, details, level), + m_mediaType(mediaType), + m_mediaPath(mediaPath) +{ } + +CMediaLibraryEvent::CMediaLibraryEvent(const MediaType& mediaType, const std::string& mediaPath, const CVariant& label, const CVariant& description, const std::string& icon, const CVariant& details, const CVariant& executionLabel, EventLevel level /* = EventLevel::Information */) + : CUniqueEvent(label, description, icon, details, executionLabel, level), + m_mediaType(mediaType), + m_mediaPath(mediaPath) +{ } + +std::string CMediaLibraryEvent::GetExecutionLabel() const +{ + std::string executionLabel = CUniqueEvent::GetExecutionLabel(); + if (!executionLabel.empty()) + return executionLabel; + + return g_localizeStrings.Get(24140); +} + +bool CMediaLibraryEvent::Execute() const +{ + if (!CanExecute()) + return false; + + int windowId = -1; + std::string path = m_mediaPath; + if (m_mediaType == MediaTypeVideo || m_mediaType == MediaTypeMovie || m_mediaType == MediaTypeVideoCollection || + m_mediaType == MediaTypeTvShow || m_mediaType == MediaTypeSeason || m_mediaType == MediaTypeEpisode || + m_mediaType == MediaTypeMusicVideo) + { + if (path.empty()) + { + if (m_mediaType == MediaTypeVideo) + path = "sources://video/"; + else if (m_mediaType == MediaTypeMovie) + path = "videodb://movies/titles/"; + else if (m_mediaType == MediaTypeVideoCollection) + path = "videodb://movies/sets/"; + else if (m_mediaType == MediaTypeMusicVideo) + path = "videodb://musicvideos/titles/"; + else if (m_mediaType == MediaTypeTvShow || m_mediaType == MediaTypeSeason || m_mediaType == MediaTypeEpisode) + path = "videodb://tvshows/titles/"; + } + else + { + //! @todo remove the filename for now as CGUIMediaWindow::GetDirectory() can't handle it + if (m_mediaType == MediaTypeMovie || m_mediaType == MediaTypeMusicVideo || m_mediaType == MediaTypeEpisode) + path = URIUtils::GetDirectory(path); + } + + windowId = WINDOW_VIDEO_NAV; + } + else if (m_mediaType == MediaTypeMusic || m_mediaType == MediaTypeArtist || + m_mediaType == MediaTypeAlbum || m_mediaType == MediaTypeSong) + { + if (path.empty()) + { + if (m_mediaType == MediaTypeMusic) + path = "sources://music/"; + else if (m_mediaType == MediaTypeArtist) + path = "musicdb://artists/"; + else if (m_mediaType == MediaTypeAlbum) + path = "musicdb://albums/"; + else if (m_mediaType == MediaTypeSong) + path = "musicdb://songs/"; + } + else + { + //! @todo remove the filename for now as CGUIMediaWindow::GetDirectory() can't handle it + if (m_mediaType == MediaTypeSong) + path = URIUtils::GetDirectory(path); + } + + windowId = WINDOW_MUSIC_NAV; + } + + if (windowId < 0) + return false; + + std::vector<std::string> params; + params.push_back(path); + params.emplace_back("return"); + CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow(windowId, params); + return true; +} diff --git a/xbmc/events/MediaLibraryEvent.h b/xbmc/events/MediaLibraryEvent.h new file mode 100644 index 0000000..effd4ac --- /dev/null +++ b/xbmc/events/MediaLibraryEvent.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2015-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "events/UniqueEvent.h" +#include "media/MediaType.h" + +class CMediaLibraryEvent : public CUniqueEvent +{ +public: + CMediaLibraryEvent(const MediaType& mediaType, const std::string& mediaPath, const CVariant& label, const CVariant& description, EventLevel level = EventLevel::Information); + CMediaLibraryEvent(const MediaType& mediaType, const std::string& mediaPath, const CVariant& label, const CVariant& description, const std::string& icon, EventLevel level = EventLevel::Information); + CMediaLibraryEvent(const MediaType& mediaType, const std::string& mediaPath, const CVariant& label, const CVariant& description, const std::string& icon, const CVariant& details, EventLevel level = EventLevel::Information); + CMediaLibraryEvent(const MediaType& mediaType, const std::string& mediaPath, const CVariant& label, const CVariant& description, const std::string& icon, const CVariant& details, const CVariant& executionLabel, EventLevel level = EventLevel::Information); + ~CMediaLibraryEvent() override = default; + + const char* GetType() const override { return "MediaLibraryEvent"; } + std::string GetExecutionLabel() const override; + + bool CanExecute() const override { return !m_mediaType.empty(); } + bool Execute() const override; + +protected: + MediaType m_mediaType; + std::string m_mediaPath; +}; diff --git a/xbmc/events/NotificationEvent.h b/xbmc/events/NotificationEvent.h new file mode 100644 index 0000000..b4be9b7 --- /dev/null +++ b/xbmc/events/NotificationEvent.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2015-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "events/UniqueEvent.h" + +class CNotificationEvent : public CUniqueEvent +{ +public: + CNotificationEvent(const CVariant& label, const CVariant& description, EventLevel level = EventLevel::Information) + : CUniqueEvent(label, description, level) + { } + CNotificationEvent(const CVariant& label, const CVariant& description, const std::string& icon, EventLevel level = EventLevel::Information) + : CUniqueEvent(label, description, icon, level) + { } + CNotificationEvent(const CVariant& label, const CVariant& description, const std::string& icon, const CVariant& details, EventLevel level = EventLevel::Information) + : CUniqueEvent(label, description, icon, details, level) + { } + CNotificationEvent(const CVariant& label, const CVariant& description, const std::string& icon, const CVariant& details, const CVariant& executionLabel, EventLevel level = EventLevel::Information) + : CUniqueEvent(label, description, icon, details, executionLabel, level) + { } + ~CNotificationEvent() override = default; + + const char* GetType() const override { return "NotificationEvent"; } + + bool CanExecute() const override { return false; } + bool Execute() const override { return true; } +}; diff --git a/xbmc/events/UniqueEvent.h b/xbmc/events/UniqueEvent.h new file mode 100644 index 0000000..4a03fc3 --- /dev/null +++ b/xbmc/events/UniqueEvent.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2015-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "events/BaseEvent.h" +#include "utils/StringUtils.h" + +class CUniqueEvent : public CBaseEvent +{ +public: + ~CUniqueEvent() override = default; + +protected: + CUniqueEvent(const CVariant& label, const CVariant& description, EventLevel level = EventLevel::Information) + : CBaseEvent(StringUtils::CreateUUID(), label, description, level) + { } + CUniqueEvent(const CVariant& label, const CVariant& description, const std::string& icon, EventLevel level = EventLevel::Information) + : CBaseEvent(StringUtils::CreateUUID(), label, description, icon, level) + { } + CUniqueEvent(const CVariant& label, const CVariant& description, const std::string& icon, const CVariant& details, EventLevel level = EventLevel::Information) + : CBaseEvent(StringUtils::CreateUUID(), label, description, icon, details, level) + { } + CUniqueEvent(const CVariant& label, const CVariant& description, const std::string& icon, const CVariant& details, const CVariant& executionLabel, EventLevel level = EventLevel::Information) + : CBaseEvent(StringUtils::CreateUUID(), label, description, icon, details, executionLabel, level) + { } +}; diff --git a/xbmc/events/windows/CMakeLists.txt b/xbmc/events/windows/CMakeLists.txt new file mode 100644 index 0000000..fcd0b94 --- /dev/null +++ b/xbmc/events/windows/CMakeLists.txt @@ -0,0 +1,7 @@ +set(SOURCES GUIViewStateEventLog.cpp + GUIWindowEventLog.cpp) + +set(HEADERS GUIViewStateEventLog.h + GUIWindowEventLog.h) + +core_add_library(events_windows) diff --git a/xbmc/events/windows/GUIViewStateEventLog.cpp b/xbmc/events/windows/GUIViewStateEventLog.cpp new file mode 100644 index 0000000..1f6dd66 --- /dev/null +++ b/xbmc/events/windows/GUIViewStateEventLog.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2015-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GUIViewStateEventLog.h" + +#include "FileItem.h" +#include "guilib/WindowIDs.h" +#include "view/ViewState.h" +#include "windowing/GraphicContext.h" + +CGUIViewStateEventLog::CGUIViewStateEventLog(const CFileItemList& items) : CGUIViewState(items) +{ + AddSortMethod(SortByDate, 552, LABEL_MASKS("%L", "%d", "%L", "%d")); // Label, Date | Label, Date + + SetSortMethod(SortByDate); + SetViewAsControl(DEFAULT_VIEW_AUTO); + + SetSortOrder(SortOrderDescending); + LoadViewState(items.GetPath(), WINDOW_EVENT_LOG); +} + +void CGUIViewStateEventLog::SaveViewState() +{ + SaveViewToDb(m_items.GetPath(), WINDOW_EVENT_LOG); +} + +std::string CGUIViewStateEventLog::GetExtensions() +{ + return ""; +} diff --git a/xbmc/events/windows/GUIViewStateEventLog.h b/xbmc/events/windows/GUIViewStateEventLog.h new file mode 100644 index 0000000..d7436ed --- /dev/null +++ b/xbmc/events/windows/GUIViewStateEventLog.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "view/GUIViewState.h" + +class CGUIViewStateEventLog : public CGUIViewState +{ +public: + explicit CGUIViewStateEventLog(const CFileItemList& items); + ~CGUIViewStateEventLog() override = default; + + // specializations of CGUIViewState + bool HideExtensions() override { return true; } + bool HideParentDirItems() override { return true; } + bool DisableAddSourceButtons() override { return true; } + +protected: + // specializations of CGUIViewState + void SaveViewState() override; + std::string GetExtensions() override; +}; + diff --git a/xbmc/events/windows/GUIWindowEventLog.cpp b/xbmc/events/windows/GUIWindowEventLog.cpp new file mode 100644 index 0000000..01ec4bb --- /dev/null +++ b/xbmc/events/windows/GUIWindowEventLog.cpp @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2015-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GUIWindowEventLog.h" + +#include "FileItem.h" +#include "GUIUserMessages.h" +#include "ServiceBroker.h" +#include "URL.h" +#include "events/EventLog.h" +#include "filesystem/EventsDirectory.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/LocalizeStrings.h" +#include "guilib/WindowIDs.h" +#include "input/Key.h" +#include "settings/Settings.h" +#include "settings/SettingsComponent.h" +#include "utils/StringUtils.h" +#include "view/ViewStateSettings.h" + +#define CONTROL_BUTTON_CLEAR 20 +#define CONTROL_BUTTON_LEVEL 21 +#define CONTROL_BUTTON_LEVEL_ONLY 22 + +CGUIWindowEventLog::CGUIWindowEventLog() + : CGUIMediaWindow(WINDOW_EVENT_LOG, "EventLog.xml") +{ } + +CGUIWindowEventLog::~CGUIWindowEventLog() = default; + +bool CGUIWindowEventLog::OnMessage(CGUIMessage& message) +{ + switch (message.GetMessage()) + { + case GUI_MSG_CLICKED: + { + int iControl = message.GetSenderId(); + + // check if we should clear all items + if (iControl == CONTROL_BUTTON_CLEAR) + { + auto eventLog = CServiceBroker::GetEventLog(); + if (eventLog) + eventLog->Clear(CViewStateSettings::GetInstance().GetEventLevel(), + CViewStateSettings::GetInstance().ShowHigherEventLevels()); + + // refresh the list + Refresh(true); + return true; + } + + // check if we should change the level + if (iControl == CONTROL_BUTTON_LEVEL) + { + // update the event level + CViewStateSettings::GetInstance().CycleEventLevel(); + CServiceBroker::GetSettingsComponent()->GetSettings()->Save(); + + // update the listing + Refresh(); + return true; + } + + // check if we should change the level + if (iControl == CONTROL_BUTTON_LEVEL_ONLY) + { + // update whether to show higher event levels + CViewStateSettings::GetInstance().ToggleShowHigherEventLevels(); + CServiceBroker::GetSettingsComponent()->GetSettings()->Save(); + + // update the listing + Refresh(); + return true; + } + + // check if the user interacted with one of the events + if (m_viewControl.HasControl(iControl)) + { + // get selected item + int itemIndex = m_viewControl.GetSelectedItem(); + if (itemIndex < 0 || itemIndex >= m_vecItems->Size()) + break; + + CFileItemPtr item = m_vecItems->Get(itemIndex); + int actionId = message.GetParam1(); + + if (actionId == ACTION_DELETE_ITEM) + return OnDelete(item); + } + + break; + } + + case GUI_MSG_NOTIFY_ALL: + { + CFileItemPtr item = std::dynamic_pointer_cast<CFileItem>(message.GetItem()); + if (item == nullptr) + break; + + switch (message.GetParam1()) + { + case GUI_MSG_EVENT_ADDED: + OnEventAdded(item); + return true; + + case GUI_MSG_EVENT_REMOVED: + OnEventRemoved(item); + return true; + + default: + break; + } + } + + default: + break; + } + + return CGUIMediaWindow::OnMessage(message); +} + +bool CGUIWindowEventLog::OnSelect(int item) +{ + if (item < 0 || item >= m_vecItems->Size()) + return false; + + return OnSelect(m_vecItems->Get(item)); +} + +void CGUIWindowEventLog::GetContextButtons(int itemNumber, CContextButtons &buttons) +{ + if (itemNumber < 0 && itemNumber >= m_vecItems->Size()) + return; + + CFileItemPtr item = m_vecItems->Get(itemNumber); + if (item == nullptr) + return; + + std::string eventIdentifier = item->GetProperty(PROPERTY_EVENT_IDENTIFIER).asString(); + if (eventIdentifier.empty()) + return; + + auto eventLog = CServiceBroker::GetEventLog(); + if (!eventLog) + return; + + EventPtr eventPtr = eventLog->Get(eventIdentifier); + if (eventPtr == nullptr) + return; + + buttons.Add(CONTEXT_BUTTON_DELETE, g_localizeStrings.Get(1210)); +} + +bool CGUIWindowEventLog::OnContextButton(int itemNumber, CONTEXT_BUTTON button) +{ + if (itemNumber < 0 && itemNumber >= m_vecItems->Size()) + return false; + + CFileItemPtr item = m_vecItems->Get(itemNumber); + if (item == nullptr) + return false; + + switch (button) + { + case CONTEXT_BUTTON_DELETE: + return OnDelete(item); + + default: + break; + } + + return CGUIMediaWindow::OnContextButton(itemNumber, button); +} + +void CGUIWindowEventLog::UpdateButtons() +{ + // only enable the "clear" button if there is something to clear + CONTROL_ENABLE_ON_CONDITION(CONTROL_BUTTON_CLEAR, m_vecItems->GetObjectCount() > 0); + + EventLevel eventLevel = CViewStateSettings::GetInstance().GetEventLevel(); + // set the label of the "level" button + SET_CONTROL_LABEL(CONTROL_BUTTON_LEVEL, + StringUtils::Format(g_localizeStrings.Get(14119), + g_localizeStrings.Get(14115 + (int)eventLevel))); + + // set the label, value and enabled state of the "level only" button + SET_CONTROL_LABEL(CONTROL_BUTTON_LEVEL_ONLY, 14120); + SET_CONTROL_SELECTED(GetID(), CONTROL_BUTTON_LEVEL_ONLY, CViewStateSettings::GetInstance().ShowHigherEventLevels()); + CONTROL_ENABLE_ON_CONDITION(CONTROL_BUTTON_LEVEL_ONLY, eventLevel < EventLevel::Error); + + CGUIMediaWindow::UpdateButtons(); +} + +bool CGUIWindowEventLog::GetDirectory(const std::string &strDirectory, CFileItemList &items) +{ + bool result = CGUIMediaWindow::GetDirectory(strDirectory, items); + + EventLevel currentLevel = CViewStateSettings::GetInstance().GetEventLevel(); + bool showHigherLevels = CViewStateSettings::GetInstance().ShowHigherEventLevels(); + + CFileItemList filteredItems(items.GetPath()); + for (int i = 0; i < items.Size(); i++) + { + CFileItemPtr item = items.Get(i); + if (item->IsParentFolder()) + { + filteredItems.Add(item); + continue; + } + + if (!item->HasProperty(PROPERTY_EVENT_LEVEL)) + continue; + + EventLevel level = CEventLog::EventLevelFromString(item->GetProperty(PROPERTY_EVENT_LEVEL).asString()); + if (level == currentLevel || + (level > currentLevel && showHigherLevels)) + filteredItems.Add(item); + } + + items.ClearItems(); + items.Append(filteredItems); + + return result; +} + +bool CGUIWindowEventLog::OnSelect(const CFileItemPtr& item) +{ + if (item == nullptr) + return false; + + OnExecute(item); + return true; +} + +bool CGUIWindowEventLog::OnDelete(const CFileItemPtr& item) +{ + if (item == nullptr) + return false; + + std::string eventIdentifier = item->GetProperty(PROPERTY_EVENT_IDENTIFIER).asString(); + if (eventIdentifier.empty()) + return false; + + auto eventLog = CServiceBroker::GetEventLog(); + if (!eventLog) + return false; + + eventLog->Remove(eventIdentifier); + return true; +} + +bool CGUIWindowEventLog::OnExecute(const CFileItemPtr& item) +{ + if (item == nullptr) + return false; + + std::string eventIdentifier = item->GetProperty(PROPERTY_EVENT_IDENTIFIER).asString(); + if (eventIdentifier.empty()) + return false; + + auto eventLog = CServiceBroker::GetEventLog(); + if (!eventLog) + return false; + + const EventPtr eventPtr = eventLog->Get(eventIdentifier); + if (eventPtr == nullptr) + return false; + + if (!eventPtr->CanExecute()) + return true; + + return eventPtr->Execute(); +} + +void CGUIWindowEventLog::OnEventAdded(const CFileItemPtr& item) +{ + if (!IsActive()) + return; + + Refresh(true); +} + +void CGUIWindowEventLog::OnEventRemoved(const CFileItemPtr& item) +{ + if (!IsActive()) + return; + + int selectedItemIndex = -1; + if (item != nullptr) + { + selectedItemIndex = m_viewControl.GetSelectedItem(); + // only update the selected item index when the deleted item is focused + if (m_vecItems->Get(selectedItemIndex)->GetProperty(PROPERTY_EVENT_IDENTIFIER).asString() != item->GetProperty(PROPERTY_EVENT_IDENTIFIER).asString()) + selectedItemIndex = -1; + } + + Refresh(true); + + // update the selected item + if (selectedItemIndex >= 0) + m_viewControl.SetSelectedItem(selectedItemIndex); +} diff --git a/xbmc/events/windows/GUIWindowEventLog.h b/xbmc/events/windows/GUIWindowEventLog.h new file mode 100644 index 0000000..d3cb22a --- /dev/null +++ b/xbmc/events/windows/GUIWindowEventLog.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2015-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "windows/GUIMediaWindow.h" + +class CGUIWindowEventLog : public CGUIMediaWindow +{ +public: + CGUIWindowEventLog(); + ~CGUIWindowEventLog() override; + + // specialization of CGUIControl + bool OnMessage(CGUIMessage& message) override; + +protected: + // specialization of CGUIMediaWindow + bool OnSelect(int item) override; + void GetContextButtons(int itemNumber, CContextButtons &buttons) override; + bool OnContextButton(int itemNumber, CONTEXT_BUTTON button) override; + void UpdateButtons() override; + bool GetDirectory(const std::string &strDirectory, CFileItemList &items) override; + std::string GetRootPath() const override { return "events://"; } + + bool OnSelect(const CFileItemPtr& item); + bool OnDelete(const CFileItemPtr& item); + bool OnExecute(const CFileItemPtr& item); + + void OnEventAdded(const CFileItemPtr& item); + void OnEventRemoved(const CFileItemPtr& item); +}; |