Add support for disk tab.

This commit is contained in:
Alastair Poole 2018-06-09 11:30:07 +01:00
parent f66c40bc73
commit a1bfadafaa
6 changed files with 509 additions and 22 deletions

261
src/disks.c Normal file
View File

@ -0,0 +1,261 @@
#define _DEFAULT_SOURCE
#include "disks.h"
#include <Ecore.h>
#include <Ecore_File.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/statvfs.h>
#if defined(__APPLE__) && defined(__MACH__)
# define __MacOS__
#endif
#if defined (__MacOS__) || defined(__FreeBSD__) || defined(__DragonFly__)
# include <sys/types.h>
# include <sys/sysctl.h>
# include <sys/param.h>
# include <sys/ucred.h>
# include <sys/mount.h>
#endif
#if defined(__OpenBSD__) || defined(__NetBSD__)
# include <sys/param.h>
# include <sys/sysctl.h>
# include <sys/mount.h>
#endif
char *
disk_mount_point_get(const char *path)
{
#if defined(__MacOS__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
struct statfs *mounts;
int i, count;
count = getmntinfo(&mounts, MNT_WAIT);
for (i = 0; i < count; i++)
{
if (!strcmp(path, mounts[i].f_mntfromname))
{
return strdup(mounts[i].f_mntonname);
}
}
#elif defined(__linux__)
char buf[4096];
char *start, *end;
FILE *f = fopen("/proc/mounts", "r");
while ((fgets(buf, sizeof(buf), f)) != NULL)
{
start = &buf[0];
end = strchr(start, ' ');
if (!end) continue;
*end = 0x0;
if (!strcmp(path, start))
{
start = end + 1;
if (!start) continue;
end = strchr(start, ' ');
if (!end) continue;
*end = 0x0;
fclose(f);
return strdup(start);
}
}
fclose(f);
return NULL;
#else
#endif
return NULL;
}
Eina_Bool
disk_usage_get(const char *mountpoint, unsigned long *total, unsigned long *used)
{
struct statvfs stats;
*total = *used = 0;
if (statvfs(mountpoint, &stats) < 0)
return EINA_FALSE;
*total = stats.f_frsize * stats.f_blocks;
*used = stats.f_bsize * stats.f_bavail;
return EINA_TRUE;
}
static int
_cmp_cb(const void *p1, const void *p2)
{
const char *s1, *s2;
s1 = p1; s2 = p2;
return strcmp(s1, s2);
}
Eina_List *
disks_get(void)
{
#if defined(__FreeBSD__) || defined(__DragonFly__)
struct statfs *mounts;
int i, count;
char *drives, *dev, *end;
char buf[4096];
size_t len;
if ((sysctlbyname("kern.disks", NULL, &len, NULL, 0)) == -1)
return NULL;
drives = malloc(len + 1);
if ((sysctlbyname("kern.disks", drives, &len, NULL, 0)) == -1)
{
free(drives);
return NULL;
}
Eina_List *list = NULL;
dev = drives;
while (dev)
{
end = strchr(dev, ' ');
if (!end)
break;
*end = '\0';
snprintf(buf, sizeof(buf), "/dev/%s", dev);
list = eina_list_append(list, strdup(buf));
dev = end + 1;
}
free(drives);
count = getmntinfo(&mounts, MNT_WAIT);
for (i = 0; i < count; i++)
{
list = eina_list_append(list, strdup(mounts[i].f_mntfromname));
}
list = list_sort(list, _cmp_cb);
return list;
#elif defined(__OpenBSD__) || defined(__NetBSD__)
static const int mib[] = { CTL_HW, HW_DISKNAMES };
static const unsigned int miblen = 2;
struct statfs *mounts;
char *drives, *dev, *end;
char buf[4096];
size_t len;
int i, count;
if ((sysctl(mib, miblen, NULL, &len, NULL, 0)) == -1)
return NULL;
drives = malloc(len + 1);
if ((sysctl(mib, miblen, drives, &len, NULL, 0)) == -1)
{
free(drives);
return NULL;
}
Eina_List *list = NULL;
dev = drives;
while (dev)
{
end = strchr(dev, ':');
if (!end) break;
*end = '\0';
if (dev[0] == ',')
dev++;
snprintf(buf, sizeof(buf), "/dev/%s", dev);
list = eina_list_append(list, strdup(buf));
end++;
dev = strchr(end, ',');
if (!dev) break;
}
free(drives);
count = getmntinfo(&mounts, MNT_WAIT);
for (i = 0; i < count; i++)
{
list = eina_list_append(list, strdup(mounts[i].f_mntfromname));
}
list = eina_list_sort(list, eina_list_count(list), _cmp_cb);
return list;
#elif defined(__MacOS__)
char *name;
char buf[4096];
Eina_List *devs, *list;
list = NULL;
devs = ecore_file_ls("/dev");
EINA_LIST_FREE(devs, name)
{
name = l->data;
if (!strncmp(name, "disk", 4))
{
snprintf(buf, sizeof(buf), "/dev/%s", name);
list = eina_list_append(list, strdup(buf));
}
l = l->next;
}
if (devs)
list_free(devs);
list = eina_list_sort(list, eina_list_count(list), _cmp_cb);
return list;
#elif defined(__linux__)
char *name;
Eina_List *devs, *list;
char buf[4096];
list = NULL;
devs = ecore_file_ls("/dev/disk/by-path");
EINA_LIST_FREE(devs, name)
{
snprintf(buf, sizeof(buf), "/dev/disk/by-path/%s", name);
char *real = realpath(buf, NULL);
if (real)
{
list = eina_list_append(list, real);
}
free(name);
}
if (devs)
eina_list_free(devs);
list = eina_list_sort(list, eina_list_count(list), _cmp_cb);
return list;
#else
return NULL;
#endif
}

