Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions data/gresource.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@
<gresource prefix="/io/elementary/settings/system">
<file alias="OperatingSystemView.css" compressed="true">OperatingSystemView.css</file>
</gresource>

<gresource prefix="/io/elementary/settings/system/icons">
<file alias="32x32/categories/system-logs-symbolic.svg" compressed="true" preprocess="xml-stripblanks">system-logs-symbolic.svg</file>
</gresource>
</gresources>
41 changes: 41 additions & 0 deletions data/system-logs-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/Plug.vala
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public class About.Plug : Switchboard.Plug {

public override Gtk.Widget get_widget () {
if (main_grid == null) {
Gtk.IconTheme.get_for_display (Gdk.Display.get_default ()).add_resource_path ("/io/elementary/settings/system/icons");
operating_system_view = new OperatingSystemView ();

var hardware_view = new HardwareView ();
Expand Down
152 changes: 152 additions & 0 deletions src/Utils/SystemdLogModel.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* SPDX-License-Identifier: GPL-3.0-or-later
* SPDX-FileCopyrightText: 2024 elementary, Inc. (https://elementary.io)
*/

public class About.SystemdLogRow : GLib.Object {
public string origin { get; construct; }
public string message { get; construct; }

public SystemdLogRow (string origin, string message) {
Object(origin: origin, message: message);
}
}

public class About.SystemdLogModel : GLib.Object, GLib.ListModel {
private GLib.HashTable<uint, unowned About.SystemdLogRow> cached_rows;
private uint current_line = uint.MAX;
private uint num_entries = 0;
private Systemd.Journal journal;

construct {
cached_rows = new GLib.HashTable<uint, unowned About.SystemdLogRow>(GLib.direct_hash, GLib.direct_equal);
create_journal ();
load_data.begin ();
}

private void create_journal () {
int res = Systemd.Journal.open_namespace (out journal, null, LOCAL_ONLY);
if (res != 0) {
critical ("%s", strerror(-res));
return;
}

Systemd.Id128 boot_id;
res = Systemd.Id128.boot (out boot_id);
if (res != 0) {
critical ("%s", strerror(-res));
return;
}

journal.add_match ("_BOOT_ID=%s".printf(boot_id.str).data);
journal.add_conjunction ();
}

private uint load_next_entries () {
if (current_line != num_entries) {
int res = journal.seek_head ();
current_line = 0;
if (res != 0) {
critical ("%s", strerror(-res));
return 0;
}

if (num_entries > 0) {
res = journal.next_skip (num_entries);
current_line += num_entries;
if (res < 0) {
critical ("%s", strerror(-res));
return 0;
}
}
}

int res = journal.next ();
if (res < 0) {
critical ("%s", strerror(-res));
return 0;
}

current_line += res;
num_entries += res;
return res;
}

private async void load_data () {
GLib.Idle.add(() => {
uint added = 0, old_num_entries = 0;
lock (journal) {
old_num_entries = num_entries;
added = load_next_entries ();
}
if (added > 0) {
items_changed (old_num_entries, 0, added);
return Source.CONTINUE;
} else {
return Source.REMOVE;
}
}, GLib.Priority.LOW);
}

public Object? get_item (uint position) {
About.SystemdLogRow? row = null;
lock (journal) {
row = cached_rows.get (position);
if (row != null) {
return row;
}

int res = journal.seek_head ();
current_line = 0;
if (res != 0) {
critical ("%s", strerror(-res));
return null;
}

res = journal.next ();
if (res < 0) {
critical ("%s", strerror(-res));
return null;
}

res = journal.next_skip (position);
current_line += position;
if (res < 0) {
critical ("%s", strerror(-res));
return null;
}

unowned uint8[] data;
unowned uint8[] comm_data;
res = journal.get_data ("MESSAGE", out data);
if (res != 0) {
critical ("%s", strerror(-res));
return null;
}

res = journal.get_data ("_COMM", out comm_data);
if (res != 0) {
//critical ("%s %s", strerror(-res), (string) data);
comm_data = "_COMM=kernel".data;
}

row = new About.SystemdLogRow (((string)comm_data).offset ("_COMM=".length), ((string)data).offset("MESSAGE=".length));
cached_rows.set (position, row);
row.weak_ref((obj) => {
cached_rows.foreach_remove ((key, val) => {
return val == obj;
});
});
}

return (owned)row;
}

public Type get_item_type () {
return typeof(About.SystemdLogRow);
}

public uint get_n_items () {
return num_entries;
}
}
21 changes: 18 additions & 3 deletions src/Views/OperatingSystemView.vala
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,13 @@ public class About.OperatingSystemView : Gtk.Box {
hexpand = true
};

var log_button = new Gtk.Button.from_icon_name ("system-logs-symbolic") {
tooltip_text = _("System logs"),
halign = END,
valign = BASELINE_CENTER,
hexpand = false
};

var button_grid = new Gtk.Box (HORIZONTAL, 6);
button_grid.append (settings_restore_button);
button_grid.append (bug_button);
Expand All @@ -312,10 +319,11 @@ public class About.OperatingSystemView : Gtk.Box {
};
software_grid.attach (logo_overlay, 0, 0, 1, 4);
software_grid.attach (title, 1, 0);
software_grid.attach (log_button, 2, 0);

software_grid.attach (kernel_version_label, 1, 2);
software_grid.attach (updates_list, 1, 3);
software_grid.attach (links_list, 1, 4);
software_grid.attach (kernel_version_label, 1, 2, 2);
software_grid.attach (updates_list, 1, 3, 2);
software_grid.attach (links_list, 1, 4, 2);

var clamp = new Adw.Clamp () {
child = software_grid
Expand Down Expand Up @@ -353,6 +361,13 @@ public class About.OperatingSystemView : Gtk.Box {
}
});

log_button.clicked.connect (() => {
var logs_dialog = new LogsDialog () {
transient_for = (Gtk.Window) get_root ()
};
logs_dialog.present ();
});

links_list.row_activated.connect ((row) => {
launch_uri (((LinkRow) row).uri);
});
Expand Down
68 changes: 68 additions & 0 deletions src/Widgets/LogsDialog.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* SPDX-License-Identifier: GPL-3.0-or-later
* SPDX-FileCopyrightText: 2024 elementary, Inc. (https://elementary.io)
*/

public class About.LogsDialog : Granite.Dialog {

public LogsDialog () {
}

construct {
title = _("System Logs");
modal = true;

var title_label = new Gtk.Label (
_("System Logs")
) {
halign = START
};
title_label.add_css_class (Granite.STYLE_CLASS_TITLE_LABEL);

var log_listbox = new Gtk.ListBox () {
vexpand = true,
selection_mode = NONE
};
var model = new About.SystemdLogModel ();
log_listbox.bind_model (model, (obj) => {
unowned var row = (About.SystemdLogRow) obj;

var origin_label = new Gtk.Label (row.origin);
origin_label.add_css_class (Granite.STYLE_CLASS_H4_LABEL);
var message_label = new Gtk.Label (row.message) {
wrap = true,
hexpand = true,
halign = START,
};

var box = new Gtk.Box (HORIZONTAL, 6);
box.append (origin_label);
box.append (message_label);

return box;
});

var scrolled = new Gtk.ScrolledWindow () {
child = log_listbox,
hscrollbar_policy = NEVER,
max_content_height = 400,
propagate_natural_height = true
};

var frame = new Gtk.Frame (null) {
child = scrolled
};

var box = new Gtk.Box (VERTICAL, 12);
box.append (title_label);
box.append (frame);

get_content_area ().append (box);

add_button (_("Close"), Gtk.ResponseType.CLOSE);

response.connect (() => {
close ();
});
}
}
5 changes: 4 additions & 1 deletion src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ plug_files = files(
'Interfaces/FirmwareClient.vala',
'Interfaces/LoginManager.vala',
'Utils/ARMPartDecoder.vala',
'Utils' / 'SystemdLogModel.vala',
'Views' / 'DriversView.vala',
'Views/FirmwareReleaseView.vala',
'Views/FirmwareView.vala',
'Views/HardwareView.vala',
'Views/OperatingSystemView.vala',
'Widgets/FirmwareUpdateRow.vala',
'Widgets' / 'DriverRow.vala',
'Widgets' / 'UpdateDetailsDialog.vala'
'Widgets' / 'UpdateDetailsDialog.vala',
'Widgets' / 'LogsDialog.vala',
)

switchboard_dep = dependency('switchboard-3')
Expand Down Expand Up @@ -41,6 +43,7 @@ shared_module(
dependency('gtk4'),
dependency('libadwaita-1'),
dependency('libgtop-2.0'),
dependency('libsystemd'),
dependency('packagekit-glib2'),
dependency('gudev-1.0'),
dependency('udisks2'),
Expand Down
Loading