1ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron/*
2ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron * gfio - gui front end for fio - the flexible io tester
3ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron *
43c3ed070502bbfec387ded2c43d5e4559ca24a63Jens Axboe * Copyright (C) 2012 Stephen M. Cameron <stephenmcameron@gmail.com>
5c0187f3b2f62ff914d7869403213bdf4ec0b3aa7Jens Axboe * Copyright (C) 2012 Jens Axboe <axboe@kernel.dk>
6ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron *
7ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron * The license below covers all files distributed with fio unless otherwise
8ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron * noted in the file itself.
9ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron *
10ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron *  This program is free software; you can redistribute it and/or modify
11ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron *  it under the terms of the GNU General Public License version 2 as
12ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron *  published by the Free Software Foundation.
13ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron *
14ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron *  This program is distributed in the hope that it will be useful,
15ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron *  GNU General Public License for more details.
18ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron *
19ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron *  You should have received a copy of the GNU General Public License
20ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron *  along with this program; if not, write to the Free Software
21ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron *
23ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron */
248232e2855c87697a95d00d920d1fd11b30d0fcaaStephen M. Cameron#include <locale.h>
2560f6b33079c8ffbd09f448060f58b82ba920b620Stephen M. Cameron#include <malloc.h>
266b79c80c14766df7b0507c4ec679507a315ad61aJens Axboe#include <string.h>
278232e2855c87697a95d00d920d1fd11b30d0fcaaStephen M. Cameron
285b7573ab40a30b389602d4b0ec3805957b483a19Stephen M. Cameron#include <glib.h>
292fd3bb0ecbe17e8168a480cbdb8318b69bf51087Jens Axboe#include <cairo.h>
30ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron#include <gtk/gtk.h>
31ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron
328232e2855c87697a95d00d920d1fd11b30d0fcaaStephen M. Cameron#include "fio.h"
3353e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe#include "gfio.h"
3453e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe#include "ghelpers.h"
359af4a24408ea7d4cea084a4fe214b81145cc36acJens Axboe#include "goptions.h"
3641666588eed4ed830b1fabd0458eb2b0a93f0147Jens Axboe#include "gerror.h"
371252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe#include "gclient.h"
382fd3bb0ecbe17e8168a480cbdb8318b69bf51087Jens Axboe#include "graph.h"
398232e2855c87697a95d00d920d1fd11b30d0fcaaStephen M. Cameron
4063a130b7f037b55b56de05921803254a7b9ed9bbJens Axboestatic int gfio_server_running;
418577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboestatic unsigned int gfio_graph_limit = 100;
4263a130b7f037b55b56de05921803254a7b9ed9bbJens Axboe
431252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens AxboeGdkColor gfio_color_white;
442a95f716d8808f45cd5806eac0baad96b39b0016Jens AxboeGdkColor gfio_color_lightyellow;
45a1e7972d96ce1482aa43c2fcafd81d6c7f3c44d2Jens Axboeconst char *gfio_graph_font = GRAPH_DEFAULT_FONT;
463e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboe
47f3074008948b51ec380b4f06791ceec89a40d8a6Stephen M. Camerontypedef void (*clickfunction)(GtkWidget *widget, gpointer data);
48f3074008948b51ec380b4f06791ceec89a40d8a6Stephen M. Cameron
493e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboestatic void connect_clicked(GtkWidget *widget, gpointer data);
50f3074008948b51ec380b4f06791ceec89a40d8a6Stephen M. Cameronstatic void start_job_clicked(GtkWidget *widget, gpointer data);
51b9d2f30a214ebd274340f888739be250838d63c2Jens Axboestatic void send_clicked(GtkWidget *widget, gpointer data);
52f3074008948b51ec380b4f06791ceec89a40d8a6Stephen M. Cameron
53f3074008948b51ec380b4f06791ceec89a40d8a6Stephen M. Cameronstatic struct button_spec {
54f3074008948b51ec380b4f06791ceec89a40d8a6Stephen M. Cameron	const char *buttontext;
55f3074008948b51ec380b4f06791ceec89a40d8a6Stephen M. Cameron	clickfunction f;
56014f402496a3c73176937472485dedfc6ca0535eJens Axboe	const char *tooltiptext[2];
57014f402496a3c73176937472485dedfc6ca0535eJens Axboe	const int start_sensitive;
58f3074008948b51ec380b4f06791ceec89a40d8a6Stephen M. Cameron} buttonspeclist[] = {
5953e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	{
6053e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	  .buttontext		= "Connect",
6153e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	  .f			= connect_clicked,
6253e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	  .tooltiptext		= { "Disconnect from host", "Connect to host" },
6353e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	  .start_sensitive	= 1,
6453e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	},
6553e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	{
6653e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	  .buttontext		= "Send",
6753e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	  .f			= send_clicked,
6853e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	  .tooltiptext		= { "Send job description to host", NULL },
6953e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	  .start_sensitive	= 0,
7053e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	},
7153e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	{
7253e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	  .buttontext		= "Start Job",
7353e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	  .f			= start_job_clicked,
7453e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	  .tooltiptext		= { "Start the current job on the server", NULL },
7553e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	  .start_sensitive	= 0,
7653e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	},
77e0681f3edfb755e710fe7016e470d947bc5dbc3cJens Axboe};
78e0681f3edfb755e710fe7016e470d947bc5dbc3cJens Axboe
798dfd6071e1a4fd3966c0a77dbb7d719c52433b54Jens Axboestatic void setup_iops_graph(struct gfio_graphs *gg)
802f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe{
812f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	struct graph *g;
822f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
832f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	g = graph_new(DRAWING_AREA_XDIM / 2.0, DRAWING_AREA_YDIM, gfio_graph_font);
84d8fbeefb67641e9f63088b329de78a26a69fdbaeJens Axboe	graph_title(g, "IOPS (IOs/sec)");
852f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	graph_x_title(g, "Time (secs)");
868dfd6071e1a4fd3966c0a77dbb7d719c52433b54Jens Axboe	gg->read_iops = graph_add_label(g, "Read IOPS");
878dfd6071e1a4fd3966c0a77dbb7d719c52433b54Jens Axboe	gg->write_iops = graph_add_label(g, "Write IOPS");
885442cfb01f805ba26d3b8917b85c8e5f7bc50456Jens Axboe	gg->trim_iops = graph_add_label(g, "Trim IOPS");
89dbc542d442b81ddc58939be96a1c89e9953b9698Jens Axboe	graph_set_color(g, gg->read_iops, GFIO_READ_R, GFIO_READ_G, GFIO_READ_B);
90dbc542d442b81ddc58939be96a1c89e9953b9698Jens Axboe	graph_set_color(g, gg->write_iops, GFIO_WRITE_R, GFIO_WRITE_G, GFIO_WRITE_B);
91b78ca651a7254f01f5931ff49ca2206dcb42a056Jens Axboe	graph_set_color(g, gg->trim_iops, GFIO_TRIM_R, GFIO_TRIM_G, GFIO_TRIM_B);
928577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe	line_graph_set_data_count_limit(g, gfio_graph_limit);
93d8fbeefb67641e9f63088b329de78a26a69fdbaeJens Axboe	graph_add_extra_space(g, 0.0, 0.0, 0.0, 0.0);
9401a947f067b1a03add33e645ece73ac19d8257ddJens Axboe	graph_set_graph_all_zeroes(g, 0);
9575450781fef7fd1d48742dc3a791f0f1119c675cJens Axboe	gg->iops_graph = g;
962f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe}
972f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
988dfd6071e1a4fd3966c0a77dbb7d719c52433b54Jens Axboestatic void setup_bandwidth_graph(struct gfio_graphs *gg)
992f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe{
1002f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	struct graph *g;
1012f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
1022f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	g = graph_new(DRAWING_AREA_XDIM / 2.0, DRAWING_AREA_YDIM, gfio_graph_font);
103d8fbeefb67641e9f63088b329de78a26a69fdbaeJens Axboe	graph_title(g, "Bandwidth (bytes/sec)");
1042f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	graph_x_title(g, "Time (secs)");
1058dfd6071e1a4fd3966c0a77dbb7d719c52433b54Jens Axboe	gg->read_bw = graph_add_label(g, "Read Bandwidth");
1068dfd6071e1a4fd3966c0a77dbb7d719c52433b54Jens Axboe	gg->write_bw = graph_add_label(g, "Write Bandwidth");
1075442cfb01f805ba26d3b8917b85c8e5f7bc50456Jens Axboe	gg->trim_bw = graph_add_label(g, "Trim Bandwidth");
108dbc542d442b81ddc58939be96a1c89e9953b9698Jens Axboe	graph_set_color(g, gg->read_bw, GFIO_READ_R, GFIO_READ_G, GFIO_READ_B);
109dbc542d442b81ddc58939be96a1c89e9953b9698Jens Axboe	graph_set_color(g, gg->write_bw, GFIO_WRITE_R, GFIO_WRITE_G, GFIO_WRITE_B);
110b78ca651a7254f01f5931ff49ca2206dcb42a056Jens Axboe	graph_set_color(g, gg->trim_bw, GFIO_TRIM_R, GFIO_TRIM_G, GFIO_TRIM_B);
111d8fbeefb67641e9f63088b329de78a26a69fdbaeJens Axboe	graph_set_base_offset(g, 1);
1122f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	line_graph_set_data_count_limit(g, 100);
113d8fbeefb67641e9f63088b329de78a26a69fdbaeJens Axboe	graph_add_extra_space(g, 0.0, 0.0, 0.0, 0.0);
11401a947f067b1a03add33e645ece73ac19d8257ddJens Axboe	graph_set_graph_all_zeroes(g, 0);
11575450781fef7fd1d48742dc3a791f0f1119c675cJens Axboe	gg->bandwidth_graph = g;
1162f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe}
1172f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
1182f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboestatic void setup_graphs(struct gfio_graphs *g)
1192f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe{
1208dfd6071e1a4fd3966c0a77dbb7d719c52433b54Jens Axboe	setup_iops_graph(g);
1218dfd6071e1a4fd3966c0a77dbb7d719c52433b54Jens Axboe	setup_bandwidth_graph(g);
1222f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe}
1232f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
1241252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboevoid clear_ge_ui_info(struct gui_entry *ge)
1252f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe{
1262f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_label_set_text(GTK_LABEL(ge->probe.hostname), "");
1272f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_label_set_text(GTK_LABEL(ge->probe.os), "");
1282f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_label_set_text(GTK_LABEL(ge->probe.arch), "");
1292f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_label_set_text(GTK_LABEL(ge->probe.fio_ver), "");
1303863d1ad1020200f26958da42ed208f6c5c8f372Jens Axboe#if 0
1313863d1ad1020200f26958da42ed208f6c5c8f372Jens Axboe	/* should we empty it... */
1322f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_entry_set_text(GTK_ENTRY(ge->eta.name), "");
1333863d1ad1020200f26958da42ed208f6c5c8f372Jens Axboe#endif
134c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	multitext_update_entry(&ge->eta.iotype, 0, "");
13599d633af3611958ea6217f270677d0a657e4dddcJens Axboe	multitext_update_entry(&ge->eta.bs, 0, "");
136c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	multitext_update_entry(&ge->eta.ioengine, 0, "");
137c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	multitext_update_entry(&ge->eta.iodepth, 0, "");
1382f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_entry_set_text(GTK_ENTRY(ge->eta.jobs), "");
1392f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_entry_set_text(GTK_ENTRY(ge->eta.files), "");
1402f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_entry_set_text(GTK_ENTRY(ge->eta.read_bw), "");
1412f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_entry_set_text(GTK_ENTRY(ge->eta.read_iops), "");
1422f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_entry_set_text(GTK_ENTRY(ge->eta.write_bw), "");
1432f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_entry_set_text(GTK_ENTRY(ge->eta.write_iops), "");
1448663ea652b8ca7a368b39ef97e991180edebb57fJens Axboe}
1458663ea652b8ca7a368b39ef97e991180edebb57fJens Axboe
146781ccba635f4709bb580b3fac3b28c52a157275cJens Axboestatic void set_menu_entry_text(struct gui *ui, const char *path,
147781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe				const char *text)
148781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe{
149781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	GtkWidget *w;
150781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe
151781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	w = gtk_ui_manager_get_widget(ui->uimanager, path);
152781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	if (w)
153781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe		gtk_menu_item_set_label(GTK_MENU_ITEM(w), text);
154781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	else
155781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe		fprintf(stderr, "gfio: can't find path %s\n", path);
156781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe}
157781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe
158781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe
159781ccba635f4709bb580b3fac3b28c52a157275cJens Axboestatic void set_menu_entry_visible(struct gui *ui, const char *path, int show)
160781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe{
161781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	GtkWidget *w;
162781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe
163781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	w = gtk_ui_manager_get_widget(ui->uimanager, path);
164781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	if (w)
165781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe		gtk_widget_set_sensitive(w, show);
166781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	else
167781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe		fprintf(stderr, "gfio: can't find path %s\n", path);
168781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe}
169781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe
170781ccba635f4709bb580b3fac3b28c52a157275cJens Axboestatic void set_job_menu_visible(struct gui *ui, int visible)
171781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe{
172781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	set_menu_entry_visible(ui, "/MainMenu/JobMenu", visible);
173781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe}
174781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe
175781ccba635f4709bb580b3fac3b28c52a157275cJens Axboestatic void set_view_results_visible(struct gui *ui, int visible)
176781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe{
177781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	set_menu_entry_visible(ui, "/MainMenu/ViewMenu/Results", visible);
178781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe}
179781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe
180014f402496a3c73176937472485dedfc6ca0535eJens Axboestatic const char *get_button_tooltip(struct button_spec *s, int sensitive)
181014f402496a3c73176937472485dedfc6ca0535eJens Axboe{
182014f402496a3c73176937472485dedfc6ca0535eJens Axboe	if (s->tooltiptext[sensitive])
183014f402496a3c73176937472485dedfc6ca0535eJens Axboe		return s->tooltiptext[sensitive];
184014f402496a3c73176937472485dedfc6ca0535eJens Axboe
185014f402496a3c73176937472485dedfc6ca0535eJens Axboe	return s->tooltiptext[0];
186014f402496a3c73176937472485dedfc6ca0535eJens Axboe}
187014f402496a3c73176937472485dedfc6ca0535eJens Axboe
188014f402496a3c73176937472485dedfc6ca0535eJens Axboestatic GtkWidget *add_button(GtkWidget *buttonbox,
189014f402496a3c73176937472485dedfc6ca0535eJens Axboe			     struct button_spec *buttonspec, gpointer data)
190014f402496a3c73176937472485dedfc6ca0535eJens Axboe{
191014f402496a3c73176937472485dedfc6ca0535eJens Axboe	GtkWidget *button = gtk_button_new_with_label(buttonspec->buttontext);
192014f402496a3c73176937472485dedfc6ca0535eJens Axboe	gboolean sens = buttonspec->start_sensitive;
193014f402496a3c73176937472485dedfc6ca0535eJens Axboe
194014f402496a3c73176937472485dedfc6ca0535eJens Axboe	g_signal_connect(button, "clicked", G_CALLBACK(buttonspec->f), data);
195014f402496a3c73176937472485dedfc6ca0535eJens Axboe	gtk_box_pack_start(GTK_BOX(buttonbox), button, FALSE, FALSE, 3);
196014f402496a3c73176937472485dedfc6ca0535eJens Axboe
197014f402496a3c73176937472485dedfc6ca0535eJens Axboe	sens = buttonspec->start_sensitive;
198014f402496a3c73176937472485dedfc6ca0535eJens Axboe	gtk_widget_set_tooltip_text(button, get_button_tooltip(buttonspec, sens));
199014f402496a3c73176937472485dedfc6ca0535eJens Axboe	gtk_widget_set_sensitive(button, sens);
200014f402496a3c73176937472485dedfc6ca0535eJens Axboe
201014f402496a3c73176937472485dedfc6ca0535eJens Axboe	return button;
202014f402496a3c73176937472485dedfc6ca0535eJens Axboe}
203014f402496a3c73176937472485dedfc6ca0535eJens Axboe
204014f402496a3c73176937472485dedfc6ca0535eJens Axboestatic void add_buttons(struct gui_entry *ge, struct button_spec *buttonlist,
205014f402496a3c73176937472485dedfc6ca0535eJens Axboe			int nbuttons)
206014f402496a3c73176937472485dedfc6ca0535eJens Axboe{
207014f402496a3c73176937472485dedfc6ca0535eJens Axboe	int i;
208014f402496a3c73176937472485dedfc6ca0535eJens Axboe
209014f402496a3c73176937472485dedfc6ca0535eJens Axboe	for (i = 0; i < nbuttons; i++)
210014f402496a3c73176937472485dedfc6ca0535eJens Axboe		ge->button[i] = add_button(ge->buttonbox, &buttonlist[i], ge);
211014f402496a3c73176937472485dedfc6ca0535eJens Axboe}
212014f402496a3c73176937472485dedfc6ca0535eJens Axboe
21385dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe/*
21485dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe * Update sensitivity of job buttons and job menu items, based on the
21585dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe * state of the client.
21685dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe */
21785dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboestatic void update_button_states(struct gui *ui, struct gui_entry *ge)
21885dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe{
21985dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	unsigned int connect_state, send_state, start_state, edit_state;
22085dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	const char *connect_str = NULL;
22185dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe
22285dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	switch (ge->state) {
2231252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	default:
2241252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		gfio_report_error(ge, "Bad client state: %u\n", ge->state);
22585dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		/* fall through to new state */
22685dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	case GE_STATE_NEW:
22785dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		connect_state = 1;
2289af4a24408ea7d4cea084a4fe214b81145cc36acJens Axboe		edit_state = 1;
22985dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		connect_str = "Connect";
23085dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		send_state = 0;
23185dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		start_state = 0;
23285dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		break;
23385dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	case GE_STATE_CONNECTED:
23485dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		connect_state = 1;
2359af4a24408ea7d4cea084a4fe214b81145cc36acJens Axboe		edit_state = 1;
23685dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		connect_str = "Disconnect";
23785dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		send_state = 1;
23885dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		start_state = 0;
23985dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		break;
24085dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	case GE_STATE_JOB_SENT:
24185dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		connect_state = 1;
2429af4a24408ea7d4cea084a4fe214b81145cc36acJens Axboe		edit_state = 1;
24385dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		connect_str = "Disconnect";
24485dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		send_state = 0;
24585dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		start_state = 1;
24685dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		break;
24785dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	case GE_STATE_JOB_STARTED:
24885dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		connect_state = 1;
24985dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		edit_state = 1;
25085dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		connect_str = "Disconnect";
25185dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		send_state = 0;
25285dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		start_state = 1;
25385dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		break;
25485dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	case GE_STATE_JOB_RUNNING:
25585dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		connect_state = 1;
25685dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		edit_state = 0;
25785dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		connect_str = "Disconnect";
25885dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		send_state = 0;
25985dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		start_state = 0;
26085dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		break;
26185dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	case GE_STATE_JOB_DONE:
26285dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		connect_state = 1;
26385dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		edit_state = 0;
26485dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		connect_str = "Connect";
26585dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		send_state = 0;
26685dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		start_state = 0;
26785dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		break;
26885dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	}
26985dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe
27053e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	gtk_widget_set_sensitive(ge->button[GFIO_BUTTON_CONNECT], connect_state);
27153e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	gtk_widget_set_sensitive(ge->button[GFIO_BUTTON_SEND], send_state);
27253e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	gtk_widget_set_sensitive(ge->button[GFIO_BUTTON_START], start_state);
27353e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	gtk_button_set_label(GTK_BUTTON(ge->button[GFIO_BUTTON_CONNECT]), connect_str);
27453e0e85d6d5311fce98b94c1e06fab8263bafc02Jens Axboe	gtk_widget_set_tooltip_text(ge->button[GFIO_BUTTON_CONNECT], get_button_tooltip(&buttonspeclist[GFIO_BUTTON_CONNECT], connect_state));
27585dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe
276781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	set_menu_entry_visible(ui, "/MainMenu/JobMenu/Connect", connect_state);
277781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	set_menu_entry_text(ui, "/MainMenu/JobMenu/Connect", connect_str);
27885dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe
279781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	set_menu_entry_visible(ui, "/MainMenu/JobMenu/Edit job", edit_state);
280781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	set_menu_entry_visible(ui, "/MainMenu/JobMenu/Send job", send_state);
281781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	set_menu_entry_visible(ui, "/MainMenu/JobMenu/Start job", start_state);
28285dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe
283781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	if (ge->client && ge->client->nr_results)
284781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe		set_view_results_visible(ui, 1);
285781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	else
286781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe		set_view_results_visible(ui, 0);
28785dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe}
28885dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe
2891252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboevoid gfio_set_state(struct gui_entry *ge, unsigned int state)
29085dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe{
29185dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	ge->state = state;
29285dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	update_button_states(ge->ui, ge);
29385dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe}
29485dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe
2959b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboestatic void gfio_ui_setup_log(struct gui *ui)
2969b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe{
2979b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	GtkTreeSelection *selection;
2989b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	GtkListStore *model;
2999b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	GtkWidget *tree_view;
3009b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe
3013ad04399c576bb7935b9a7b8c07d5acf373a7bc4Jens Axboe	model = gtk_list_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3029b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe
3039b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
3049b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	gtk_widget_set_can_focus(tree_view, FALSE);
3059b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe
3069b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
3079b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_BROWSE);
308661f741a0378423ddf45e3f878e029e04c4c01f5Jens Axboe	g_object_set(G_OBJECT(tree_view), "headers-visible", TRUE,
309661f741a0378423ddf45e3f878e029e04c4c01f5Jens Axboe		"enable-grid-lines", GTK_TREE_VIEW_GRID_LINES_BOTH, NULL);
3109b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe
3119b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	tree_view_column(tree_view, 0, "Time", ALIGN_RIGHT | UNSORTABLE);
3129b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	tree_view_column(tree_view, 1, "Host", ALIGN_RIGHT | UNSORTABLE);
3139b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	tree_view_column(tree_view, 2, "Level", ALIGN_RIGHT | UNSORTABLE);
314f095d56371c1b5917559f0f8693ccfe032b5b779Jens Axboe	tree_view_column(tree_view, 3, "Text", ALIGN_LEFT | UNSORTABLE);
3159b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe
3169b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	ui->log_model = model;
3179b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	ui->log_tree = tree_view;
3189b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe}
3199b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe
3201252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboestatic gint on_config_drawing_area(GtkWidget *w, GdkEventConfigure *event,
3211252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe				   gpointer data)
322c57f254caa98902968c928d761dd99e1fa18a35cStephen M. Cameron{
323cd0d2db8d4a8863bb48eca8bb197bd73d2f6c9a4Jens Axboe	guint width = gtk_widget_get_allocated_width(w);
324cd0d2db8d4a8863bb48eca8bb197bd73d2f6c9a4Jens Axboe	guint height = gtk_widget_get_allocated_height(w);
3251252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	struct gfio_graphs *g = data;
326c57f254caa98902968c928d761dd99e1fa18a35cStephen M. Cameron
327cd0d2db8d4a8863bb48eca8bb197bd73d2f6c9a4Jens Axboe	graph_set_size(g->iops_graph, width / 2.0, height);
328cd0d2db8d4a8863bb48eca8bb197bd73d2f6c9a4Jens Axboe	graph_set_position(g->iops_graph, width / 2.0, 0.0);
329cd0d2db8d4a8863bb48eca8bb197bd73d2f6c9a4Jens Axboe	graph_set_size(g->bandwidth_graph, width / 2.0, height);
3301252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	graph_set_position(g->bandwidth_graph, 0, 0);
3311252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	return TRUE;
332c57f254caa98902968c928d761dd99e1fa18a35cStephen M. Cameron}
333c57f254caa98902968c928d761dd99e1fa18a35cStephen M. Cameron
3341252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboestatic void draw_graph(struct graph *g, cairo_t *cr)
335a269790cd25788dd4226641a3ceab1b3c8fda14bJens Axboe{
3361252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	line_graph_draw(g, cr);
3371252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	cairo_stroke(cr);
3381252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe}
339a269790cd25788dd4226641a3ceab1b3c8fda14bJens Axboe
3401252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboestatic gboolean graph_tooltip(GtkWidget *w, gint x, gint y,
3411252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe			      gboolean keyboard_mode, GtkTooltip *tooltip,
3421252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe			      gpointer data)
3431252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe{
3441252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	struct gfio_graphs *g = data;
3451252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	const char *text = NULL;
346a269790cd25788dd4226641a3ceab1b3c8fda14bJens Axboe
3471252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	if (graph_contains_xy(g->iops_graph, x, y))
3481252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		text = graph_find_tooltip(g->iops_graph, x, y);
3491252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	else if (graph_contains_xy(g->bandwidth_graph, x, y))
3501252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		text = graph_find_tooltip(g->bandwidth_graph, x, y);
351a269790cd25788dd4226641a3ceab1b3c8fda14bJens Axboe
3521252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	if (text) {
3531252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		gtk_tooltip_set_text(tooltip, text);
3541252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		return TRUE;
355e0681f3edfb755e710fe7016e470d947bc5dbc3cJens Axboe	}
356a269790cd25788dd4226641a3ceab1b3c8fda14bJens Axboe
3571252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	return FALSE;
358a269790cd25788dd4226641a3ceab1b3c8fda14bJens Axboe}
359a269790cd25788dd4226641a3ceab1b3c8fda14bJens Axboe
3601252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboestatic int on_expose_drawing_area(GtkWidget *w, GdkEvent *event, gpointer p)
361c57f254caa98902968c928d761dd99e1fa18a35cStephen M. Cameron{
3621252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	struct gfio_graphs *g = p;
363c57f254caa98902968c928d761dd99e1fa18a35cStephen M. Cameron	cairo_t *cr;
364c57f254caa98902968c928d761dd99e1fa18a35cStephen M. Cameron
365cd0d2db8d4a8863bb48eca8bb197bd73d2f6c9a4Jens Axboe	cr = gdk_cairo_create(gtk_widget_get_window(w));
3661252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe
3671252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	if (graph_has_tooltips(g->iops_graph) ||
3681252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	    graph_has_tooltips(g->bandwidth_graph)) {
369c57f254caa98902968c928d761dd99e1fa18a35cStephen M. Cameron		g_object_set(w, "has-tooltip", TRUE, NULL);
3701252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		g_signal_connect(w, "query-tooltip", G_CALLBACK(graph_tooltip), g);
371c57f254caa98902968c928d761dd99e1fa18a35cStephen M. Cameron	}
3721252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe
373c57f254caa98902968c928d761dd99e1fa18a35cStephen M. Cameron	cairo_set_source_rgb(cr, 0, 0, 0);
3741252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	draw_graph(g->iops_graph, cr);
3751252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	draw_graph(g->bandwidth_graph, cr);
376c57f254caa98902968c928d761dd99e1fa18a35cStephen M. Cameron	cairo_destroy(cr);
377c57f254caa98902968c928d761dd99e1fa18a35cStephen M. Cameron
378c57f254caa98902968c928d761dd99e1fa18a35cStephen M. Cameron	return FALSE;
379c57f254caa98902968c928d761dd99e1fa18a35cStephen M. Cameron}
380c57f254caa98902968c928d761dd99e1fa18a35cStephen M. Cameron
3811252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe/*
3821252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe * FIXME: need more handling here
3831252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe */
3841252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboestatic void ge_destroy(struct gui_entry *ge)
385c57f254caa98902968c928d761dd99e1fa18a35cStephen M. Cameron{
3861252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	struct gfio_client *gc = ge->client;
387c57f254caa98902968c928d761dd99e1fa18a35cStephen M. Cameron
388470cdbb7a77db8293440c8f7610e49b2537d6b7bJens Axboe	if (gc) {
389470cdbb7a77db8293440c8f7610e49b2537d6b7bJens Axboe		if (gc->client) {
390470cdbb7a77db8293440c8f7610e49b2537d6b7bJens Axboe			if (ge->state >= GE_STATE_CONNECTED)
391470cdbb7a77db8293440c8f7610e49b2537d6b7bJens Axboe				fio_client_terminate(gc->client);
392470cdbb7a77db8293440c8f7610e49b2537d6b7bJens Axboe
393470cdbb7a77db8293440c8f7610e49b2537d6b7bJens Axboe			fio_put_client(gc->client);
394470cdbb7a77db8293440c8f7610e49b2537d6b7bJens Axboe		}
395470cdbb7a77db8293440c8f7610e49b2537d6b7bJens Axboe		free(gc);
396a269790cd25788dd4226641a3ceab1b3c8fda14bJens Axboe	}
397a269790cd25788dd4226641a3ceab1b3c8fda14bJens Axboe
398b98ab718031a25ecfd3fa64df3f9992baa83b5acJens Axboe	g_hash_table_remove(ge->ui->ge_hash, &ge->page_num);
399b98ab718031a25ecfd3fa64df3f9992baa83b5acJens Axboe
4001252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	free(ge->job_file);
4011252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	free(ge->host);
4021252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	free(ge);
403a269790cd25788dd4226641a3ceab1b3c8fda14bJens Axboe}
404a269790cd25788dd4226641a3ceab1b3c8fda14bJens Axboe
4051252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboestatic void ge_widget_destroy(GtkWidget *w, gpointer data)
4063650a3ca2ccbfefe7564d6ebde03bf7f89255e89Jens Axboe{
4071252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	struct gui_entry *ge = (struct gui_entry *) data;
4083650a3ca2ccbfefe7564d6ebde03bf7f89255e89Jens Axboe
4091252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	ge_destroy(ge);
4103650a3ca2ccbfefe7564d6ebde03bf7f89255e89Jens Axboe}
4113650a3ca2ccbfefe7564d6ebde03bf7f89255e89Jens Axboe
4121252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboestatic void gfio_quit(struct gui *ui)
4133650a3ca2ccbfefe7564d6ebde03bf7f89255e89Jens Axboe{
4143c3ed070502bbfec387ded2c43d5e4559ca24a63Jens Axboe	gtk_main_quit();
4151252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe}
4163650a3ca2ccbfefe7564d6ebde03bf7f89255e89Jens Axboe
4171252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboestatic void quit_clicked(__attribute__((unused)) GtkWidget *widget,
4183c3ed070502bbfec387ded2c43d5e4559ca24a63Jens Axboe			 gpointer data)
4191252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe{
4201252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	struct gui *ui = (struct gui *) data;
4213650a3ca2ccbfefe7564d6ebde03bf7f89255e89Jens Axboe
4221252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	gfio_quit(ui);
4231252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe}
4243650a3ca2ccbfefe7564d6ebde03bf7f89255e89Jens Axboe
4251252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboestatic void *job_thread(void *arg)
4261252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe{
4271252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	struct gui *ui = arg;
4283650a3ca2ccbfefe7564d6ebde03bf7f89255e89Jens Axboe
4291252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	ui->handler_running = 1;
4301252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	fio_handle_clients(&gfio_client_ops);
4311252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	ui->handler_running = 0;
4321252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	return NULL;
4331252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe}
434ca850992888df61f347ad839be0c4091ff25bea3Jens Axboe
4351252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboestatic int send_job_file(struct gui_entry *ge)
4361252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe{
4371252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	struct gfio_client *gc = ge->client;
4381252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	int ret = 0;
439ca850992888df61f347ad839be0c4091ff25bea3Jens Axboe
440753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe	/*
441753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe	 * Prune old options, we are expecting the return options
442753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe	 * when the job file is parsed remotely and returned to us.
443753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe	 */
444753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe	while (!flist_empty(&gc->o_list)) {
445753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe		struct gfio_client_options *gco;
446753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe
447753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe		gco = flist_entry(gc->o_list.next, struct gfio_client_options, list);
448753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe		flist_del(&gco->list);
449753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe		free(gco);
450753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe	}
451753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe
4521252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	ret = fio_client_send_ini(gc->client, ge->job_file);
4531252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	if (!ret)
4541252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		return 0;
455ca850992888df61f347ad839be0c4091ff25bea3Jens Axboe
4561252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	gfio_report_error(ge, "Failed to send file %s: %s\n", ge->job_file, strerror(-ret));
4571252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	return 1;
4581252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe}
459ca850992888df61f347ad839be0c4091ff25bea3Jens Axboe
4601252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboestatic void *server_thread(void *arg)
4611252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe{
4621252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	is_backend = 1;
4631252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	gfio_server_running = 1;
4641252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	fio_start_server(NULL);
4651252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	gfio_server_running = 0;
4661252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	return NULL;
4671252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe}
468ca850992888df61f347ad839be0c4091ff25bea3Jens Axboe
4691252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboestatic void gfio_start_server(struct gui *ui)
4701252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe{
4711252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	if (!gfio_server_running) {
4721252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		gfio_server_running = 1;
4731252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		pthread_create(&ui->server_t, NULL, server_thread, NULL);
4741252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		pthread_detach(ui->server_t);
4752b0898923ad51ef5d0a84826c391b889675e57faJens Axboe	}
4763650a3ca2ccbfefe7564d6ebde03bf7f89255e89Jens Axboe}
4773650a3ca2ccbfefe7564d6ebde03bf7f89255e89Jens Axboe
4781252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboestatic void start_job_clicked(__attribute__((unused)) GtkWidget *widget,
4793c3ed070502bbfec387ded2c43d5e4559ca24a63Jens Axboe			      gpointer data)
48009d574e341c05aa1d61a33c19c05ec792bbf78a8Jens Axboe{
4811252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	struct gui_entry *ge = data;
4821252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	struct gfio_client *gc = ge->client;
48309d574e341c05aa1d61a33c19c05ec792bbf78a8Jens Axboe
4841252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	if (gc)
4851252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		fio_start_client(gc->client);
48609d574e341c05aa1d61a33c19c05ec792bbf78a8Jens Axboe}
48709d574e341c05aa1d61a33c19c05ec792bbf78a8Jens Axboe
4881252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboestatic void file_open(GtkWidget *w, gpointer data);
489e5bd13470beaeed9c4a6835b7b92265fb94173a9Jens Axboe
4901252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboestruct connection_widgets
4911252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe{
4921252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	GtkWidget *hentry;
4931252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	GtkWidget *combo;
4941252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	GtkWidget *button;
4951252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe};
496e5bd13470beaeed9c4a6835b7b92265fb94173a9Jens Axboe
4971252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboestatic void hostname_cb(GtkEntry *entry, gpointer data)
4981252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe{
4991252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	struct connection_widgets *cw = data;
5001252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	int uses_net = 0, is_localhost = 0;
5011252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	const gchar *text;
5021252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	gchar *ctext;
503e5bd13470beaeed9c4a6835b7b92265fb94173a9Jens Axboe
5041252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	/*
5051252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	 * Check whether to display the 'auto start backend' box
5061252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	 * or not. Show it if we are a localhost and using network,
5071252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	 * or using a socket.
5081252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	 */
509f762cef937f69d6a23127baf47f22e8ffaea4c11Jens Axboe	ctext = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(cw->combo));
5101252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	if (!ctext || !strncmp(ctext, "IPv4", 4) || !strncmp(ctext, "IPv6", 4))
5111252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		uses_net = 1;
5121252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	g_free(ctext);
513e5bd13470beaeed9c4a6835b7b92265fb94173a9Jens Axboe
5141252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	if (uses_net) {
5151252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		text = gtk_entry_get_text(GTK_ENTRY(cw->hentry));
5161252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		if (!strcmp(text, "127.0.0.1") || !strcmp(text, "localhost") ||
5171252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		    !strcmp(text, "::1") || !strcmp(text, "ip6-localhost") ||
5181252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		    !strcmp(text, "ip6-loopback"))
5191252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe			is_localhost = 1;
5201252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	}
521e5bd13470beaeed9c4a6835b7b92265fb94173a9Jens Axboe
5221252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	if (!uses_net || is_localhost) {
5231252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw->button), 1);
5241252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		gtk_widget_set_sensitive(cw->button, 1);
5251252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	} else {
5261252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw->button), 0);
5271252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		gtk_widget_set_sensitive(cw->button, 0);
5281252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	}
529b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
530661f741a0378423ddf45e3f878e029e04c4c01f5Jens Axboe
531b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic int get_connection_details(struct gui_entry *ge)
532b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
533b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	GtkWidget *dialog, *box, *vbox, *hbox, *frame, *pentry;
534b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	struct connection_widgets cw;
535b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	struct gui *ui = ge->ui;
536b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	char *typeentry;
5372e33101f218a1603eeecca969f5b7a0e98696a01Jens Axboe
538b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	if (ge->host)
539b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		return 0;
540b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
541b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	dialog = gtk_dialog_new_with_buttons("Connection details",
542b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			GTK_WINDOW(ui->window),
543b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			GTK_DIALOG_DESTROY_WITH_PARENT,
544b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
545b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
546b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
547b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	frame = gtk_frame_new("Hostname / socket name");
548f762cef937f69d6a23127baf47f22e8ffaea4c11Jens Axboe	vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
549b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
550b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
551b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	box = gtk_vbox_new(FALSE, 6);
552b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_container_add(GTK_CONTAINER(frame), box);
553b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
554b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	hbox = gtk_hbox_new(TRUE, 10);
555b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
556b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	cw.hentry = gtk_entry_new();
557b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_entry_set_text(GTK_ENTRY(cw.hentry), "localhost");
558b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_box_pack_start(GTK_BOX(hbox), cw.hentry, TRUE, TRUE, 0);
559b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
560b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	frame = gtk_frame_new("Port");
561b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
562b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	box = gtk_vbox_new(FALSE, 10);
563b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_container_add(GTK_CONTAINER(frame), box);
564b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
565b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	hbox = gtk_hbox_new(TRUE, 4);
566b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
567b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	pentry = create_spinbutton(hbox, 1, 65535, FIO_NET_PORT);
568b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
569b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	frame = gtk_frame_new("Type");
570b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
571b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	box = gtk_vbox_new(FALSE, 10);
572b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_container_add(GTK_CONTAINER(frame), box);
573b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
574b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	hbox = gtk_hbox_new(TRUE, 4);
575b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
576b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
577f762cef937f69d6a23127baf47f22e8ffaea4c11Jens Axboe	cw.combo = gtk_combo_box_text_new();
578f762cef937f69d6a23127baf47f22e8ffaea4c11Jens Axboe	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cw.combo), "IPv4");
579f762cef937f69d6a23127baf47f22e8ffaea4c11Jens Axboe	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cw.combo), "IPv6");
580f762cef937f69d6a23127baf47f22e8ffaea4c11Jens Axboe	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cw.combo), "local socket");
581b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_combo_box_set_active(GTK_COMBO_BOX(cw.combo), 0);
582b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
583b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_container_add(GTK_CONTAINER(hbox), cw.combo);
584b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
585b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	frame = gtk_frame_new("Options");
586b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
587b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	box = gtk_vbox_new(FALSE, 10);
588b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_container_add(GTK_CONTAINER(frame), box);
589b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
590b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	hbox = gtk_hbox_new(TRUE, 4);
591b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
592b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
593b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	cw.button = gtk_check_button_new_with_label("Auto-spawn fio backend");
594b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw.button), 1);
595b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	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.");
596b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_box_pack_start(GTK_BOX(hbox), cw.button, FALSE, FALSE, 6);
5972e33101f218a1603eeecca969f5b7a0e98696a01Jens Axboe
598b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	/*
599b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	 * Connect edit signal, so we can show/not-show the auto start button
600b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	 */
601cd972fddb5a626bc9bc3fa55d199ed39f0ccc11fJens Axboe	g_signal_connect(G_OBJECT(cw.hentry), "changed", G_CALLBACK(hostname_cb), &cw);
602cd972fddb5a626bc9bc3fa55d199ed39f0ccc11fJens Axboe	g_signal_connect(G_OBJECT(cw.combo), "changed", G_CALLBACK(hostname_cb), &cw);
6032e33101f218a1603eeecca969f5b7a0e98696a01Jens Axboe
604b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_widget_show_all(dialog);
6052e33101f218a1603eeecca969f5b7a0e98696a01Jens Axboe
606b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
6071252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		gtk_widget_destroy(dialog);
608b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		return 1;
6091252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	}
6102e33101f218a1603eeecca969f5b7a0e98696a01Jens Axboe
611b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	ge->host = strdup(gtk_entry_get_text(GTK_ENTRY(cw.hentry)));
612b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	ge->port = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(pentry));
6132e33101f218a1603eeecca969f5b7a0e98696a01Jens Axboe
614f762cef937f69d6a23127baf47f22e8ffaea4c11Jens Axboe	typeentry = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(cw.combo));
615b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	if (!typeentry || !strncmp(typeentry, "IPv4", 4))
616b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		ge->type = Fio_client_ipv4;
617b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	else if (!strncmp(typeentry, "IPv6", 4))
618b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		ge->type = Fio_client_ipv6;
619b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	else
620b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		ge->type = Fio_client_socket;
621b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	g_free(typeentry);
6222e33101f218a1603eeecca969f5b7a0e98696a01Jens Axboe
623b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	ge->server_start = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cw.button));
6242e33101f218a1603eeecca969f5b7a0e98696a01Jens Axboe
625b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_widget_destroy(dialog);
626b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	return 0;
627b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
6281252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe
629b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic void gfio_set_client(struct gfio_client *gc, struct fio_client *client)
630b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
631b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gc->client = fio_get_client(client);
632b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	client->client_data = gc;
633b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
634b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
635b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic void gfio_client_added(struct gui_entry *ge, struct fio_client *client)
636b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
637cf3d824147fe285bba1c93f341f6e44c34aaccd9Jens Axboe	struct gfio_client_options *gco;
638b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	struct gfio_client *gc;
639b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
640cf3d824147fe285bba1c93f341f6e44c34aaccd9Jens Axboe	gc = calloc(1, sizeof(*gc));
641cf3d824147fe285bba1c93f341f6e44c34aaccd9Jens Axboe	INIT_FLIST_HEAD(&gc->o_list);
642b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gc->ge = ge;
643b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	ge->client = gc;
644b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gfio_set_client(gc, client);
645cf3d824147fe285bba1c93f341f6e44c34aaccd9Jens Axboe
646cf3d824147fe285bba1c93f341f6e44c34aaccd9Jens Axboe	/*
647cf3d824147fe285bba1c93f341f6e44c34aaccd9Jens Axboe	 * Just add a default set of options, need to consider how best
648cf3d824147fe285bba1c93f341f6e44c34aaccd9Jens Axboe	 * to handle this
649cf3d824147fe285bba1c93f341f6e44c34aaccd9Jens Axboe	 */
650cf3d824147fe285bba1c93f341f6e44c34aaccd9Jens Axboe	gco = calloc(1, sizeof(*gco));
651753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe	INIT_FLIST_HEAD(&gco->list);
652cf3d824147fe285bba1c93f341f6e44c34aaccd9Jens Axboe	options_default_fill(&gco->o);
653cf3d824147fe285bba1c93f341f6e44c34aaccd9Jens Axboe	flist_add_tail(&gco->list, &gc->o_list);
654753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe	gc->o_list_nr++;
655b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
656b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
6575721d270285a5f7e41b0b076a4a43b825239d964Jens Axboestatic void gfio_clear_graph_data(struct gfio_graphs *g)
6585721d270285a5f7e41b0b076a4a43b825239d964Jens Axboe{
6595721d270285a5f7e41b0b076a4a43b825239d964Jens Axboe	graph_clear_values(g->iops_graph);
6605721d270285a5f7e41b0b076a4a43b825239d964Jens Axboe	graph_clear_values(g->bandwidth_graph);
6615721d270285a5f7e41b0b076a4a43b825239d964Jens Axboe}
6625721d270285a5f7e41b0b076a4a43b825239d964Jens Axboe
663b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic void connect_clicked(GtkWidget *widget, gpointer data)
664b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
665b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	struct gui_entry *ge = data;
666b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	struct gfio_client *gc = ge->client;
667b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
668b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	if (ge->state == GE_STATE_NEW) {
669b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		int ret;
67019998dbcb6712ba5885c059428ac511d306890cfJens Axboe
671b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		if (!ge->job_file)
672b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			file_open(widget, ge->ui);
673b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		if (!ge->job_file)
674b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			return;
6752e33101f218a1603eeecca969f5b7a0e98696a01Jens Axboe
676b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		gc = ge->client;
6772e33101f218a1603eeecca969f5b7a0e98696a01Jens Axboe
678b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		if (!gc->client) {
679b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			struct fio_client *client;
68019998dbcb6712ba5885c059428ac511d306890cfJens Axboe
681b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			if (get_connection_details(ge)) {
682b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe				gfio_report_error(ge, "Failed to get connection details\n");
683b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe				return;
6841252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe			}
6852e33101f218a1603eeecca969f5b7a0e98696a01Jens Axboe
686b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			client = fio_client_add_explicit(&gfio_client_ops, ge->host, ge->type, ge->port);
687b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			if (!client) {
688b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe				gfio_report_error(ge, "Failed to add client %s\n", ge->host);
689b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe				free(ge->host);
690b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe				ge->host = NULL;
691b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe				return;
6921252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe			}
693b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			gfio_set_client(gc, client);
694b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		}
695b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
696b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ge->thread_status_pb), "No jobs running");
697b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ge->thread_status_pb), 0.0);
698b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		ret = fio_client_connect(gc->client);
699b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		if (!ret) {
700b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			if (!ge->ui->handler_running)
701b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe				pthread_create(&ge->ui->t, NULL, job_thread, ge->ui);
702b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			gfio_set_state(ge, GE_STATE_CONNECTED);
7035721d270285a5f7e41b0b076a4a43b825239d964Jens Axboe			gfio_clear_graph_data(&ge->graphs);
7041252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		} else {
705b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			gfio_report_error(ge, "Failed to connect to %s: %s\n", ge->client->client->hostname, strerror(-ret));
7062e33101f218a1603eeecca969f5b7a0e98696a01Jens Axboe		}
707b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	} else {
708b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		fio_client_terminate(gc->client);
709b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		gfio_set_state(ge, GE_STATE_NEW);
710b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		clear_ge_ui_info(ge);
7112e33101f218a1603eeecca969f5b7a0e98696a01Jens Axboe	}
712b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
7132e33101f218a1603eeecca969f5b7a0e98696a01Jens Axboe
714b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic void send_clicked(GtkWidget *widget, gpointer data)
715b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
716b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	struct gui_entry *ge = data;
7172e33101f218a1603eeecca969f5b7a0e98696a01Jens Axboe
718b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	if (send_job_file(ge))
719b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		gtk_widget_set_sensitive(ge->button[GFIO_BUTTON_START], 1);
720b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
72162bc937f9ee196342184ff1ece0b9f404bbd0585Jens Axboe
722b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic GtkWidget *new_client_page(struct gui_entry *ge);
72362bc937f9ee196342184ff1ece0b9f404bbd0585Jens Axboe
724b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic struct gui_entry *alloc_new_gui_entry(struct gui *ui)
725b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
726b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	struct gui_entry *ge;
727a7a42ce19d0f1339ce7d0768683afaa043d5ab36Jens Axboe
728b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	ge = malloc(sizeof(*ge));
729b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	memset(ge, 0, sizeof(*ge));
730b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	ge->state = GE_STATE_NEW;
731b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	ge->ui = ui;
732b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	return ge;
733b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
734a7a42ce19d0f1339ce7d0768683afaa043d5ab36Jens Axboe
735b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic struct gui_entry *get_new_ge_with_tab(struct gui *ui, const char *name)
736b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
737b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	struct gui_entry *ge;
738a7a42ce19d0f1339ce7d0768683afaa043d5ab36Jens Axboe
739b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	ge = alloc_new_gui_entry(ui);
740a7a42ce19d0f1339ce7d0768683afaa043d5ab36Jens Axboe
741b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	ge->vbox = new_client_page(ge);
742b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	g_signal_connect(ge->vbox, "destroy", G_CALLBACK(ge_widget_destroy), ge);
743a7a42ce19d0f1339ce7d0768683afaa043d5ab36Jens Axboe
744b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	ge->page_label = gtk_label_new(name);
745b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	ge->page_num = gtk_notebook_append_page(GTK_NOTEBOOK(ui->notebook), ge->vbox, ge->page_label);
746b9f3c7ed703f0f94476c5d9123034a45a4936517Jens Axboe
747b98ab718031a25ecfd3fa64df3f9992baa83b5acJens Axboe	g_hash_table_insert(ui->ge_hash, &ge->page_num, ge);
748b98ab718031a25ecfd3fa64df3f9992baa83b5acJens Axboe
749b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_widget_show_all(ui->window);
750b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	return ge;
751b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
752b9f3c7ed703f0f94476c5d9123034a45a4936517Jens Axboe
753b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic void file_new(GtkWidget *w, gpointer data)
754b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
755b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	struct gui *ui = (struct gui *) data;
756b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	struct gui_entry *ge;
75762bc937f9ee196342184ff1ece0b9f404bbd0585Jens Axboe
758b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	ge = get_new_ge_with_tab(ui, "Untitled");
759b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_notebook_set_current_page(GTK_NOTEBOOK(ui->notebook), ge->page_num);
760b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
761a7a42ce19d0f1339ce7d0768683afaa043d5ab36Jens Axboe
762b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe/*
763b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe * Return the 'ge' corresponding to the tab. If the active tab is the
764b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe * main tab, open a new tab.
765b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe */
766b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic struct gui_entry *get_ge_from_page(struct gui *ui, gint cur_page,
767b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe					  int *created)
768b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
769b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	if (!cur_page) {
7701252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		if (created)
771b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			*created = 1;
772b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		return get_new_ge_with_tab(ui, "Untitled");
773b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	}
774b9f3c7ed703f0f94476c5d9123034a45a4936517Jens Axboe
775b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	if (created)
776b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		*created = 0;
777a7a42ce19d0f1339ce7d0768683afaa043d5ab36Jens Axboe
778b98ab718031a25ecfd3fa64df3f9992baa83b5acJens Axboe	return g_hash_table_lookup(ui->ge_hash, &cur_page);
779b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
780e0681f3edfb755e710fe7016e470d947bc5dbc3cJens Axboe
781b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic struct gui_entry *get_ge_from_cur_tab(struct gui *ui)
782b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
783b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gint cur_page;
784e0681f3edfb755e710fe7016e470d947bc5dbc3cJens Axboe
785b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	/*
786b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	 * Main tab is tab 0, so any current page other than 0 holds
787b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	 * a ge entry.
788b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	 */
789b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	cur_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(ui->notebook));
790b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	if (cur_page)
791b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		return get_ge_from_page(ui, cur_page, NULL);
7920cf3ece062d6856bd79b89770780296c99937a98Jens Axboe
793b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	return NULL;
794b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
7950cf3ece062d6856bd79b89770780296c99937a98Jens Axboe
796b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic void file_close(GtkWidget *w, gpointer data)
797b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
798b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	struct gui *ui = (struct gui *) data;
799b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	struct gui_entry *ge;
8002f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
801b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	/*
802b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	 * Can't close the main tab
803b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	 */
804b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	ge = get_ge_from_cur_tab(ui);
805b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	if (ge) {
806b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		gtk_widget_destroy(ge->vbox);
807b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		return;
8081252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	}
80916ce5adf97de087c4c5220f6800bf310a3a70045Jens Axboe
810b98ab718031a25ecfd3fa64df3f9992baa83b5acJens Axboe	if (g_hash_table_size(ui->ge_hash)) {
811b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		gfio_report_info(ui, "Error", "The main page view cannot be closed\n");
812b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		return;
81338634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	}
81438634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
815b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gfio_quit(ui);
816b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
8172f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
818b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic void file_add_recent(struct gui *ui, const gchar *uri)
819b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
820b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	GtkRecentData grd;
8212f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
822b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	memset(&grd, 0, sizeof(grd));
823b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	grd.display_name = strdup("gfio");
824b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	grd.description = strdup("Fio job file");
825b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	grd.mime_type = strdup(GFIO_MIME);
826b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	grd.app_name = strdup(g_get_application_name());
827b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	grd.app_exec = strdup("gfio %f/%u");
82885dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe
829b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_recent_manager_add_full(ui->recentmanager, uri, &grd);
830b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
83185dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe
832b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic gchar *get_filename_from_uri(const gchar *uri)
833b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
834b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	if (strncmp(uri, "file://", 7))
835b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		return strdup(uri);
83616ce5adf97de087c4c5220f6800bf310a3a70045Jens Axboe
837b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	return strdup(uri + 7);
838b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
83916ce5adf97de087c4c5220f6800bf310a3a70045Jens Axboe
840b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic int do_file_open(struct gui_entry *ge, const gchar *uri)
841b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
842b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	struct fio_client *client;
843f5c6726e5c9fc0077c3c6d682e5453372942a21eJens Axboe
844b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	assert(!ge->job_file);
84538634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
846b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	ge->job_file = get_filename_from_uri(uri);
84738634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
848b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	client = fio_client_add_explicit(&gfio_client_ops, ge->host, ge->type, ge->port);
849b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	if (client) {
850832fde7966f885a0c975a243596bc5b38a23c38eJens Axboe		char *label = strdup(uri);
851832fde7966f885a0c975a243596bc5b38a23c38eJens Axboe
852832fde7966f885a0c975a243596bc5b38a23c38eJens Axboe		basename(label);
853832fde7966f885a0c975a243596bc5b38a23c38eJens Axboe		gtk_label_set_text(GTK_LABEL(ge->page_label), basename(label));
854832fde7966f885a0c975a243596bc5b38a23c38eJens Axboe		free(label);
855832fde7966f885a0c975a243596bc5b38a23c38eJens Axboe
856b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		gfio_client_added(ge, client);
857b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		file_add_recent(ge->ui, uri);
858b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		return 0;
859b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	}
86038634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
861b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gfio_report_error(ge, "Failed to add client %s\n", ge->host);
862b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	free(ge->host);
863b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	ge->host = NULL;
864b98ab718031a25ecfd3fa64df3f9992baa83b5acJens Axboe	free(ge->job_file);
865b98ab718031a25ecfd3fa64df3f9992baa83b5acJens Axboe	ge->job_file = NULL;
866b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	return 1;
867b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
86838634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
869b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic int do_file_open_with_tab(struct gui *ui, const gchar *uri)
870b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
871b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	struct gui_entry *ge;
872b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gint cur_page;
873b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	int ret, ge_is_new = 0;
8742f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
875b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	/*
876b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	 * Creates new tab if current tab is the main window, or the
877b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	 * current tab already has a client.
878b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	 */
879b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	cur_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(ui->notebook));
880b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	ge = get_ge_from_page(ui, cur_page, &ge_is_new);
881b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	if (ge->client) {
882b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		ge = get_new_ge_with_tab(ui, "Untitled");
883b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		ge_is_new = 1;
88438634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	}
8852f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
886b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_notebook_set_current_page(GTK_NOTEBOOK(ui->notebook), ge->page_num);
887b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
888b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	if (get_connection_details(ge)) {
889b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		if (ge_is_new)
890b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			gtk_widget_destroy(ge->vbox);
8913c3ed070502bbfec387ded2c43d5e4559ca24a63Jens Axboe
892b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		return 1;
893b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	}
894a67909069393f090bb00c0039206bc30830f3427Jens Axboe
895b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	ret = do_file_open(ge, uri);
896a67909069393f090bb00c0039206bc30830f3427Jens Axboe
897b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	if (!ret) {
898b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		if (ge->server_start)
899b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			gfio_start_server(ui);
900b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	} else {
901b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		if (ge_is_new)
902b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe			gtk_widget_destroy(ge->vbox);
903a67909069393f090bb00c0039206bc30830f3427Jens Axboe	}
904a67909069393f090bb00c0039206bc30830f3427Jens Axboe
905b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	return ret;
906b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
907a67909069393f090bb00c0039206bc30830f3427Jens Axboe
908b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic void recent_open(GtkAction *action, gpointer data)
909b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
910b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	struct gui *ui = (struct gui *) data;
911b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	GtkRecentInfo *info;
912b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	const gchar *uri;
9130420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
914b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	info = g_object_get_data(G_OBJECT(action), "gtk-recent-info");
915b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	uri = gtk_recent_info_get_uri(info);
9160420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
917b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	do_file_open_with_tab(ui, uri);
918b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
919a7a42ce19d0f1339ce7d0768683afaa043d5ab36Jens Axboe
920b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic void file_open(GtkWidget *w, gpointer data)
921b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
922b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	struct gui *ui = data;
923b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	GtkWidget *dialog;
924b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	GtkFileFilter *filter;
925b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gchar *filename;
926b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
927b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	dialog = gtk_file_chooser_dialog_new("Open File",
928b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		GTK_WINDOW(ui->window),
929b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		GTK_FILE_CHOOSER_ACTION_OPEN,
930b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
931b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
932b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		NULL);
933b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
934b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
935b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	filter = gtk_file_filter_new();
936b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_file_filter_add_pattern(filter, "*.fio");
937b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_file_filter_add_pattern(filter, "*.job");
938b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_file_filter_add_pattern(filter, "*.ini");
939b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_file_filter_add_mime_type(filter, GFIO_MIME);
940b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_file_filter_set_name(filter, "Fio job file");
941b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
942b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
943b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
944b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		gtk_widget_destroy(dialog);
945b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		return;
9461252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	}
9470420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
948b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
9490420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
950b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_widget_destroy(dialog);
9510420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
952b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	do_file_open_with_tab(ui, filename);
953b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	g_free(filename);
954b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
9550420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
956b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboestatic void file_save(GtkWidget *w, gpointer data)
957b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe{
958b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	struct gui *ui = data;
959b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	GtkWidget *dialog;
9600420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
961b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	dialog = gtk_file_chooser_dialog_new("Save File",
962b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		GTK_WINDOW(ui->window),
963b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		GTK_FILE_CHOOSER_ACTION_SAVE,
964b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
965b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
966b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		NULL);
967b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
968b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
969b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "Untitled document");
970b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
971b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
972b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		char *filename;
973b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe
974b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
975b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		// save_job_file(filename);
976b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe		g_free(filename);
9770420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe	}
978b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe	gtk_widget_destroy(dialog);
979b0500ccb313908b3d01bceaa1b03f91024d9eaecJens Axboe}
9800420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
9819b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboestatic void view_log_destroy(GtkWidget *w, gpointer data)
9829b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe{
9839b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	struct gui *ui = (struct gui *) data;
9849b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe
985f762cef937f69d6a23127baf47f22e8ffaea4c11Jens Axboe	g_object_ref(G_OBJECT(ui->log_tree));
9869b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	gtk_container_remove(GTK_CONTAINER(w), ui->log_tree);
9879b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	gtk_widget_destroy(w);
9884cbe721180807c629dc521e368692025d9cac288Jens Axboe	ui->log_view = NULL;
9899b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe}
9909b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe
9911252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboevoid gfio_view_log(struct gui *ui)
9929b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe{
9934cbe721180807c629dc521e368692025d9cac288Jens Axboe	GtkWidget *win, *scroll, *vbox, *box;
9949b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe
9954cbe721180807c629dc521e368692025d9cac288Jens Axboe	if (ui->log_view)
9964cbe721180807c629dc521e368692025d9cac288Jens Axboe		return;
9974cbe721180807c629dc521e368692025d9cac288Jens Axboe
9984cbe721180807c629dc521e368692025d9cac288Jens Axboe	ui->log_view = win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
9999b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	gtk_window_set_title(GTK_WINDOW(win), "Log");
10004cbe721180807c629dc521e368692025d9cac288Jens Axboe	gtk_window_set_default_size(GTK_WINDOW(win), 700, 500);
10019b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe
10024cbe721180807c629dc521e368692025d9cac288Jens Axboe	scroll = gtk_scrolled_window_new(NULL, NULL);
10034cbe721180807c629dc521e368692025d9cac288Jens Axboe
10044cbe721180807c629dc521e368692025d9cac288Jens Axboe	gtk_container_set_border_width(GTK_CONTAINER(scroll), 5);
10054cbe721180807c629dc521e368692025d9cac288Jens Axboe
10064cbe721180807c629dc521e368692025d9cac288Jens Axboe	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
10074cbe721180807c629dc521e368692025d9cac288Jens Axboe
10084cbe721180807c629dc521e368692025d9cac288Jens Axboe	box = gtk_hbox_new(TRUE, 0);
1009f762cef937f69d6a23127baf47f22e8ffaea4c11Jens Axboe	gtk_box_pack_start(GTK_BOX(box), ui->log_tree, TRUE, TRUE, 0);
10104cbe721180807c629dc521e368692025d9cac288Jens Axboe	g_signal_connect(box, "destroy", G_CALLBACK(view_log_destroy), ui);
10114cbe721180807c629dc521e368692025d9cac288Jens Axboe	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), box);
10124cbe721180807c629dc521e368692025d9cac288Jens Axboe
10134cbe721180807c629dc521e368692025d9cac288Jens Axboe	vbox = gtk_vbox_new(TRUE, 5);
1014f762cef937f69d6a23127baf47f22e8ffaea4c11Jens Axboe	gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 0);
10159b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe
10164cbe721180807c629dc521e368692025d9cac288Jens Axboe	gtk_container_add(GTK_CONTAINER(win), vbox);
10179b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	gtk_widget_show_all(win);
10189b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe}
10199b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe
10201252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboestatic void view_log(GtkWidget *w, gpointer data)
10211252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe{
10221252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	struct gui *ui = (struct gui *) data;
10231252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe
10241252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	gfio_view_log(ui);
10251252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe}
10261252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe
102785dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboestatic void connect_job_entry(GtkWidget *w, gpointer data)
102885dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe{
102985dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	struct gui *ui = (struct gui *) data;
103085dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	struct gui_entry *ge;
10313c3ed070502bbfec387ded2c43d5e4559ca24a63Jens Axboe
103285dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	ge = get_ge_from_cur_tab(ui);
103385dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	if (ge)
103485dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		connect_clicked(w, ge);
103585dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe}
103685dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe
103785dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboestatic void send_job_entry(GtkWidget *w, gpointer data)
103885dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe{
103985dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	struct gui *ui = (struct gui *) data;
104085dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	struct gui_entry *ge;
104185dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe
104285dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	ge = get_ge_from_cur_tab(ui);
104385dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	if (ge)
104485dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		send_clicked(w, ge);
104585dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe}
104685dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe
104785dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboestatic void edit_job_entry(GtkWidget *w, gpointer data)
104816ce5adf97de087c4c5220f6800bf310a3a70045Jens Axboe{
10499af4a24408ea7d4cea084a4fe214b81145cc36acJens Axboe	struct gui *ui = (struct gui *) data;
1050789f4ccdf725e6da8bde98afd004c31e16241cfdJens Axboe	struct gui_entry *ge;
10519af4a24408ea7d4cea084a4fe214b81145cc36acJens Axboe
1052789f4ccdf725e6da8bde98afd004c31e16241cfdJens Axboe	ge = get_ge_from_cur_tab(ui);
1053789f4ccdf725e6da8bde98afd004c31e16241cfdJens Axboe	if (ge && ge->client)
1054cf3d824147fe285bba1c93f341f6e44c34aaccd9Jens Axboe		gopt_get_options_window(ui->window, ge->client);
105516ce5adf97de087c4c5220f6800bf310a3a70045Jens Axboe}
105616ce5adf97de087c4c5220f6800bf310a3a70045Jens Axboe
105785dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboestatic void start_job_entry(GtkWidget *w, gpointer data)
105885dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe{
105985dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	struct gui *ui = (struct gui *) data;
106085dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	struct gui_entry *ge;
106185dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe
106285dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	ge = get_ge_from_cur_tab(ui);
106385dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	if (ge)
106485dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		start_job_clicked(w, ge);
106585dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe}
106685dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe
1067781ccba635f4709bb580b3fac3b28c52a157275cJens Axboestatic void view_results(GtkWidget *w, gpointer data)
1068781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe{
1069781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	struct gui *ui = (struct gui *) data;
1070781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	struct gfio_client *gc;
1071781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	struct gui_entry *ge;
1072781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe
1073781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	ge = get_ge_from_cur_tab(ui);
1074781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	if (!ge)
1075781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe		return;
1076781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe
1077781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	if (ge->results_window)
1078781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe		return;
1079781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe
1080781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	gc = ge->client;
1081781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	if (gc && gc->nr_results)
1082781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe		gfio_display_end_results(gc);
1083781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe}
1084781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe
1085a1e7972d96ce1482aa43c2fcafd81d6c7f3c44d2Jens Axboestatic void __update_graph_settings(struct gfio_graphs *g)
10868577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe{
10878577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe	line_graph_set_data_count_limit(g->iops_graph, gfio_graph_limit);
1088a1e7972d96ce1482aa43c2fcafd81d6c7f3c44d2Jens Axboe	graph_set_font(g->iops_graph, gfio_graph_font);
10898577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe	line_graph_set_data_count_limit(g->bandwidth_graph, gfio_graph_limit);
1090a1e7972d96ce1482aa43c2fcafd81d6c7f3c44d2Jens Axboe	graph_set_font(g->bandwidth_graph, gfio_graph_font);
10918577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe}
10928577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe
1093a1e7972d96ce1482aa43c2fcafd81d6c7f3c44d2Jens Axboestatic void ge_update_settings_fn(gpointer key, gpointer value, gpointer data)
1094b98ab718031a25ecfd3fa64df3f9992baa83b5acJens Axboe{
1095b98ab718031a25ecfd3fa64df3f9992baa83b5acJens Axboe	struct gui_entry *ge = (struct gui_entry *) value;
1096a1e7972d96ce1482aa43c2fcafd81d6c7f3c44d2Jens Axboe	GdkEvent *ev;
1097b98ab718031a25ecfd3fa64df3f9992baa83b5acJens Axboe
1098a1e7972d96ce1482aa43c2fcafd81d6c7f3c44d2Jens Axboe	__update_graph_settings(&ge->graphs);
1099a1e7972d96ce1482aa43c2fcafd81d6c7f3c44d2Jens Axboe
1100a1e7972d96ce1482aa43c2fcafd81d6c7f3c44d2Jens Axboe	ev = gdk_event_new(GDK_EXPOSE);
1101b6ab6a31f82cf498da9da08ce83f7b12160203feJens Axboe	g_signal_emit_by_name(G_OBJECT(ge->graphs.drawing_area), GFIO_DRAW_EVENT, GTK_WIDGET(ge->graphs.drawing_area), ev, &ge->graphs);
1102a1e7972d96ce1482aa43c2fcafd81d6c7f3c44d2Jens Axboe	gdk_event_free(ev);
1103b98ab718031a25ecfd3fa64df3f9992baa83b5acJens Axboe}
1104b98ab718031a25ecfd3fa64df3f9992baa83b5acJens Axboe
11058577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboestatic void update_graph_limits(void)
11068577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe{
1107b98ab718031a25ecfd3fa64df3f9992baa83b5acJens Axboe	struct gui *ui = &main_ui;
1108a1e7972d96ce1482aa43c2fcafd81d6c7f3c44d2Jens Axboe	GdkEvent *ev;
1109a1e7972d96ce1482aa43c2fcafd81d6c7f3c44d2Jens Axboe
1110a1e7972d96ce1482aa43c2fcafd81d6c7f3c44d2Jens Axboe	__update_graph_settings(&ui->graphs);
11118577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe
1112a1e7972d96ce1482aa43c2fcafd81d6c7f3c44d2Jens Axboe	ev = gdk_event_new(GDK_EXPOSE);
1113b6ab6a31f82cf498da9da08ce83f7b12160203feJens Axboe	g_signal_emit_by_name(G_OBJECT(ui->graphs.drawing_area), GFIO_DRAW_EVENT, GTK_WIDGET(ui->graphs.drawing_area), ev, &ui->graphs);
1114a1e7972d96ce1482aa43c2fcafd81d6c7f3c44d2Jens Axboe	gdk_event_free(ev);
11158577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe
1116a1e7972d96ce1482aa43c2fcafd81d6c7f3c44d2Jens Axboe	g_hash_table_foreach(ui->ge_hash, ge_update_settings_fn, NULL);
11178577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe}
11188577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe
111946974a7d2d212a513fcefdb2095126fa249e210cJens Axboestatic void preferences(GtkWidget *w, gpointer data)
112046974a7d2d212a513fcefdb2095126fa249e210cJens Axboe{
1121f3e8440f75f98ced28cdd19ba785718e734cf7c5Jens Axboe	GtkWidget *dialog, *frame, *box, **buttons, *vbox, *font;
11221cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe	GtkWidget *hbox, *spin, *entry, *spin_int;
11236e02ad6c232c326b5fa5b5bc4f1570db22f3999cJens Axboe	struct gui *ui = (struct gui *) data;
112446974a7d2d212a513fcefdb2095126fa249e210cJens Axboe	int i;
112546974a7d2d212a513fcefdb2095126fa249e210cJens Axboe
112646974a7d2d212a513fcefdb2095126fa249e210cJens Axboe	dialog = gtk_dialog_new_with_buttons("Preferences",
11276e02ad6c232c326b5fa5b5bc4f1570db22f3999cJens Axboe		GTK_WINDOW(ui->window),
112846974a7d2d212a513fcefdb2095126fa249e210cJens Axboe		GTK_DIALOG_DESTROY_WITH_PARENT,
112946974a7d2d212a513fcefdb2095126fa249e210cJens Axboe		GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
113046974a7d2d212a513fcefdb2095126fa249e210cJens Axboe		GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
113146974a7d2d212a513fcefdb2095126fa249e210cJens Axboe		NULL);
113246974a7d2d212a513fcefdb2095126fa249e210cJens Axboe
11338577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe	frame = gtk_frame_new("Graphing");
1134f762cef937f69d6a23127baf47f22e8ffaea4c11Jens Axboe	vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
1135f762cef937f69d6a23127baf47f22e8ffaea4c11Jens Axboe	gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
1136f3e8440f75f98ced28cdd19ba785718e734cf7c5Jens Axboe	vbox = gtk_vbox_new(FALSE, 6);
1137f3e8440f75f98ced28cdd19ba785718e734cf7c5Jens Axboe	gtk_container_add(GTK_CONTAINER(frame), vbox);
1138f3e8440f75f98ced28cdd19ba785718e734cf7c5Jens Axboe
11391cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe	hbox = gtk_hbox_new(FALSE, 5);
11401cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
11411cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe	entry = gtk_label_new("Font face to use for graph labels");
11421cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe	gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 5);
11431cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe
1144a1e7972d96ce1482aa43c2fcafd81d6c7f3c44d2Jens Axboe	font = gtk_font_button_new_with_font(gfio_graph_font);
11451cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe	gtk_box_pack_start(GTK_BOX(hbox), font, FALSE, FALSE, 5);
1146f3e8440f75f98ced28cdd19ba785718e734cf7c5Jens Axboe
11478577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe	box = gtk_vbox_new(FALSE, 6);
11488577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe	gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 5);
11498577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe
11508577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe	hbox = gtk_hbox_new(FALSE, 5);
11511cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe	gtk_box_pack_start(GTK_BOX(box), hbox, TRUE, TRUE, 5);
11528577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe	entry = gtk_label_new("Maximum number of data points in graph (seconds)");
11538577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe	gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
11548577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe
1155c05d90567e28705e6ef77591ebc23ad5b7974f68Jens Axboe	spin = create_spinbutton(hbox, 10, 1000000, gfio_graph_limit);
11568577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe
11571cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe	box = gtk_vbox_new(FALSE, 6);
11581cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe	gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 5);
11591cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe
11601cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe	hbox = gtk_hbox_new(FALSE, 5);
11611cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe	gtk_box_pack_start(GTK_BOX(box), hbox, TRUE, TRUE, 5);
11621cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe	entry = gtk_label_new("Client ETA request interval (msec)");
11631cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe	gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
11641cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe
11651cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe	spin_int = create_spinbutton(hbox, 100, 100000, gfio_client_ops.eta_msec);
1166a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe	frame = gtk_frame_new("Debug logging");
1167f762cef937f69d6a23127baf47f22e8ffaea4c11Jens Axboe	vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
1168f762cef937f69d6a23127baf47f22e8ffaea4c11Jens Axboe	gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
1169a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe	vbox = gtk_vbox_new(FALSE, 6);
1170a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe	gtk_container_add(GTK_CONTAINER(frame), vbox);
1171a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe
1172a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe	box = gtk_hbox_new(FALSE, 6);
1173a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe	gtk_container_add(GTK_CONTAINER(vbox), box);
1174a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe
1175a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe	buttons = malloc(sizeof(GtkWidget *) * FD_DEBUG_MAX);
1176a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe
1177a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe	for (i = 0; i < FD_DEBUG_MAX; i++) {
1178a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe		if (i == 7) {
1179a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe			box = gtk_hbox_new(FALSE, 6);
1180a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe			gtk_container_add(GTK_CONTAINER(vbox), box);
1181a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe		}
1182a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe
1183a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe
1184a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe		buttons[i] = gtk_check_button_new_with_label(debug_levels[i].name);
1185a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe		gtk_widget_set_tooltip_text(buttons[i], debug_levels[i].help);
1186a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe		gtk_box_pack_start(GTK_BOX(box), buttons[i], FALSE, FALSE, 6);
1187a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe	}
1188a31d9fa466bfeefb30ff56a3e697779c5079771bJens Axboe
118946974a7d2d212a513fcefdb2095126fa249e210cJens Axboe	gtk_widget_show_all(dialog);
119046974a7d2d212a513fcefdb2095126fa249e210cJens Axboe
119146974a7d2d212a513fcefdb2095126fa249e210cJens Axboe	if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
119246974a7d2d212a513fcefdb2095126fa249e210cJens Axboe		gtk_widget_destroy(dialog);
119346974a7d2d212a513fcefdb2095126fa249e210cJens Axboe		return;
119446974a7d2d212a513fcefdb2095126fa249e210cJens Axboe	}
119546974a7d2d212a513fcefdb2095126fa249e210cJens Axboe
119646974a7d2d212a513fcefdb2095126fa249e210cJens Axboe	for (i = 0; i < FD_DEBUG_MAX; i++) {
119746974a7d2d212a513fcefdb2095126fa249e210cJens Axboe		int set;
119846974a7d2d212a513fcefdb2095126fa249e210cJens Axboe
119946974a7d2d212a513fcefdb2095126fa249e210cJens Axboe		set = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttons[i]));
120046974a7d2d212a513fcefdb2095126fa249e210cJens Axboe		if (set)
120146974a7d2d212a513fcefdb2095126fa249e210cJens Axboe			fio_debug |= (1UL << i);
120246974a7d2d212a513fcefdb2095126fa249e210cJens Axboe	}
120346974a7d2d212a513fcefdb2095126fa249e210cJens Axboe
1204f3e8440f75f98ced28cdd19ba785718e734cf7c5Jens Axboe	gfio_graph_font = strdup(gtk_font_button_get_font_name(GTK_FONT_BUTTON(font)));
12058577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe	gfio_graph_limit = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin));
12068577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe	update_graph_limits();
12071cf6bca564fbcfbbace10abcec78c1f271d98a00Jens Axboe	gfio_client_ops.eta_msec = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_int));
12088577f4fdb30ad26033d6175d66a6edd21c2417c6Jens Axboe
120946974a7d2d212a513fcefdb2095126fa249e210cJens Axboe	gtk_widget_destroy(dialog);
121046974a7d2d212a513fcefdb2095126fa249e210cJens Axboe}
121146974a7d2d212a513fcefdb2095126fa249e210cJens Axboe
12120420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboestatic void about_dialog(GtkWidget *w, gpointer data)
12130420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe{
121481e4ea6eb485b39917a5bbda79d22f54df624838Jens Axboe	const char *authors[] = {
121581e4ea6eb485b39917a5bbda79d22f54df624838Jens Axboe		"Jens Axboe <axboe@kernel.dk>",
121681e4ea6eb485b39917a5bbda79d22f54df624838Jens Axboe		"Stephen Carmeron <stephenmcameron@gmail.com>",
121781e4ea6eb485b39917a5bbda79d22f54df624838Jens Axboe		NULL
121881e4ea6eb485b39917a5bbda79d22f54df624838Jens Axboe	};
121984a72ed32732c7e91e954c2a574d1612240e65efJens Axboe	const char *license[] = {
122084a72ed32732c7e91e954c2a574d1612240e65efJens Axboe		"Fio is free software; you can redistribute it and/or modify "
122184a72ed32732c7e91e954c2a574d1612240e65efJens Axboe		"it under the terms of the GNU General Public License as published by "
122284a72ed32732c7e91e954c2a574d1612240e65efJens Axboe		"the Free Software Foundation; either version 2 of the License, or "
122384a72ed32732c7e91e954c2a574d1612240e65efJens Axboe		"(at your option) any later version.\n",
122484a72ed32732c7e91e954c2a574d1612240e65efJens Axboe		"Fio is distributed in the hope that it will be useful, "
122584a72ed32732c7e91e954c2a574d1612240e65efJens Axboe		"but WITHOUT ANY WARRANTY; without even the implied warranty of "
122684a72ed32732c7e91e954c2a574d1612240e65efJens Axboe		"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the "
122784a72ed32732c7e91e954c2a574d1612240e65efJens Axboe		"GNU General Public License for more details.\n",
122884a72ed32732c7e91e954c2a574d1612240e65efJens Axboe		"You should have received a copy of the GNU General Public License "
122984a72ed32732c7e91e954c2a574d1612240e65efJens Axboe		"along with Fio; if not, write to the Free Software Foundation, Inc., "
123084a72ed32732c7e91e954c2a574d1612240e65efJens Axboe		"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA\n"
123184a72ed32732c7e91e954c2a574d1612240e65efJens Axboe	};
123284a72ed32732c7e91e954c2a574d1612240e65efJens Axboe	char *license_trans;
123384a72ed32732c7e91e954c2a574d1612240e65efJens Axboe
123484a72ed32732c7e91e954c2a574d1612240e65efJens Axboe	license_trans = g_strconcat(license[0], "\n", license[1], "\n",
123584a72ed32732c7e91e954c2a574d1612240e65efJens Axboe				     license[2], "\n", NULL);
123681e4ea6eb485b39917a5bbda79d22f54df624838Jens Axboe
12370420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe	gtk_show_about_dialog(NULL,
12380420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe		"program-name", "gfio",
12390420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe		"comments", "Gtk2 UI for fio",
124084a72ed32732c7e91e954c2a574d1612240e65efJens Axboe		"license", license_trans,
124181e4ea6eb485b39917a5bbda79d22f54df624838Jens Axboe		"website", "http://git.kernel.dk/?p=fio.git;a=summary",
124281e4ea6eb485b39917a5bbda79d22f54df624838Jens Axboe		"authors", authors,
12430420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe		"version", fio_version_string,
124481e4ea6eb485b39917a5bbda79d22f54df624838Jens Axboe		"copyright", "© 2012 Jens Axboe <axboe@kernel.dk>",
12450420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe		"logo-icon-name", "fio",
12460420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe		/* Must be last: */
124781e4ea6eb485b39917a5bbda79d22f54df624838Jens Axboe		"wrap-license", TRUE,
12480420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe		NULL);
124984a72ed32732c7e91e954c2a574d1612240e65efJens Axboe
12502f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	g_free(license_trans);
12510420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe}
12520420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
12530420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboestatic GtkActionEntry menu_items[] = {
125446974a7d2d212a513fcefdb2095126fa249e210cJens Axboe	{ "FileMenuAction", GTK_STOCK_FILE, "File", NULL, NULL, NULL},
12559b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	{ "ViewMenuAction", GTK_STOCK_FILE, "View", NULL, NULL, NULL},
125616ce5adf97de087c4c5220f6800bf310a3a70045Jens Axboe	{ "JobMenuAction", GTK_STOCK_FILE, "Job", NULL, NULL, NULL},
125746974a7d2d212a513fcefdb2095126fa249e210cJens Axboe	{ "HelpMenuAction", GTK_STOCK_HELP, "Help", NULL, NULL, NULL},
12582f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	{ "NewFile", GTK_STOCK_NEW, "New", "<Control>N", NULL, G_CALLBACK(file_new) },
125916ce5adf97de087c4c5220f6800bf310a3a70045Jens Axboe	{ "CloseFile", GTK_STOCK_CLOSE, "Close", "<Control>W", NULL, G_CALLBACK(file_close) },
126046974a7d2d212a513fcefdb2095126fa249e210cJens Axboe	{ "OpenFile", GTK_STOCK_OPEN, NULL,   "<Control>O", NULL, G_CALLBACK(file_open) },
126146974a7d2d212a513fcefdb2095126fa249e210cJens Axboe	{ "SaveFile", GTK_STOCK_SAVE, NULL,   "<Control>S", NULL, G_CALLBACK(file_save) },
126246974a7d2d212a513fcefdb2095126fa249e210cJens Axboe	{ "Preferences", GTK_STOCK_PREFERENCES, NULL, "<Control>p", NULL, G_CALLBACK(preferences) },
12639b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	{ "ViewLog", NULL, "Log", "<Control>l", NULL, G_CALLBACK(view_log) },
1264781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe	{ "ViewResults", NULL, "Results", "<Control>R", NULL, G_CALLBACK(view_results) },
1265bc271d8788ae87d40da5e65c11b4d83c68d8c0e8Jens Axboe	{ "ConnectJob", NULL, "Connect", "<Control>D", NULL, G_CALLBACK(connect_job_entry) },
126685dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	{ "EditJob", NULL, "Edit job", "<Control>E", NULL, G_CALLBACK(edit_job_entry) },
126785dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	{ "SendJob", NULL, "Send job", "<Control>X", NULL, G_CALLBACK(send_job_entry) },
126885dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	{ "StartJob", NULL, "Start job", "<Control>L", NULL, G_CALLBACK(start_job_entry) },
126946974a7d2d212a513fcefdb2095126fa249e210cJens Axboe	{ "Quit", GTK_STOCK_QUIT, NULL,   "<Control>Q", NULL, G_CALLBACK(quit_clicked) },
127046974a7d2d212a513fcefdb2095126fa249e210cJens Axboe	{ "About", GTK_STOCK_ABOUT, NULL,  NULL, NULL, G_CALLBACK(about_dialog) },
12710420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe};
12723e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboestatic gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
12730420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
12740420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboestatic const gchar *ui_string = " \
12750420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe	<ui> \
12760420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe		<menubar name=\"MainMenu\"> \
12770420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe			<menu name=\"FileMenu\" action=\"FileMenuAction\"> \
12782f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe				<menuitem name=\"New\" action=\"NewFile\" /> \
1279bf64138bff75e2a1434d7c4eabcc6ced6d0fb537Jens Axboe				<menuitem name=\"Open\" action=\"OpenFile\" /> \
128016ce5adf97de087c4c5220f6800bf310a3a70045Jens Axboe				<menuitem name=\"Close\" action=\"CloseFile\" /> \
12812f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe				<separator name=\"Separator1\"/> \
12820420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe				<menuitem name=\"Save\" action=\"SaveFile\" /> \
128346974a7d2d212a513fcefdb2095126fa249e210cJens Axboe				<separator name=\"Separator2\"/> \
12842f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe				<menuitem name=\"Preferences\" action=\"Preferences\" /> \
12852f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe				<separator name=\"Separator3\"/> \
1286261f21d0e9a273cea8d0ef2ae7faf78edb95ef62Jens Axboe				<placeholder name=\"FileRecentFiles\"/> \
1287261f21d0e9a273cea8d0ef2ae7faf78edb95ef62Jens Axboe				<separator name=\"Separator4\"/> \
12880420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe				<menuitem name=\"Quit\" action=\"Quit\" /> \
12890420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe			</menu> \
129016ce5adf97de087c4c5220f6800bf310a3a70045Jens Axboe			<menu name=\"JobMenu\" action=\"JobMenuAction\"> \
129185dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe				<menuitem name=\"Connect\" action=\"ConnectJob\" /> \
1292261f21d0e9a273cea8d0ef2ae7faf78edb95ef62Jens Axboe				<separator name=\"Separator5\"/> \
129385dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe				<menuitem name=\"Edit job\" action=\"EditJob\" /> \
129485dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe				<menuitem name=\"Send job\" action=\"SendJob\" /> \
1295261f21d0e9a273cea8d0ef2ae7faf78edb95ef62Jens Axboe				<separator name=\"Separator6\"/> \
129685dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe				<menuitem name=\"Start job\" action=\"StartJob\" /> \
129716ce5adf97de087c4c5220f6800bf310a3a70045Jens Axboe			</menu>\
12989b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe			<menu name=\"ViewMenu\" action=\"ViewMenuAction\"> \
1299781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe				<menuitem name=\"Results\" action=\"ViewResults\" /> \
1300781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe				<separator name=\"Separator7\"/> \
13019b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe				<menuitem name=\"Log\" action=\"ViewLog\" /> \
13029b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe			</menu>\
13030420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe			<menu name=\"Help\" action=\"HelpMenuAction\"> \
13040420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe				<menuitem name=\"About\" action=\"About\" /> \
13050420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe			</menu> \
13060420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe		</menubar> \
13070420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe	</ui> \
13080420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe";
13090420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
13104cbe721180807c629dc521e368692025d9cac288Jens Axboestatic GtkWidget *get_menubar_menu(GtkWidget *window, GtkUIManager *ui_manager,
13114cbe721180807c629dc521e368692025d9cac288Jens Axboe				   struct gui *ui)
13120420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe{
1313ca664f491d0896a8b5a7e2b3a40ef0ea13d6f31cJens Axboe	GtkActionGroup *action_group;
13140420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe	GError *error = 0;
13150420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
13160420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe	action_group = gtk_action_group_new("Menu");
13174cbe721180807c629dc521e368692025d9cac288Jens Axboe	gtk_action_group_add_actions(action_group, menu_items, nmenu_items, ui);
13180420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
13190420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe	gtk_ui_manager_insert_action_group(ui_manager, action_group, 0);
13200420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe	gtk_ui_manager_add_ui_from_string(GTK_UI_MANAGER(ui_manager), ui_string, -1, &error);
13210420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
13220420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe	gtk_window_add_accel_group(GTK_WINDOW(window), gtk_ui_manager_get_accel_group(ui_manager));
132302421e6997342004577a773c36ab11da989d24bdJens Axboe
13240420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe	return gtk_ui_manager_get_widget(ui_manager, "/MainMenu");
13250420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe}
13260420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
13270420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboevoid gfio_ui_setup(GtkSettings *settings, GtkWidget *menubar,
13281252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe		   GtkWidget *vbox, GtkUIManager *ui_manager)
13290420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe{
13301252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
13310420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe}
13320420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
1333c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboestatic void combo_entry_changed(GtkComboBox *box, gpointer data)
1334c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe{
1335c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	struct gui_entry *ge = (struct gui_entry *) data;
1336c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	gint index;
1337c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe
1338c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	index = gtk_combo_box_get_active(box);
1339c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe
1340c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	multitext_set_entry(&ge->eta.iotype, index);
134199d633af3611958ea6217f270677d0a657e4dddcJens Axboe	multitext_set_entry(&ge->eta.bs, index);
1342c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	multitext_set_entry(&ge->eta.ioengine, index);
1343c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	multitext_set_entry(&ge->eta.iodepth, index);
1344c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe}
1345c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe
1346c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboestatic void combo_entry_destroy(GtkWidget *widget, gpointer data)
1347c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe{
1348c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	struct gui_entry *ge = (struct gui_entry *) data;
1349c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe
1350c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	multitext_free(&ge->eta.iotype);
135199d633af3611958ea6217f270677d0a657e4dddcJens Axboe	multitext_free(&ge->eta.bs);
1352c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	multitext_free(&ge->eta.ioengine);
1353c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	multitext_free(&ge->eta.iodepth);
1354c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe}
1355c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe
13562f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboestatic GtkWidget *new_client_page(struct gui_entry *ge)
1357ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron{
13582f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	GtkWidget *main_vbox, *probe, *probe_frame, *probe_box;
1359654763360216552261bf4ca3b674022225468931Jens Axboe	GtkWidget *scrolled_window, *bottom_align, *top_align, *top_vbox;
13600420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
13612f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	main_vbox = gtk_vbox_new(FALSE, 3);
136245032dd83a49ffd76aa5db4c2ef65a832c413c1cStephen M. Cameron
1363654763360216552261bf4ca3b674022225468931Jens Axboe	top_align = gtk_alignment_new(0, 0, 1, 0);
1364654763360216552261bf4ca3b674022225468931Jens Axboe	top_vbox = gtk_vbox_new(FALSE, 3);
1365654763360216552261bf4ca3b674022225468931Jens Axboe	gtk_container_add(GTK_CONTAINER(top_align), top_vbox);
1366654763360216552261bf4ca3b674022225468931Jens Axboe	gtk_box_pack_start(GTK_BOX(main_vbox), top_align, FALSE, FALSE, 0);
13672f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
13682f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	probe = gtk_frame_new("Job");
13692f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_box_pack_start(GTK_BOX(main_vbox), probe, FALSE, FALSE, 3);
13702f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	probe_frame = gtk_vbox_new(FALSE, 3);
13712f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_container_add(GTK_CONTAINER(probe), probe_frame);
13722f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
13732f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	probe_box = gtk_hbox_new(FALSE, 3);
13742f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, FALSE, FALSE, 3);
13752f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	ge->probe.hostname = new_info_label_in_frame(probe_box, "Host");
13762f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	ge->probe.os = new_info_label_in_frame(probe_box, "OS");
13772f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	ge->probe.arch = new_info_label_in_frame(probe_box, "Architecture");
13782f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	ge->probe.fio_ver = new_info_label_in_frame(probe_box, "Fio version");
13792f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
13802f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	probe_box = gtk_hbox_new(FALSE, 3);
13812f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, FALSE, FALSE, 3);
13822f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
13833863d1ad1020200f26958da42ed208f6c5c8f372Jens Axboe	ge->eta.names = new_combo_entry_in_frame(probe_box, "Jobs");
1384c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	g_signal_connect(ge->eta.names, "changed", G_CALLBACK(combo_entry_changed), ge);
1385c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	g_signal_connect(ge->eta.names, "destroy", G_CALLBACK(combo_entry_destroy), ge);
1386c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	ge->eta.iotype.entry = new_info_entry_in_frame(probe_box, "IO");
138799d633af3611958ea6217f270677d0a657e4dddcJens Axboe	ge->eta.bs.entry = new_info_entry_in_frame(probe_box, "Blocksize (Read/Write)");
1388c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	ge->eta.ioengine.entry = new_info_entry_in_frame(probe_box, "IO Engine");
1389c80b74b02babc36441971a2245f41ddcfdb9e08fJens Axboe	ge->eta.iodepth.entry = new_info_entry_in_frame(probe_box, "IO Depth");
13902f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	ge->eta.jobs = new_info_entry_in_frame(probe_box, "Jobs");
13912f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	ge->eta.files = new_info_entry_in_frame(probe_box, "Open files");
13922f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
13932f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	probe_box = gtk_hbox_new(FALSE, 3);
13942f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, FALSE, FALSE, 3);
1395b78ca651a7254f01f5931ff49ca2206dcb42a056Jens Axboe	ge->eta.read_bw = new_info_entry_in_frame_rgb(probe_box, "Read BW", GFIO_READ_R, GFIO_READ_G, GFIO_READ_B);
1396b78ca651a7254f01f5931ff49ca2206dcb42a056Jens Axboe	ge->eta.read_iops = new_info_entry_in_frame_rgb(probe_box, "IOPS", GFIO_READ_R, GFIO_READ_G, GFIO_READ_B);
1397b78ca651a7254f01f5931ff49ca2206dcb42a056Jens Axboe	ge->eta.write_bw = new_info_entry_in_frame_rgb(probe_box, "Write BW", GFIO_WRITE_R, GFIO_WRITE_G, GFIO_WRITE_B);
1398b78ca651a7254f01f5931ff49ca2206dcb42a056Jens Axboe	ge->eta.write_iops = new_info_entry_in_frame_rgb(probe_box, "IOPS", GFIO_WRITE_R, GFIO_WRITE_G, GFIO_WRITE_B);
1399b78ca651a7254f01f5931ff49ca2206dcb42a056Jens Axboe	ge->eta.trim_bw = new_info_entry_in_frame_rgb(probe_box, "Trim BW", GFIO_TRIM_R, GFIO_TRIM_G, GFIO_TRIM_B);
1400b78ca651a7254f01f5931ff49ca2206dcb42a056Jens Axboe	ge->eta.trim_iops = new_info_entry_in_frame_rgb(probe_box, "IOPS", GFIO_TRIM_R, GFIO_TRIM_G, GFIO_TRIM_B);
1401dbc542d442b81ddc58939be96a1c89e9953b9698Jens Axboe
14022f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	/*
14032f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	 * Only add this if we have a commit rate
14042839f0c6d86e99313e1a039293b36aa570db3aceStephen M. Cameron	 */
14052f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe#if 0
14062f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	probe_box = gtk_hbox_new(FALSE, 3);
14072f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
14082839f0c6d86e99313e1a039293b36aa570db3aceStephen M. Cameron
14092f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	ge->eta.cr_bw = new_info_label_in_frame(probe_box, "Commit BW");
14102f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	ge->eta.cr_iops = new_info_label_in_frame(probe_box, "Commit IOPS");
1411ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron
14122f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	ge->eta.cw_bw = new_info_label_in_frame(probe_box, "Commit BW");
14132f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	ge->eta.cw_iops = new_info_label_in_frame(probe_box, "Commit IOPS");
14142f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe#endif
1415ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron
14162f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	/*
14172f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	 * Set up a drawing area and IOPS and bandwidth graphs
14182f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	 */
14192f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	ge->graphs.drawing_area = gtk_drawing_area_new();
14202f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_widget_set_size_request(GTK_WIDGET(ge->graphs.drawing_area),
142157f9d28e010b52fea5f41245e8fcb998367d3bcdStephen M. Cameron		DRAWING_AREA_XDIM, DRAWING_AREA_YDIM);
14222a95f716d8808f45cd5806eac0baad96b39b0016Jens Axboe	gtk_widget_modify_bg(ge->graphs.drawing_area, GTK_STATE_NORMAL, &gfio_color_lightyellow);
1423b6ab6a31f82cf498da9da08ce83f7b12160203feJens Axboe	g_signal_connect(G_OBJECT(ge->graphs.drawing_area), GFIO_DRAW_EVENT,
14242f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe				G_CALLBACK(on_expose_drawing_area), &ge->graphs);
14252f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	g_signal_connect(G_OBJECT(ge->graphs.drawing_area), "configure_event",
14262f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe				G_CALLBACK(on_config_drawing_area), &ge->graphs);
1427654763360216552261bf4ca3b674022225468931Jens Axboe	scrolled_window = gtk_scrolled_window_new(NULL, NULL);
1428654763360216552261bf4ca3b674022225468931Jens Axboe	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
14292f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe					GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1430654763360216552261bf4ca3b674022225468931Jens Axboe	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window),
14312f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe					ge->graphs.drawing_area);
1432654763360216552261bf4ca3b674022225468931Jens Axboe	gtk_box_pack_start(GTK_BOX(main_vbox), scrolled_window, TRUE, TRUE, 0);
143304cc6b77973636a914de3dff8ca6ae0857cf453bStephen M. Cameron
14342f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	setup_graphs(&ge->graphs);
14352f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
14362f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	/*
14373c3ed070502bbfec387ded2c43d5e4559ca24a63Jens Axboe	 * Set up alignments for widgets at the bottom of ui,
14382f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	 * align bottom left, expand horizontally but not vertically
14392f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	 */
1440654763360216552261bf4ca3b674022225468931Jens Axboe	bottom_align = gtk_alignment_new(0, 1, 1, 0);
14412f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	ge->buttonbox = gtk_hbox_new(FALSE, 0);
1442654763360216552261bf4ca3b674022225468931Jens Axboe	gtk_container_add(GTK_CONTAINER(bottom_align), ge->buttonbox);
1443654763360216552261bf4ca3b674022225468931Jens Axboe	gtk_box_pack_start(GTK_BOX(main_vbox), bottom_align, FALSE, FALSE, 0);
14442f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
1445057754389863aa18cbf36b1f2a556a422ea2f4b5Jens Axboe	add_buttons(ge, buttonspeclist, ARRAY_SIZE(buttonspeclist));
14460420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe
144704cc6b77973636a914de3dff8ca6ae0857cf453bStephen M. Cameron	/*
14482f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	 * Set up thread status progress bar
14492f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	 */
14502f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	ge->thread_status_pb = gtk_progress_bar_new();
14512f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ge->thread_status_pb), 0.0);
14522f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ge->thread_status_pb), "No connections");
14532f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_container_add(GTK_CONTAINER(ge->buttonbox), ge->thread_status_pb);
14542f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
14552f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
14562f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	return main_vbox;
14572f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe}
14582f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
14592f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboestatic GtkWidget *new_main_page(struct gui *ui)
14602f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe{
14612f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	GtkWidget *main_vbox, *probe, *probe_frame, *probe_box;
1462654763360216552261bf4ca3b674022225468931Jens Axboe	GtkWidget *scrolled_window, *bottom_align, *top_align, *top_vbox;
14632f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
14642f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	main_vbox = gtk_vbox_new(FALSE, 3);
14652f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
14662f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	/*
14672f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	 * Set up alignments for widgets at the top of ui,
1468c36f98d9487c4b3a9b5c1f77aedb15e674b5a192Stephen M. Cameron	 * align top left, expand horizontally but not vertically
1469c36f98d9487c4b3a9b5c1f77aedb15e674b5a192Stephen M. Cameron	 */
1470654763360216552261bf4ca3b674022225468931Jens Axboe	top_align = gtk_alignment_new(0, 0, 1, 0);
1471654763360216552261bf4ca3b674022225468931Jens Axboe	top_vbox = gtk_vbox_new(FALSE, 0);
1472654763360216552261bf4ca3b674022225468931Jens Axboe	gtk_container_add(GTK_CONTAINER(top_align), top_vbox);
1473654763360216552261bf4ca3b674022225468931Jens Axboe	gtk_box_pack_start(GTK_BOX(main_vbox), top_align, FALSE, FALSE, 0);
1474c36f98d9487c4b3a9b5c1f77aedb15e674b5a192Stephen M. Cameron
14752f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	probe = gtk_frame_new("Run statistics");
14762f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_box_pack_start(GTK_BOX(main_vbox), probe, FALSE, FALSE, 3);
1477843ad23782b4e6061dcc0e14b0fbc5f4fecf55f9Jens Axboe	probe_frame = gtk_vbox_new(FALSE, 3);
1478843ad23782b4e6061dcc0e14b0fbc5f4fecf55f9Jens Axboe	gtk_container_add(GTK_CONTAINER(probe), probe_frame);
1479843ad23782b4e6061dcc0e14b0fbc5f4fecf55f9Jens Axboe
1480843ad23782b4e6061dcc0e14b0fbc5f4fecf55f9Jens Axboe	probe_box = gtk_hbox_new(FALSE, 3);
14812f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, FALSE, FALSE, 3);
14823863d1ad1020200f26958da42ed208f6c5c8f372Jens Axboe	ui->eta.jobs = new_info_entry_in_frame(probe_box, "Running");
1483b78ca651a7254f01f5931ff49ca2206dcb42a056Jens Axboe	ui->eta.read_bw = new_info_entry_in_frame_rgb(probe_box, "Read BW", GFIO_READ_R, GFIO_READ_G, GFIO_READ_B);
1484b78ca651a7254f01f5931ff49ca2206dcb42a056Jens Axboe	ui->eta.read_iops = new_info_entry_in_frame_rgb(probe_box, "IOPS", GFIO_READ_R, GFIO_READ_G, GFIO_READ_B);
1485b78ca651a7254f01f5931ff49ca2206dcb42a056Jens Axboe	ui->eta.write_bw = new_info_entry_in_frame_rgb(probe_box, "Write BW", GFIO_WRITE_R, GFIO_WRITE_G, GFIO_WRITE_B);
1486b78ca651a7254f01f5931ff49ca2206dcb42a056Jens Axboe	ui->eta.write_iops = new_info_entry_in_frame_rgb(probe_box, "IOPS", GFIO_WRITE_R, GFIO_WRITE_G, GFIO_WRITE_B);
1487b78ca651a7254f01f5931ff49ca2206dcb42a056Jens Axboe	ui->eta.trim_bw = new_info_entry_in_frame_rgb(probe_box, "Trim BW", GFIO_TRIM_R, GFIO_TRIM_G, GFIO_TRIM_B);
1488b78ca651a7254f01f5931ff49ca2206dcb42a056Jens Axboe	ui->eta.trim_iops = new_info_entry_in_frame_rgb(probe_box, "IOPS", GFIO_TRIM_R, GFIO_TRIM_G, GFIO_TRIM_B);
14893e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboe
1490807f9971e7bfedfc905d2cb2c38a6e558db2f343Jens Axboe	/*
1491807f9971e7bfedfc905d2cb2c38a6e558db2f343Jens Axboe	 * Only add this if we have a commit rate
1492807f9971e7bfedfc905d2cb2c38a6e558db2f343Jens Axboe	 */
1493807f9971e7bfedfc905d2cb2c38a6e558db2f343Jens Axboe#if 0
14943e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboe	probe_box = gtk_hbox_new(FALSE, 3);
14953e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboe	gtk_box_pack_start(GTK_BOX(probe_frame), probe_box, TRUE, FALSE, 3);
1496807f9971e7bfedfc905d2cb2c38a6e558db2f343Jens Axboe
1497807f9971e7bfedfc905d2cb2c38a6e558db2f343Jens Axboe	ui->eta.cr_bw = new_info_label_in_frame(probe_box, "Commit BW");
1498807f9971e7bfedfc905d2cb2c38a6e558db2f343Jens Axboe	ui->eta.cr_iops = new_info_label_in_frame(probe_box, "Commit IOPS");
1499807f9971e7bfedfc905d2cb2c38a6e558db2f343Jens Axboe
15003e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboe	ui->eta.cw_bw = new_info_label_in_frame(probe_box, "Commit BW");
15013e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboe	ui->eta.cw_iops = new_info_label_in_frame(probe_box, "Commit IOPS");
1502807f9971e7bfedfc905d2cb2c38a6e558db2f343Jens Axboe#endif
15033e47bd250cac5fb81a5c0ad578dfbe90c6ddf6deJens Axboe
150445032dd83a49ffd76aa5db4c2ef65a832c413c1cStephen M. Cameron	/*
15052fd3bb0ecbe17e8168a480cbdb8318b69bf51087Jens Axboe	 * Set up a drawing area and IOPS and bandwidth graphs
1506736f2dff9fa6af83434bc4decafc6d8b40054ca0Stephen M. Cameron	 */
15072f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	ui->graphs.drawing_area = gtk_drawing_area_new();
15082f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_widget_set_size_request(GTK_WIDGET(ui->graphs.drawing_area),
150957f9d28e010b52fea5f41245e8fcb998367d3bcdStephen M. Cameron		DRAWING_AREA_XDIM, DRAWING_AREA_YDIM);
15102a95f716d8808f45cd5806eac0baad96b39b0016Jens Axboe	gtk_widget_modify_bg(ui->graphs.drawing_area, GTK_STATE_NORMAL, &gfio_color_lightyellow);
1511b6ab6a31f82cf498da9da08ce83f7b12160203feJens Axboe	g_signal_connect(G_OBJECT(ui->graphs.drawing_area), GFIO_DRAW_EVENT,
15122f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe			G_CALLBACK(on_expose_drawing_area), &ui->graphs);
15132f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	g_signal_connect(G_OBJECT(ui->graphs.drawing_area), "configure_event",
15142f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe			G_CALLBACK(on_config_drawing_area), &ui->graphs);
1515654763360216552261bf4ca3b674022225468931Jens Axboe	scrolled_window = gtk_scrolled_window_new(NULL, NULL);
1516654763360216552261bf4ca3b674022225468931Jens Axboe	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
1517736f2dff9fa6af83434bc4decafc6d8b40054ca0Stephen M. Cameron					GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1518654763360216552261bf4ca3b674022225468931Jens Axboe	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window),
15192f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe					ui->graphs.drawing_area);
1520654763360216552261bf4ca3b674022225468931Jens Axboe	gtk_box_pack_start(GTK_BOX(main_vbox), scrolled_window,
1521e164534f44e12fec73d418e7f1d9c8b12dee925fStephen M. Cameron			TRUE, TRUE, 0);
1522736f2dff9fa6af83434bc4decafc6d8b40054ca0Stephen M. Cameron
15232f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	setup_graphs(&ui->graphs);
15242fd3bb0ecbe17e8168a480cbdb8318b69bf51087Jens Axboe
1525c36f98d9487c4b3a9b5c1f77aedb15e674b5a192Stephen M. Cameron	/*
15263c3ed070502bbfec387ded2c43d5e4559ca24a63Jens Axboe	 * Set up alignments for widgets at the bottom of ui,
1527c36f98d9487c4b3a9b5c1f77aedb15e674b5a192Stephen M. Cameron	 * align bottom left, expand horizontally but not vertically
1528c36f98d9487c4b3a9b5c1f77aedb15e674b5a192Stephen M. Cameron	 */
1529654763360216552261bf4ca3b674022225468931Jens Axboe	bottom_align = gtk_alignment_new(0, 1, 1, 0);
1530c36f98d9487c4b3a9b5c1f77aedb15e674b5a192Stephen M. Cameron	ui->buttonbox = gtk_hbox_new(FALSE, 0);
1531654763360216552261bf4ca3b674022225468931Jens Axboe	gtk_container_add(GTK_CONTAINER(bottom_align), ui->buttonbox);
1532654763360216552261bf4ca3b674022225468931Jens Axboe	gtk_box_pack_start(GTK_BOX(main_vbox), bottom_align, FALSE, FALSE, 0);
1533c36f98d9487c4b3a9b5c1f77aedb15e674b5a192Stephen M. Cameron
15343ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	/*
15353ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	 * Set up thread status progress bar
15363ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	 */
15373ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	ui->thread_status_pb = gtk_progress_bar_new();
15383ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ui->thread_status_pb), 0.0);
15398663ea652b8ca7a368b39ef97e991180edebb57fJens Axboe	gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ui->thread_status_pb), "No connections");
15403ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe	gtk_container_add(GTK_CONTAINER(ui->buttonbox), ui->thread_status_pb);
15413ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe
15422f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	return main_vbox;
15432f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe}
15442f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
15452f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboestatic gboolean notebook_switch_page(GtkNotebook *notebook, GtkWidget *widget,
15462f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe				     guint page, gpointer data)
15472f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
15482f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe{
154902421e6997342004577a773c36ab11da989d24bdJens Axboe	struct gui *ui = (struct gui *) data;
155085dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	struct gui_entry *ge;
155185dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe
155285dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	if (!page) {
155385dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		set_job_menu_visible(ui, 0);
1554781ccba635f4709bb580b3fac3b28c52a157275cJens Axboe		set_view_results_visible(ui, 0);
155585dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		return TRUE;
155685dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	}
155785dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe
155885dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	set_job_menu_visible(ui, 1);
15596e02ad6c232c326b5fa5b5bc4f1570db22f3999cJens Axboe	ge = get_ge_from_page(ui, page, NULL);
156085dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe	if (ge)
156185dd01e7d7fa9989bf55002bc416c4d8118fdf5fJens Axboe		update_button_states(ui, ge);
156202421e6997342004577a773c36ab11da989d24bdJens Axboe
15632f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	return TRUE;
15642f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe}
15652f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
156638634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboestatic gint compare_recent_items(GtkRecentInfo *a, GtkRecentInfo *b)
156738634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe{
156838634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	time_t time_a = gtk_recent_info_get_visited(a);
156938634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	time_t time_b = gtk_recent_info_get_visited(b);
157038634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
157138634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	return time_b - time_a;
157238634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe}
157338634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
157438634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboestatic void add_recent_file_items(struct gui *ui)
157538634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe{
157638634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	const gchar *gfio = g_get_application_name();
157738634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	GList *items, *item;
157838634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	int i = 0;
157938634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
158038634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	if (ui->recent_ui_id) {
158138634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		gtk_ui_manager_remove_ui(ui->uimanager, ui->recent_ui_id);
158238634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		gtk_ui_manager_ensure_update(ui->uimanager);
158338634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	}
158438634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	ui->recent_ui_id = gtk_ui_manager_new_merge_id(ui->uimanager);
158538634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
158638634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	if (ui->actiongroup) {
158738634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		gtk_ui_manager_remove_action_group(ui->uimanager, ui->actiongroup);
158838634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		g_object_unref(ui->actiongroup);
158938634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	}
159038634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	ui->actiongroup = gtk_action_group_new("RecentFileActions");
159138634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
159238634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	gtk_ui_manager_insert_action_group(ui->uimanager, ui->actiongroup, -1);
159338634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
159438634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	items = gtk_recent_manager_get_items(ui->recentmanager);
159538634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	items = g_list_sort(items, (GCompareFunc) compare_recent_items);
159638634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
159738634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	for (item = items; item && item->data; item = g_list_next(item)) {
159838634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		GtkRecentInfo *info = (GtkRecentInfo *) item->data;
159938634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		gchar *action_name;
160038634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		const gchar *label;
160138634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		GtkAction *action;
160238634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
160338634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		if (!gtk_recent_info_has_application(info, gfio))
160438634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe			continue;
160538634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
160638634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		/*
160738634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		 * We only support local files for now
160838634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		 */
160938634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		if (!gtk_recent_info_is_local(info) || !gtk_recent_info_exists(info))
161038634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe			continue;
161138634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
161238634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		action_name = g_strdup_printf("RecentFile%u", i++);
161338634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		label = gtk_recent_info_get_display_name(info);
161438634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
161538634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		action = g_object_new(GTK_TYPE_ACTION,
161638634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe					"name", action_name,
161738634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe					"label", label, NULL);
161838634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
161938634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		g_object_set_data_full(G_OBJECT(action), "gtk-recent-info",
162038634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe					gtk_recent_info_ref(info),
162138634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe					(GDestroyNotify) gtk_recent_info_unref);
162238634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
162338634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
162438634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		g_signal_connect(action, "activate", G_CALLBACK(recent_open), ui);
162538634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
162638634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		gtk_action_group_add_action(ui->actiongroup, action);
162738634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		g_object_unref(action);
162838634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
162938634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		gtk_ui_manager_add_ui(ui->uimanager, ui->recent_ui_id,
163038634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe					"/MainMenu/FileMenu/FileRecentFiles",
163138634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe					label, action_name,
163238634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe					GTK_UI_MANAGER_MENUITEM, FALSE);
163338634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
163438634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		g_free(action_name);
163538634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
163638634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe		if (i == 8)
163738634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe			break;
163838634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	}
163938634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
164038634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	g_list_foreach(items, (GFunc) gtk_recent_info_unref, NULL);
164138634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	g_list_free(items);
164238634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe}
164338634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
1644a67909069393f090bb00c0039206bc30830f3427Jens Axboestatic void drag_and_drop_received(GtkWidget *widget, GdkDragContext *ctx,
16456e02ad6c232c326b5fa5b5bc4f1570db22f3999cJens Axboe				   gint x, gint y, GtkSelectionData *seldata,
16466e02ad6c232c326b5fa5b5bc4f1570db22f3999cJens Axboe				   guint info, guint time, gpointer *data)
1647a67909069393f090bb00c0039206bc30830f3427Jens Axboe{
16486e02ad6c232c326b5fa5b5bc4f1570db22f3999cJens Axboe	struct gui *ui = (struct gui *) data;
1649a67909069393f090bb00c0039206bc30830f3427Jens Axboe	gchar **uris;
1650a67909069393f090bb00c0039206bc30830f3427Jens Axboe	GtkWidget *source;
1651a67909069393f090bb00c0039206bc30830f3427Jens Axboe
1652a67909069393f090bb00c0039206bc30830f3427Jens Axboe	source = gtk_drag_get_source_widget(ctx);
1653a67909069393f090bb00c0039206bc30830f3427Jens Axboe	if (source && widget == gtk_widget_get_toplevel(source)) {
1654a67909069393f090bb00c0039206bc30830f3427Jens Axboe		gtk_drag_finish(ctx, FALSE, FALSE, time);
1655a67909069393f090bb00c0039206bc30830f3427Jens Axboe		return;
1656a67909069393f090bb00c0039206bc30830f3427Jens Axboe	}
1657a67909069393f090bb00c0039206bc30830f3427Jens Axboe
16586e02ad6c232c326b5fa5b5bc4f1570db22f3999cJens Axboe	uris = gtk_selection_data_get_uris(seldata);
1659a67909069393f090bb00c0039206bc30830f3427Jens Axboe	if (!uris) {
1660a67909069393f090bb00c0039206bc30830f3427Jens Axboe		gtk_drag_finish(ctx, FALSE, FALSE, time);
1661a67909069393f090bb00c0039206bc30830f3427Jens Axboe		return;
1662a67909069393f090bb00c0039206bc30830f3427Jens Axboe	}
1663a67909069393f090bb00c0039206bc30830f3427Jens Axboe
16640cf3ece062d6856bd79b89770780296c99937a98Jens Axboe	if (uris[0])
16650cf3ece062d6856bd79b89770780296c99937a98Jens Axboe		do_file_open_with_tab(ui, uris[0]);
1666a67909069393f090bb00c0039206bc30830f3427Jens Axboe
1667a67909069393f090bb00c0039206bc30830f3427Jens Axboe	gtk_drag_finish(ctx, TRUE, FALSE, time);
1668a67909069393f090bb00c0039206bc30830f3427Jens Axboe	g_strfreev(uris);
1669a67909069393f090bb00c0039206bc30830f3427Jens Axboe}
1670a67909069393f090bb00c0039206bc30830f3427Jens Axboe
16712f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboestatic void init_ui(int *argc, char **argv[], struct gui *ui)
16722f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe{
16732f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	GtkSettings *settings;
167402421e6997342004577a773c36ab11da989d24bdJens Axboe	GtkWidget *vbox;
16752f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
16762f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	/* Magical g*thread incantation, you just need this thread stuff.
16772f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	 * Without it, the update that happens in gfio_update_thread_status
16782f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	 * doesn't really happen in a timely fashion, you need expose events
16792f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	 */
1680b11bd8d8b784feb591b3904ca787c42b3799a8cfJens Axboe#if !GTK_CHECK_VERSION(2, 24, 0)
16812f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	if (!g_thread_supported())
16822f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe		g_thread_init(NULL);
1683b11bd8d8b784feb591b3904ca787c42b3799a8cfJens Axboe#endif
1684b11bd8d8b784feb591b3904ca787c42b3799a8cfJens Axboe
16852f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gdk_threads_init();
16862f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
16872f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_init(argc, argv);
16882f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	settings = gtk_settings_get_default();
16892f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_settings_set_long_property(settings, "gtk_tooltip_timeout", 10, "gfio setting");
16902f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	g_type_init();
16910950e832e5f2ef92fbfad92c8a9d20480e3b13f9Jens Axboe	gdk_color_parse("#fffff4", &gfio_color_lightyellow);
16921252d8f2c1daeb31fdc8c1f63db3ceadf7e20892Jens Axboe	gdk_color_parse("white", &gfio_color_white);
16933c3ed070502bbfec387ded2c43d5e4559ca24a63Jens Axboe
16942f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	ui->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1695814479d5805f49a5c44263c61848874a92dc1cafStephen M. Cameron	gtk_window_set_title(GTK_WINDOW(ui->window), "fio");
16962f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_window_set_default_size(GTK_WINDOW(ui->window), 1024, 768);
16972f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
16986e02ad6c232c326b5fa5b5bc4f1570db22f3999cJens Axboe	g_signal_connect(ui->window, "delete-event", G_CALLBACK(quit_clicked), ui);
16996e02ad6c232c326b5fa5b5bc4f1570db22f3999cJens Axboe	g_signal_connect(ui->window, "destroy", G_CALLBACK(quit_clicked), ui);
17002f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
17012f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	ui->vbox = gtk_vbox_new(FALSE, 0);
17022f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_container_add(GTK_CONTAINER(ui->window), ui->vbox);
17032f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
170402421e6997342004577a773c36ab11da989d24bdJens Axboe	ui->uimanager = gtk_ui_manager_new();
170502421e6997342004577a773c36ab11da989d24bdJens Axboe	ui->menu = get_menubar_menu(ui->window, ui->uimanager, ui);
170602421e6997342004577a773c36ab11da989d24bdJens Axboe	gfio_ui_setup(settings, ui->menu, ui->vbox, ui->uimanager);
17072f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
170838634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	ui->recentmanager = gtk_recent_manager_get_default();
170938634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe	add_recent_file_items(ui);
171038634cb19ddc5576b6e96a30fd6c444082e93501Jens Axboe
17112f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	ui->notebook = gtk_notebook_new();
17122f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	g_signal_connect(ui->notebook, "switch-page", G_CALLBACK(notebook_switch_page), ui);
1713b870c31b30e5b07e19e7e8de4cc750c7eae455edJens Axboe	gtk_notebook_set_scrollable(GTK_NOTEBOOK(ui->notebook), 1);
17140aa928c49991d100f28aa75116be0036c90ebaa4Jens Axboe	gtk_notebook_popup_enable(GTK_NOTEBOOK(ui->notebook));
17152f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_container_add(GTK_CONTAINER(ui->vbox), ui->notebook);
17162f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
17172f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	vbox = new_main_page(ui);
17180cf3ece062d6856bd79b89770780296c99937a98Jens Axboe	gtk_drag_dest_set(GTK_WIDGET(ui->window), GTK_DEST_DEFAULT_ALL, NULL, 1, GDK_ACTION_COPY);
1719a67909069393f090bb00c0039206bc30830f3427Jens Axboe	gtk_drag_dest_add_uri_targets(GTK_WIDGET(ui->window));
1720a67909069393f090bb00c0039206bc30830f3427Jens Axboe	g_signal_connect(ui->window, "drag-data-received", G_CALLBACK(drag_and_drop_received), ui);
17212f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
17222f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	gtk_notebook_append_page(GTK_NOTEBOOK(ui->notebook), vbox, gtk_label_new("Main"));
17232f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
17249b260bdfc79dfc55855ffddce15ac1ca7025376fJens Axboe	gfio_ui_setup_log(ui);
17253ec62ec45ce971b76dd3029412dfd3d0c6221384Jens Axboe
1726ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron	gtk_widget_show_all(ui->window);
1727ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron}
1728ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron
17298232e2855c87697a95d00d920d1fd11b30d0fcaaStephen M. Cameronint main(int argc, char *argv[], char *envp[])
1730ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron{
17318232e2855c87697a95d00d920d1fd11b30d0fcaaStephen M. Cameron	if (initialize_fio(envp))
17328232e2855c87697a95d00d920d1fd11b30d0fcaaStephen M. Cameron		return 1;
17330420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe	if (fio_init_options())
17340420ba6a85617cb02e196ac92e519191dafc6c52Jens Axboe		return 1;
1735a182020749dc65b8f96f799fd9ee13df41ada359Stephen M. Cameron
1736753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe	gopt_init();
1737753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe
17382f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	memset(&main_ui, 0, sizeof(main_ui));
1739b98ab718031a25ecfd3fa64df3f9992baa83b5acJens Axboe	main_ui.ge_hash = g_hash_table_new(g_int_hash, g_int_equal);
17402f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe
17412f99deb0895b2d0b618e6e72c74add7192b4d73fJens Axboe	init_ui(&argc, &argv, &main_ui);
17425b7573ab40a30b389602d4b0ec3805957b483a19Stephen M. Cameron
17432839f0c6d86e99313e1a039293b36aa570db3aceStephen M. Cameron	gdk_threads_enter();
1744ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron	gtk_main();
17452839f0c6d86e99313e1a039293b36aa570db3aceStephen M. Cameron	gdk_threads_leave();
1746b98ab718031a25ecfd3fa64df3f9992baa83b5acJens Axboe
1747b98ab718031a25ecfd3fa64df3f9992baa83b5acJens Axboe	g_hash_table_destroy(main_ui.ge_hash);
1748753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe
1749753e9e642f1cf7aa6e46a31aeebc65da26c8bf2eJens Axboe	gopt_exit();
1750ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron	return 0;
1751ff1f3280ded10c6844c07f0e466ca02224e48b62Stephen M. Cameron}
1752