17
src/disks.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef __DISKS_H__
#define __DISKS_H__
#include <Eina.h>
#include <Ecore.h>
Eina_Bool
disk_usage_get(const char *mountpoint, unsigned long *total, unsigned long *used);
char *
disk_mount_point_get(const char *path);
Eina_List *
disks_get(void);
#endif

View File

@ -25,7 +25,7 @@ _win_add(void)
elm_icon_standard_set(icon, "evisum");
elm_win_icon_object_set(win, icon);
evas_object_resize(win, 768 * elm_config_scale_get(), 420 * elm_config_scale_get());
evas_object_resize(win, 768 * elm_config_scale_get(), 620 * elm_config_scale_get());
evas_object_smart_callback_add(win, "delete,request", _win_del_cb, NULL);
elm_win_title_set(win, "System Information");

View File

@ -1,6 +1,6 @@
TARGET = ../evisum
OBJECTS = system.o process.o ui.o main.o
OBJECTS = system.o disks.o process.o ui.o main.o
default: $(TARGET)
@ -13,6 +13,9 @@ main.o: main.c
system.o: system.c
$(CC) -c $(CFLAGS) system.c -o $@
disks.o: disks.c
$(CC) -c $(CFLAGS) $(shell pkg-config --cflags $(PKGS)) disks.c -o $@
process.o: process.c
$(CC) -c $(CFLAGS) $(shell pkg-config --cflags $(PKGS)) process.c -o $@

239
src/ui.c
View File

