*/
#include <locale.h>
#include <malloc.h>
+#include <string.h>
#include <glib.h>
+#include <cairo.h>
#include <gtk/gtk.h>
#include "fio.h"
+#include "graph.h"
static int gfio_server_running;
+static const char *gfio_graph_font;
static void gfio_update_thread_status(char *status_message, double perc);
+static void view_log(GtkWidget *w, gpointer data);
#define ARRAYSIZE(x) (sizeof((x)) / (sizeof((x)[0])))
GtkWidget *buttonbox;
GtkWidget *button[ARRAYSIZE(buttonspeclist)];
GtkWidget *scrolled_window;
- GtkWidget *textview;
+#define DRAWING_AREA_XDIM 1000
+#define DRAWING_AREA_YDIM 400
+ GtkWidget *drawing_area;
+ int drawing_area_xdim;
+ int drawing_area_ydim;
GtkWidget *error_info_bar;
GtkWidget *error_label;
GtkWidget *results_notebook;
pthread_t t;
pthread_t server_t;
+ struct graph *iops_graph;
+ struct graph *bandwidth_graph;
struct fio_client *client;
int nr_job_files;
char **job_files;
struct gui *ui;
GtkWidget *results_widget;
GtkWidget *disk_util_frame;
+ GtkWidget *err_entry;
+ unsigned int job_added;
+ struct thread_options o;
};
+static void setup_iops_graph(struct gui *ui)
+{
+ if (ui->iops_graph)
+ graph_free(ui->iops_graph);
+ ui->iops_graph = graph_new(DRAWING_AREA_XDIM / 2.0,
+ DRAWING_AREA_YDIM, gfio_graph_font);
+ graph_title(ui->iops_graph, "IOPS");
+ graph_x_title(ui->iops_graph, "Time (secs)");
+ graph_y_title(ui->iops_graph, "IOs / sec");
+ graph_add_label(ui->iops_graph, "Read IOPS");
+ graph_add_label(ui->iops_graph, "Write IOPS");
+ graph_set_color(ui->iops_graph, "Read IOPS", 0.13, 0.54, 0.13);
+ graph_set_color(ui->iops_graph, "Write IOPS", 1.0, 0.0, 0.0);
+ line_graph_set_data_count_limit(ui->iops_graph, 100);
+}
+
+static void setup_bandwidth_graph(struct gui *ui)
+{
+ if (ui->bandwidth_graph)
+ graph_free(ui->bandwidth_graph);
+ ui->bandwidth_graph = graph_new(DRAWING_AREA_XDIM / 2.0,
+ DRAWING_AREA_YDIM, gfio_graph_font);
+ graph_title(ui->bandwidth_graph, "Bandwidth");
+ graph_x_title(ui->bandwidth_graph, "Time (secs)");
+ graph_y_title(ui->bandwidth_graph, "Kbytes / sec");
+ graph_add_label(ui->bandwidth_graph, "Read Bandwidth");
+ graph_add_label(ui->bandwidth_graph, "Write Bandwidth");
+ graph_set_color(ui->bandwidth_graph, "Read Bandwidth", 0.13, 0.54, 0.13);
+ graph_set_color(ui->bandwidth_graph, "Write Bandwidth", 1.0, 0.0, 0.0);
+ line_graph_set_data_count_limit(ui->bandwidth_graph, 100);
+}
+
static void clear_ui_info(struct gui *ui)
{
gtk_label_set_text(GTK_LABEL(ui->probe.hostname), "");
win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(win), "Results");
+ gtk_window_set_default_size(GTK_WINDOW(win), 1024, 768);
g_signal_connect(win, "delete-event", G_CALLBACK(results_window_delete), ui);
g_signal_connect(win, "destroy", G_CALLBACK(results_window_delete), ui);
static void gfio_display_ts(struct fio_client *client, struct thread_stat *ts,
struct group_run_stats *rs)
{
- GtkWidget *res_win, *box, *vbox, *entry;
+ GtkWidget *res_win, *box, *vbox, *entry, *scroll;
struct gfio_client *gc = client->client_data;
gdk_threads_enter();
res_win = get_results_window(gc->ui);
+ scroll = gtk_scrolled_window_new(NULL, NULL);
+ gtk_container_set_border_width(GTK_CONTAINER(scroll), 5);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
vbox = gtk_vbox_new(FALSE, 3);
- box = gtk_hbox_new(TRUE, 3);
- gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 5);
+ box = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), box, TRUE, FALSE, 5);
- gtk_notebook_append_page(GTK_NOTEBOOK(res_win), vbox, gtk_label_new(ts->name));
+ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), vbox);
+
+ gtk_notebook_append_page(GTK_NOTEBOOK(res_win), scroll, gtk_label_new(ts->name));
gc->results_widget = vbox;
entry_set_int_value(entry, ts->groupid);
entry = new_info_entry_in_frame(box, "Jobs");
entry_set_int_value(entry, ts->members);
- entry = new_info_entry_in_frame(box, "Error");
+ gc->err_entry = entry = new_info_entry_in_frame(box, "Error");
entry_set_int_value(entry, ts->error);
entry = new_info_entry_in_frame(box, "PID");
entry_set_int_value(entry, ts->pid);
gtk_list_store_set(gc->ui->log_model, &iter, 2, p->level, -1);
gtk_list_store_set(gc->ui->log_model, &iter, 3, p->buf, -1);
+ if (p->level == FIO_LOG_ERR)
+ view_log(NULL, (gpointer) gc->ui);
+
gdk_threads_leave();
}
struct cmd_du_pdu *p = (struct cmd_du_pdu *) cmd->payload;
struct gfio_client *gc = client->client_data;
GtkWidget *box, *frame, *entry, *vbox;
+ double util;
+ char tmp[16];
gdk_threads_enter();
- if (!gc->results_widget) {
- printf("no results!\n");
+ if (!gc->results_widget)
goto out;
- }
if (!gc->disk_util_frame) {
gc->disk_util_frame = gtk_frame_new("Disk utilization");
entry = new_info_entry_in_frame(vbox, "Time in queue");
entry_set_int_value(entry, p->dus.time_in_queue);
+ util = 0.0;
+ if (p->dus.msec)
+ util = (double) 100 * p->dus.io_ticks / (double) p->dus.msec;
+ if (util > 100.0)
+ util = 100.0;
+
+ sprintf(tmp, "%3.2f%%", util);
+ entry = new_info_entry_in_frame(vbox, "Disk utilization");
+ gtk_entry_set_text(GTK_ENTRY(entry), tmp);
+
gtk_widget_show_all(gc->results_widget);
out:
gdk_threads_leave();
gdk_threads_leave();
}
+static gint on_config_drawing_area(GtkWidget *w, GdkEventConfigure *event)
+{
+ ui.drawing_area_xdim = w->allocation.width;
+ ui.drawing_area_ydim = w->allocation.height;
+ return TRUE;
+}
+
+static int on_expose_drawing_area(GtkWidget *w, GdkEvent *event, gpointer p)
+{
+ struct gui *ui = (struct gui *) p;
+ cairo_t *cr;
+
+ graph_set_size(ui->iops_graph, ui->drawing_area_xdim / 2.0,
+ ui->drawing_area_ydim);
+ graph_set_size(ui->bandwidth_graph, ui->drawing_area_xdim / 2.0,
+ ui->drawing_area_ydim);
+ cr = gdk_cairo_create(w->window);
+
+ cairo_set_source_rgb(cr, 0, 0, 0);
+
+ cairo_save(cr);
+ cairo_translate(cr, 0, 0);
+ line_graph_draw(ui->bandwidth_graph, cr);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+
+ cairo_save(cr);
+ cairo_translate(cr, ui->drawing_area_xdim / 2.0, 0);
+ line_graph_draw(ui->iops_graph, cr);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ cairo_destroy(cr);
+
+ return FALSE;
+}
+
static void gfio_update_eta(struct jobs_eta *je)
{
static int eta_good;
gtk_entry_set_text(GTK_ENTRY(ui.eta.write_bw), rate_str[1]);
gtk_entry_set_text(GTK_ENTRY(ui.eta.write_iops), iops_str[1]);
+ graph_add_xy_data(ui.iops_graph, "Read IOPS", je->elapsed_sec, je->iops[0]);
+ graph_add_xy_data(ui.iops_graph, "Write IOPS", je->elapsed_sec, je->iops[1]);
+ graph_add_xy_data(ui.bandwidth_graph, "Read Bandwidth", je->elapsed_sec, je->rate[0]);
+ graph_add_xy_data(ui.bandwidth_graph, "Write Bandwidth", je->elapsed_sec, je->rate[1]);
+
free(rate_str[0]);
free(rate_str[1]);
free(iops_str[0]);
{
struct cmd_add_job_pdu *p = (struct cmd_add_job_pdu *) cmd->payload;
struct gfio_client *gc = client->client_data;
+ struct thread_options *o = &gc->o;
struct gui *ui = gc->ui;
char tmp[8];
- int i;
-
- p->iodepth = le32_to_cpu(p->iodepth);
- p->rw = le32_to_cpu(p->rw);
-
- for (i = 0; i < 2; i++) {
- p->min_bs[i] = le32_to_cpu(p->min_bs[i]);
- p->max_bs[i] = le32_to_cpu(p->max_bs[i]);
- }
- p->numjobs = le32_to_cpu(p->numjobs);
- p->group_reporting = le32_to_cpu(p->group_reporting);
+ convert_thread_options_to_cpu(o, &p->top);
gdk_threads_enter();
- gtk_entry_set_text(GTK_ENTRY(ui->eta.name), (gchar *) p->jobname);
- gtk_entry_set_text(GTK_ENTRY(ui->eta.iotype), ddir_str(p->rw));
- gtk_entry_set_text(GTK_ENTRY(ui->eta.ioengine), (gchar *) p->ioengine);
+ gtk_entry_set_text(GTK_ENTRY(ui->eta.name), (gchar *) o->name);
+ gtk_entry_set_text(GTK_ENTRY(ui->eta.iotype), ddir_str(o->td_ddir));
+ gtk_entry_set_text(GTK_ENTRY(ui->eta.ioengine), (gchar *) o->ioengine);
- sprintf(tmp, "%u", p->iodepth);
+ sprintf(tmp, "%u", o->iodepth);
gtk_entry_set_text(GTK_ENTRY(ui->eta.iodepth), tmp);
+ gc->job_added++;
+
gdk_threads_leave();
}
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
- content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ /* gtk_dialog_get_content_area() is 2.14 and newer */
+ content = GTK_DIALOG(dialog)->vbox;
+
label = gtk_label_new((const gchar *) buf);
gtk_container_add(GTK_CONTAINER(content), label);
gtk_widget_show_all(dialog);
gdk_threads_leave();
}
+static void gfio_client_stop(struct fio_client *client, struct fio_net_cmd *cmd)
+{
+ struct gfio_client *gc = client->client_data;
+
+ gdk_threads_enter();
+
+ gfio_set_connected(gc->ui, 0);
+
+ if (gc->err_entry)
+ entry_set_int_value(gc->err_entry, client->error);
+
+ gdk_threads_leave();
+}
+
struct client_ops gfio_client_ops = {
.text_op = gfio_text_op,
.disk_util = gfio_disk_util_op,
.quit = gfio_quit_op,
.add_job = gfio_add_job_op,
.timed_out = gfio_client_timed_out,
+ .stop = gfio_client_stop,
.stay_connected = 1,
};
if (!gfio_server_running) {
gfio_server_running = 1;
pthread_create(&ui->server_t, NULL, server_thread, NULL);
+ pthread_detach(ui->server_t);
}
}
if (!ui->nr_job_files)
file_open(widget, data);
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No jobs running");
+ gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ui->thread_status_pb), 0.0);
if (!fio_clients_connect()) {
pthread_create(&ui->t, NULL, job_thread, NULL);
gtk_widget_set_sensitive(ui->button[CONNECT_BUTTON], 0);
}
}
+struct connection_widgets
+{
+ GtkWidget *hentry;
+ GtkWidget *combo;
+ GtkWidget *button;
+};
+
+static void hostname_cb(GtkEntry *entry, gpointer data)
+{
+ struct connection_widgets *cw = data;
+ int uses_net = 0, is_localhost = 0;
+ const gchar *text;
+ gchar *ctext;
+
+ /*
+ * Check whether to display the 'auto start backend' box
+ * or not. Show it if we are a localhost and using network,
+ * or using a socket.
+ */
+ ctext = gtk_combo_box_get_active_text(GTK_COMBO_BOX(cw->combo));
+ if (!ctext || !strncmp(ctext, "IPv4", 4) || !strncmp(ctext, "IPv6", 4))
+ uses_net = 1;
+ g_free(ctext);
+
+ if (uses_net) {
+ text = gtk_entry_get_text(GTK_ENTRY(cw->hentry));
+ if (!strcmp(text, "127.0.0.1") || !strcmp(text, "localhost") ||
+ !strcmp(text, "::1") || !strcmp(text, "ip6-localhost") ||
+ !strcmp(text, "ip6-loopback"))
+ is_localhost = 1;
+ }
+
+ if (!uses_net || is_localhost) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw->button), 1);
+ gtk_widget_set_sensitive(cw->button, 1);
+ } else {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw->button), 0);
+ gtk_widget_set_sensitive(cw->button, 0);
+ }
+}
+
static int get_connection_details(char **host, int *port, int *type,
int *server_start)
{
- GtkWidget *dialog, *box, *vbox, *hentry, *hbox, *frame, *pentry, *combo;
- GtkWidget *button;
+ GtkWidget *dialog, *box, *vbox, *hbox, *frame, *pentry;
+ struct connection_widgets cw;
char *typeentry;
dialog = gtk_dialog_new_with_buttons("Connection details",
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
frame = gtk_frame_new("Hostname / socket name");
- vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ /* gtk_dialog_get_content_area() is 2.14 and newer */
+ vbox = GTK_DIALOG(dialog)->vbox;
gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
box = gtk_vbox_new(FALSE, 6);
hbox = gtk_hbox_new(TRUE, 10);
gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
- hentry = gtk_entry_new();
- gtk_entry_set_text(GTK_ENTRY(hentry), "localhost");
- gtk_box_pack_start(GTK_BOX(hbox), hentry, TRUE, TRUE, 0);
+ cw.hentry = gtk_entry_new();
+ gtk_entry_set_text(GTK_ENTRY(cw.hentry), "localhost");
+ gtk_box_pack_start(GTK_BOX(hbox), cw.hentry, TRUE, TRUE, 0);
frame = gtk_frame_new("Port");
gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
hbox = gtk_hbox_new(TRUE, 4);
gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
- combo = gtk_combo_box_new_text();
- gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "IPv4");
- gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "IPv6");
- gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "local socket");
- gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
+ cw.combo = gtk_combo_box_new_text();
+ gtk_combo_box_append_text(GTK_COMBO_BOX(cw.combo), "IPv4");
+ gtk_combo_box_append_text(GTK_COMBO_BOX(cw.combo), "IPv6");
+ gtk_combo_box_append_text(GTK_COMBO_BOX(cw.combo), "local socket");
+ gtk_combo_box_set_active(GTK_COMBO_BOX(cw.combo), 0);
- gtk_container_add(GTK_CONTAINER(hbox), combo);
+ gtk_container_add(GTK_CONTAINER(hbox), cw.combo);
frame = gtk_frame_new("Options");
gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
hbox = gtk_hbox_new(TRUE, 4);
gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
- button = gtk_check_button_new_with_label("Auto-spawn fio backend");
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), 1);
- gtk_widget_set_tooltip_text(button, "When running fio locally, it is necessary to have the backend running on the same system. If this is checked, gfio will start the backend automatically for you if it isn't already running.");
- gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 6);
+ cw.button = gtk_check_button_new_with_label("Auto-spawn fio backend");
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw.button), 1);
+ gtk_widget_set_tooltip_text(cw.button, "When running fio locally, it is necessary to have the backend running on the same system. If this is checked, gfio will start the backend automatically for you if it isn't already running.");
+ gtk_box_pack_start(GTK_BOX(hbox), cw.button, FALSE, FALSE, 6);
+
+ /*
+ * Connect edit signal, so we can show/not-show the auto start button
+ */
+ g_signal_connect(GTK_OBJECT(cw.hentry), "changed", G_CALLBACK(hostname_cb), &cw);
+ g_signal_connect(GTK_OBJECT(cw.combo), "changed", G_CALLBACK(hostname_cb), &cw);
gtk_widget_show_all(dialog);
return 1;
}
- *host = strdup(gtk_entry_get_text(GTK_ENTRY(hentry)));
+ *host = strdup(gtk_entry_get_text(GTK_ENTRY(cw.hentry)));
*port = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(pentry));
- typeentry = gtk_combo_box_get_active_text(GTK_COMBO_BOX(combo));
+ typeentry = gtk_combo_box_get_active_text(GTK_COMBO_BOX(cw.combo));
if (!typeentry || !strncmp(typeentry, "IPv4", 4))
*type = Fio_client_ipv4;
else if (!strncmp(typeentry, "IPv6", 4))
*type = Fio_client_socket;
g_free(typeentry);
- *server_start = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
+ *server_start = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cw.button));
gtk_widget_destroy(dialog);
return 0;
filter = gtk_file_filter_new();
gtk_file_filter_add_pattern(filter, "*.fio");
gtk_file_filter_add_pattern(filter, "*.job");
+ gtk_file_filter_add_pattern(filter, "*.ini");
gtk_file_filter_add_mime_type(filter, "text/fio");
gtk_file_filter_set_name(filter, "Fio job file");
gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
static void preferences(GtkWidget *w, gpointer data)
{
- GtkWidget *dialog, *frame, *box, **buttons;
+ GtkWidget *dialog, *frame, *box, **buttons, *vbox, *font;
int i;
dialog = gtk_dialog_new_with_buttons("Preferences",
frame = gtk_frame_new("Debug logging");
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5);
+
+ vbox = gtk_vbox_new(FALSE, 6);
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+
box = gtk_hbox_new(FALSE, 6);
- gtk_container_add(GTK_CONTAINER(frame), box);
+ gtk_container_add(GTK_CONTAINER(vbox), box);
buttons = malloc(sizeof(GtkWidget *) * FD_DEBUG_MAX);
for (i = 0; i < FD_DEBUG_MAX; i++) {
+ if (i == 7) {
+ box = gtk_hbox_new(FALSE, 6);
+ gtk_container_add(GTK_CONTAINER(vbox), box);
+ }
+
+
buttons[i] = gtk_check_button_new_with_label(debug_levels[i].name);
gtk_widget_set_tooltip_text(buttons[i], debug_levels[i].help);
gtk_box_pack_start(GTK_BOX(box), buttons[i], FALSE, FALSE, 6);
}
+ frame = gtk_frame_new("Graph font");
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5);
+ vbox = gtk_vbox_new(FALSE, 6);
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+
+ font = gtk_font_button_new();
+ gtk_box_pack_start(GTK_BOX(vbox), font, FALSE, FALSE, 5);
+
gtk_widget_show_all(dialog);
if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
fio_debug |= (1UL << i);
}
+ gfio_graph_font = strdup(gtk_font_button_get_font_name(GTK_FONT_BUTTON(font)));
gtk_widget_destroy(dialog);
}
static void about_dialog(GtkWidget *w, gpointer data)
{
+ const char *authors[] = {
+ "Jens Axboe <axboe@kernel.dk>",
+ "Stephen Carmeron <stephenmcameron@gmail.com>",
+ NULL
+ };
+ const char *license[] = {
+ "Fio is free software; you can redistribute it and/or modify "
+ "it under the terms of the GNU General Public License as published by "
+ "the Free Software Foundation; either version 2 of the License, or "
+ "(at your option) any later version.\n",
+ "Fio is distributed in the hope that it will be useful, "
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of "
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the "
+ "GNU General Public License for more details.\n",
+ "You should have received a copy of the GNU General Public License "
+ "along with Fio; if not, write to the Free Software Foundation, Inc., "
+ "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n"
+ };
+ char *license_trans;
+
+ license_trans = g_strconcat(license[0], "\n", license[1], "\n",
+ license[2], "\n", NULL);
+
gtk_show_about_dialog(NULL,
"program-name", "gfio",
"comments", "Gtk2 UI for fio",
- "license", "GPLv2",
+ "license", license_trans,
+ "website", "http://git.kernel.dk/?p=fio.git;a=summary",
+ "authors", authors,
"version", fio_version_string,
- "copyright", "Jens Axboe <axboe@kernel.dk> 2012",
+ "copyright", "© 2012 Jens Axboe <axboe@kernel.dk>",
"logo-icon-name", "fio",
/* Must be last: */
- NULL, NULL,
+ "wrap-license", TRUE,
NULL);
+
+ g_free (license_trans);
}
static GtkActionEntry menu_items[] = {
GtkSettings *settings;
GtkUIManager *uimanager;
GtkWidget *menu, *probe, *probe_frame, *probe_box;
+ GdkColor white;
memset(ui, 0, sizeof(*ui));
ui->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(ui->window), "fio");
- gtk_window_set_default_size(GTK_WINDOW(ui->window), 700, 500);
+ gtk_window_set_default_size(GTK_WINDOW(ui->window), 700, 700);
g_signal_connect(ui->window, "delete-event", G_CALLBACK(quit_clicked), NULL);
g_signal_connect(ui->window, "destroy", G_CALLBACK(quit_clicked), NULL);
#endif
/*
- * Add a text box for text op messages
+ * Set up a drawing area and IOPS and bandwidth graphs
*/
- ui->textview = gtk_text_view_new();
- ui->text = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ui->textview));
- gtk_text_buffer_set_text(ui->text, "", -1);
- gtk_text_view_set_editable(GTK_TEXT_VIEW(ui->textview), FALSE);
- gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(ui->textview), FALSE);
+ gdk_color_parse("white", &white);
+ ui->drawing_area = gtk_drawing_area_new();
+ ui->drawing_area_xdim = DRAWING_AREA_XDIM;
+ ui->drawing_area_ydim = DRAWING_AREA_YDIM;
+ gtk_widget_set_size_request(GTK_WIDGET(ui->drawing_area),
+ ui->drawing_area_xdim, ui->drawing_area_ydim);
+ gtk_widget_modify_bg(ui->drawing_area, GTK_STATE_NORMAL, &white);
+ g_signal_connect(G_OBJECT(ui->drawing_area), "expose_event",
+ G_CALLBACK (on_expose_drawing_area), ui);
+ g_signal_connect(G_OBJECT(ui->drawing_area), "configure_event",
+ G_CALLBACK (on_config_drawing_area), ui);
ui->scrolled_window = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ui->scrolled_window),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_container_add(GTK_CONTAINER(ui->scrolled_window), ui->textview);
+ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(ui->scrolled_window),
+ ui->drawing_area);
gtk_box_pack_start(GTK_BOX(ui->vbox), ui->scrolled_window,
TRUE, TRUE, 0);
+ setup_iops_graph(ui);
+ setup_bandwidth_graph(ui);
+
/*
* Set up alignments for widgets at the bottom of ui,
* align bottom left, expand horizontally but not vertically