mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-06 16:09:30 +00:00
Ladybird: Add a simple TaskManager window for tracking child processes
This implementation uses a really basic WebView to update stats once a second. In the future it might make more sense to both move the details into LibWebView, and to create a native widget for each platform to remove the overhead of having an extra WebView.
This commit is contained in:
parent
096feaaeb8
commit
31c0d00ab1
|
@ -124,6 +124,7 @@ if (ENABLE_QT)
|
|||
Qt/Settings.cpp
|
||||
Qt/SettingsDialog.cpp
|
||||
Qt/Tab.cpp
|
||||
Qt/TaskManagerWindow.cpp
|
||||
Qt/TVGIconEngine.cpp
|
||||
Qt/StringUtils.cpp
|
||||
Qt/WebContentView.cpp
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "Settings.h"
|
||||
#include "SettingsDialog.h"
|
||||
#include "StringUtils.h"
|
||||
#include "TaskManagerWindow.h"
|
||||
#include "WebContentView.h"
|
||||
#include <AK/TypeCasts.h>
|
||||
#include <Ladybird/Utilities.h>
|
||||
|
@ -21,6 +22,7 @@
|
|||
#include <LibWebView/UserAgent.h>
|
||||
#include <QAction>
|
||||
#include <QActionGroup>
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QGuiApplication>
|
||||
#include <QInputDialog>
|
||||
|
@ -213,6 +215,14 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> const& initial_urls, WebView::Cook
|
|||
}
|
||||
});
|
||||
|
||||
auto* task_manager_action = new QAction("Open Task &Manager", this);
|
||||
task_manager_action->setIcon(load_icon_from_uri("resource://icons/16x16/app-system-monitor.png"sv));
|
||||
task_manager_action->setShortcuts({ QKeySequence("Ctrl+Shift+M") });
|
||||
inspect_menu->addAction(task_manager_action);
|
||||
QObject::connect(task_manager_action, &QAction::triggered, this, [this] {
|
||||
show_task_manager_window();
|
||||
});
|
||||
|
||||
auto* debug_menu = menuBar()->addMenu("&Debug");
|
||||
|
||||
auto* dump_session_history_tree_action = new QAction("Dump Session History Tree", this);
|
||||
|
@ -890,4 +900,20 @@ void BrowserWindow::closeEvent(QCloseEvent* event)
|
|||
QMainWindow::closeEvent(event);
|
||||
}
|
||||
|
||||
void BrowserWindow::show_task_manager_window()
|
||||
{
|
||||
if (!m_task_manager_window) {
|
||||
m_task_manager_window = new TaskManagerWindow(this);
|
||||
}
|
||||
m_task_manager_window->show();
|
||||
m_task_manager_window->activateWindow();
|
||||
m_task_manager_window->raise();
|
||||
}
|
||||
|
||||
void BrowserWindow::close_task_manager_window()
|
||||
{
|
||||
if (m_task_manager_window)
|
||||
m_task_manager_window->close();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace Ladybird {
|
|||
|
||||
class SettingsDialog;
|
||||
class WebContentView;
|
||||
class TaskManagerWindow;
|
||||
|
||||
class BrowserWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
|
@ -132,6 +133,9 @@ private:
|
|||
QString tool_tip_for_page_mute_state(Tab&) const;
|
||||
QTabBar::ButtonPosition audio_button_position_for_tab(int tab_index) const;
|
||||
|
||||
void show_task_manager_window();
|
||||
void close_task_manager_window();
|
||||
|
||||
QScreen* m_current_screen;
|
||||
double m_device_pixel_ratio { 0 };
|
||||
|
||||
|
@ -150,6 +154,9 @@ private:
|
|||
|
||||
SettingsDialog* m_settings_dialog { nullptr };
|
||||
|
||||
// FIXME: This should be owned at a higher level in case we have multiple browser windows
|
||||
TaskManagerWindow* m_task_manager_window { nullptr };
|
||||
|
||||
WebView::CookieJar& m_cookie_jar;
|
||||
|
||||
WebContentOptions m_web_content_options;
|
||||
|
|
49
Ladybird/Qt/TaskManagerWindow.cpp
Normal file
49
Ladybird/Qt/TaskManagerWindow.cpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "TaskManagerWindow.h"
|
||||
#include <LibWebView/ProcessManager.h>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
TaskManagerWindow::TaskManagerWindow(QWidget* parent)
|
||||
: QWidget(parent, Qt::WindowFlags(Qt::WindowType::Window))
|
||||
, m_web_view(new WebContentView(this, {}, {}))
|
||||
{
|
||||
setLayout(new QVBoxLayout);
|
||||
layout()->addWidget(m_web_view);
|
||||
|
||||
setWindowTitle("Task Manager");
|
||||
resize(400, 300);
|
||||
|
||||
m_update_timer.setInterval(1000);
|
||||
|
||||
QObject::connect(&m_update_timer, &QTimer::timeout, [this] {
|
||||
this->update_statistics();
|
||||
});
|
||||
|
||||
update_statistics();
|
||||
}
|
||||
|
||||
void TaskManagerWindow::showEvent(QShowEvent*)
|
||||
{
|
||||
m_update_timer.start();
|
||||
}
|
||||
|
||||
void TaskManagerWindow::hideEvent(QHideEvent*)
|
||||
{
|
||||
m_update_timer.stop();
|
||||
}
|
||||
|
||||
void TaskManagerWindow::update_statistics()
|
||||
{
|
||||
|
||||
WebView::ProcessManager::the().update_all_processes();
|
||||
m_web_view->load_html(WebView::ProcessManager::the().generate_html());
|
||||
}
|
||||
|
||||
}
|
31
Ladybird/Qt/TaskManagerWindow.h
Normal file
31
Ladybird/Qt/TaskManagerWindow.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "WebContentView.h"
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
class TaskManagerWindow : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TaskManagerWindow(QWidget* parent);
|
||||
|
||||
private:
|
||||
virtual void showEvent(QShowEvent*) override;
|
||||
virtual void hideEvent(QHideEvent*) override;
|
||||
|
||||
void update_statistics();
|
||||
|
||||
WebContentView* m_web_view { nullptr };
|
||||
QTimer m_update_timer;
|
||||
};
|
||||
|
||||
}
|
|
@ -18,6 +18,7 @@ list(TRANSFORM FONTS PREPEND "${SERENITY_SOURCE_DIR}/Base/res/fonts/")
|
|||
|
||||
set(16x16_ICONS
|
||||
app-browser.png
|
||||
app-system-monitor.png
|
||||
audio-volume-high.png
|
||||
audio-volume-muted.png
|
||||
close-tab.png
|
||||
|
@ -48,6 +49,7 @@ set(16x16_ICONS
|
|||
)
|
||||
set(32x32_ICONS
|
||||
app-browser.png
|
||||
app-system-monitor.png
|
||||
filetype-folder.png
|
||||
filetype-unknown.png
|
||||
msgbox-warning.png
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/String.h>
|
||||
#include <LibCore/EventLoop.h>
|
||||
#include <LibCore/System.h>
|
||||
#include <LibWebView/ProcessManager.h>
|
||||
|
@ -114,4 +115,70 @@ void ProcessManager::update_all_processes()
|
|||
// FIXME: Actually gather stats in a platform-specific way
|
||||
}
|
||||
|
||||
String ProcessManager::generate_html()
|
||||
{
|
||||
StringBuilder builder;
|
||||
auto processes = m_processes;
|
||||
|
||||
builder.append(R"(
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
th {
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
td, th {
|
||||
padding: 4px;
|
||||
border: 1px solid #aaa;
|
||||
}
|
||||
tr:nth-child(odd) {
|
||||
background: #f7f7f7;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>PID</th>
|
||||
<th>Memory Usage</th>
|
||||
<th>CPU %</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
)"sv);
|
||||
|
||||
for (auto& process : processes) {
|
||||
builder.append("<tr>"sv);
|
||||
builder.append("<td>"sv);
|
||||
builder.append(WebView::process_name_from_type(process.type));
|
||||
builder.append("</td>"sv);
|
||||
builder.append("<td>"sv);
|
||||
builder.append(MUST(String::number(process.pid)));
|
||||
builder.append("</td>"sv);
|
||||
builder.append("<td>"sv);
|
||||
builder.append(MUST(String::formatted("{} KB", process.memory_usage_kib)));
|
||||
builder.append("</td>"sv);
|
||||
builder.append("<td>"sv);
|
||||
builder.append(MUST(String::formatted("{:.1f}", process.cpu_percent)));
|
||||
builder.append("</td>"sv);
|
||||
builder.append("</tr>"sv);
|
||||
}
|
||||
|
||||
builder.append(R"(
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
)"sv);
|
||||
|
||||
return builder.to_string_without_validation();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,6 +43,8 @@ public:
|
|||
void update_all_processes();
|
||||
Vector<ProcessInfo> processes() const { return m_processes; }
|
||||
|
||||
String generate_html();
|
||||
|
||||
private:
|
||||
ProcessManager();
|
||||
~ProcessManager();
|
||||
|
|
Loading…
Reference in a new issue