@ -1,5 +1,6 @@
#include "system.h"
#include "process.h"
#include "disks.h"
#include "ui.h"
#include <stdio.h>
#include <sys/types.h>
@ -14,6 +15,8 @@ static Eina_Lock _lock;
static long _memory_total = 0;
static long _memory_used = 0;
static void _disk_view_update(Ui *ui);
static void
_system_stats(void *data, Ecore_Thread *thread)
{
@ -58,6 +61,8 @@ _system_stats_feedback_cb(void *data, Ecore_Thread *thread, void *msg)
elm_progressbar_value_set(ui->progress_cpu, (double)sys->cpu_usage / 100);
elm_progressbar_value_set(ui->progress_mem, (double)((sys->mem_total / 100.0) * sys->mem_used) / 1000000);
_disk_view_update(ui);
out:
free(sys);
}
@ -785,18 +790,106 @@ _entry_pid_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info
ui->panel_visible = EINA_TRUE;
}
static unsigned long _disk_used = 0, _disk_total = 0;
static char *
_progress_disk_format_cb(double val)
{
char buf[1024];
snprintf(buf, sizeof(buf), "%.2fM of %.1f M", (double) (_disk_used), (double) (_disk_total));
return strdup(buf);
}
static void
_ui_main_view_add(Evas_Object *parent, Ui *ui)
_progress_disk_format_free_cb(char *str)
{
if (str)
free(str);
}
static void
_ui_disk_add(Ui *ui, const char *mountpoint, unsigned long total, unsigned long used)
{
Evas_Object *table, *hbox, *progress, *label;
table = elm_table_add(ui->disk_activity);
evas_object_size_hint_weight_set(table, 0, 0);
evas_object_size_hint_align_set(table, EVAS_HINT_FILL, 0);
evas_object_show(table);
label = elm_label_add(table);
evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(label, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_object_text_set(label, mountpoint);
evas_object_show(label);
elm_table_pack(table, label, 0, 0, 1, 1);
progress = elm_progressbar_add(table);
evas_object_size_hint_align_set(progress, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_size_hint_weight_set(progress, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_progressbar_span_size_set(progress, 1.0);
elm_progressbar_unit_format_set(progress, "");
elm_progressbar_unit_format_function_set(progress, _progress_disk_format_cb, _progress_disk_format_free_cb);
_disk_used = used;
_disk_total = total;
double ratio = total / 100.0;
uint64_t have = total - used;
double value = used / ratio;
elm_progressbar_value_set(progress, value / 100.0);
evas_object_show(progress);
elm_table_pack(table, progress, 0, 1, 1, 1);
elm_box_pack_end(ui->disk_activity, table);
}
static void
_disk_view_update(Ui *ui)
{
Eina_List *disks;
char *path;
unsigned long total, used;
elm_box_clear(ui->disk_activity);
disks = disks_get();
EINA_LIST_FREE(disks, path)
{
char *mountpoint = disk_mount_point_get(path);
if (mountpoint)
{
if (disk_usage_get(mountpoint, &total, &used))
{
total >>= 20; used >>= 20;
_ui_disk_add(ui, mountpoint, total, used);
}
free(mountpoint);
}
free(path);
}
if (disks)
free(disks);
}
static void
_ui_system_view_add(Evas_Object *parent, Ui *ui)
{
Evas_Object *box, *hbox, *frame, *table;
Evas_Object *progress, *button, *entry;
Evas_Object *scroller;
box = elm_box_add(parent);
ui->system_activity = box = elm_box_add(parent);
evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(box);
elm_object_content_set(parent, box);
elm_table_pack(ui->content, ui->system_activity, 0, 1, 1, 1);
hbox = elm_box_add(box);
evas_object_size_hint_weight_set(hbox, EVAS_HINT_EXPAND, 0);
@ -1045,20 +1138,6 @@ _ui_main_view_add(Evas_Object *parent, Ui *ui)
evas_object_show(hbox);
elm_box_pack_end(box, hbox);
box = elm_box_add(parent);
evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(hbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_box_horizontal_set(box, EINA_TRUE);
elm_box_pack_end(hbox, box);
button = elm_button_add(parent);
evas_object_size_hint_weight_set(button, 0.1, 0);
evas_object_size_hint_align_set(button, EVAS_HINT_FILL, 0);
elm_object_text_set(button, "Close");
elm_box_pack_end(hbox, button);
evas_object_show(button);
evas_object_smart_callback_add(button, "clicked", _btn_quit_clicked_cb, ui);
evas_object_smart_callback_add(ui->btn_pid, "clicked", _btn_pid_clicked_cb, ui);
evas_object_smart_callback_add(ui->btn_uid, "clicked", _btn_uid_clicked_cb, ui);
evas_object_smart_callback_add(ui->btn_size, "clicked", _btn_size_clicked_cb, ui);
@ -1080,7 +1159,7 @@ _ui_process_panel_add(Evas_Object *parent, Ui *ui)
evas_object_size_hint_align_set(panel, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_panel_orient_set(panel, ELM_PANEL_ORIENT_BOTTOM);
elm_panel_toggle(panel);
elm_object_content_set(parent, panel);
elm_object_content_set(ui->win, panel);
evas_object_show(panel);
evas_object_smart_callback_add(ui->panel, "scroll", _panel_scrolled_cb, ui);
@ -1366,6 +1445,121 @@ _ui_process_panel_add(Evas_Object *parent, Ui *ui)
evas_object_smart_callback_add(button, "clicked", _btn_kill_clicked_cb, ui);
}
static void
_ui_disk_view_add(Evas_Object *parent, Ui *ui)
{
Evas_Object *box, *hbox, *frame, *scroller;
ui->disk_view = box = elm_box_add(parent);
evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_table_pack(ui->content, ui->disk_view, 0, 1, 1, 1);
evas_object_hide(box);
ui->disk_activity = hbox = elm_box_add(box);
evas_object_size_hint_weight_set(hbox, EVAS_HINT_EXPAND, 0);
evas_object_size_hint_align_set(hbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
evas_object_show(hbox);
frame = elm_frame_add(box);
evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_object_text_set(frame, "Disk usage");
evas_object_show(frame);
scroller = elm_scroller_add(parent);
evas_object_size_hint_weight_set(scroller, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(scroller, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_scroller_policy_set(scroller, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_ON);
evas_object_show(scroller);
elm_object_content_set(scroller, hbox);
elm_object_content_set(frame, scroller);
elm_box_pack_end(box, frame);
}
static void
_tab_system_activity_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Ui *ui;
ui = data;
evas_object_show(ui->system_activity);
evas_object_hide(ui->disk_view);
}
static void
_tab_disk_activity_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Ui *ui;
ui = data;
evas_object_show(ui->disk_view);
evas_object_hide(ui->system_activity);
}
static Evas_Object *
_ui_tabs_add(Evas_Object *parent, Ui *ui)
{
Evas_Object *table, *hbox, *frame, *button;
ui->content = table = elm_table_add(parent);
evas_object_size_hint_weight_set(table, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(table, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_object_content_set(parent, table);
evas_object_show(table);
frame = elm_frame_add(parent);
evas_object_size_hint_weight_set(frame, EVAS_HINT_EXPAND, 0);
evas_object_size_hint_align_set(frame, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_object_text_set(frame, "Options");
evas_object_show(frame);
hbox = elm_box_add(parent);
evas_object_size_hint_weight_set(hbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(hbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_box_horizontal_set(hbox, EINA_TRUE);
evas_object_show(hbox);
button = elm_button_add(hbox);
evas_object_size_hint_weight_set(button, 1.0, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_object_text_set(button, "System Activity");
evas_object_show(button);
elm_box_pack_end(hbox, button);
evas_object_smart_callback_add(button, "clicked", _tab_system_activity_clicked_cb, ui);
button = elm_button_add(hbox);
evas_object_size_hint_weight_set(button, 1.0, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_object_text_set(button, "Disk Activity");
evas_object_show(button);
elm_box_pack_end(hbox, button);
evas_object_smart_callback_add(button, "clicked", _tab_disk_activity_clicked_cb, ui);
elm_object_content_set(frame, hbox);
elm_table_pack(ui->content, frame, 0, 0, 1, 1);
hbox = elm_box_add(parent);
evas_object_size_hint_weight_set(hbox, 0.5, 0);
evas_object_size_hint_align_set(hbox, EVAS_HINT_EXPAND, EVAS_HINT_FILL);
elm_box_horizontal_set(hbox, EINA_TRUE);
evas_object_show(hbox);
button = elm_button_add(parent);
evas_object_size_hint_weight_set(button, 0.1, 0);
evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_object_text_set(button, "Close");
elm_box_pack_end(hbox, button);
evas_object_show(button);
evas_object_smart_callback_add(button, "clicked", _btn_quit_clicked_cb, ui);
elm_table_pack(ui->content, hbox, 0, 2, 1, 1);
return table;
}
void
ui_add(Evas_Object *parent)
{
@ -1392,10 +1586,15 @@ ui_add(Evas_Object *parent)
eina_lock_new(&_lock);
_ui_main_view_add(parent, ui);
_ui_process_panel_add(parent, ui);
Evas_Object *content = _ui_tabs_add(parent, ui);
_ui_system_view_add(content, ui);
_ui_process_panel_add(content, ui);
_ui_disk_view_add(content, ui);
_disk_view_update(ui);
_process_panel_update(ui);
ecore_thread_feedback_run(_system_stats, _system_stats_feedback_cb, _thread_end_cb, _thread_error_cb, ui, EINA_FALSE);
ecore_thread_feedback_run(_system_process_list, _system_process_list_feedback_cb, _thread_end_cb, _thread_error_cb, ui, EINA_FALSE);
}

View File

@ -46,6 +46,13 @@ typedef struct Ui
Evas_Object *panel;
Evas_Object *scroller;
Evas_Object *content;
Evas_Object *disk_view;
Evas_Object *disk_activity;
Evas_Object *system_activity;
Evas_Object *progress_cpu;
Evas_Object *progress_mem;