summaryrefslogtreecommitdiffstats
path: root/xbmc/events
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 18:07:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 18:07:22 +0000
commitc04dcc2e7d834218ef2d4194331e383402495ae1 (patch)
tree7333e38d10d75386e60f336b80c2443c1166031d /xbmc/events
parentInitial commit. (diff)
downloadkodi-c04dcc2e7d834218ef2d4194331e383402495ae1.tar.xz
kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.zip
Adding upstream version 2:20.4+dfsg.upstream/2%20.4+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xbmc/events')
-rw-r--r--xbmc/events/AddonEvent.cpp48
-rw-r--r--xbmc/events/AddonEvent.h39
-rw-r--r--xbmc/events/AddonManagementEvent.cpp74
-rw-r--r--xbmc/events/AddonManagementEvent.h43
-rw-r--r--xbmc/events/BaseEvent.cpp107
-rw-r--r--xbmc/events/BaseEvent.h53
-rw-r--r--xbmc/events/CMakeLists.txt18
-rw-r--r--xbmc/events/EventLog.cpp230
-rw-r--r--xbmc/events/EventLog.h62
-rw-r--r--xbmc/events/EventLogManager.cpp28
-rw-r--r--xbmc/events/EventLogManager.h26
-rw-r--r--xbmc/events/IEvent.h47
-rw-r--r--xbmc/events/MediaLibraryEvent.cpp116
-rw-r--r--xbmc/events/MediaLibraryEvent.h32
-rw-r--r--xbmc/events/NotificationEvent.h34
-rw-r--r--xbmc/events/UniqueEvent.h32
-rw-r--r--xbmc/events/windows/CMakeLists.txt7
-rw-r--r--xbmc/events/windows/GUIViewStateEventLog.cpp35
-rw-r--r--xbmc/events/windows/GUIViewStateEventLog.h29
-rw-r--r--xbmc/events/windows/GUIWindowEventLog.cpp307
-rw-r--r--xbmc/events/windows/GUIWindowEventLog.h37
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);
+};