Browse Source

Merge starpu-top branch into trunk

Samuel Thibault 14 years ago
parent
commit
cf42bcf4a1
100 changed files with 18313 additions and 102 deletions
  1. 13 1
      Makefile.am
  2. 48 0
      configure.ac
  3. 9 0
      examples/Makefile.am
  4. 10 0
      examples/stencil/stencil-kernels.c
  5. 11 1
      examples/stencil/stencil.c
  6. 4 0
      examples/stencil/stencil.h
  7. 220 0
      examples/top/hello_world_top.c
  8. 271 0
      include/starpu_top.h
  9. 8 2
      src/Makefile.am
  10. 2 1
      src/core/jobs.c
  11. 3 36
      src/drivers/cpu/driver_cpu.c
  12. 3 26
      src/drivers/cuda/driver_cuda.c
  13. 62 1
      src/drivers/driver_common/driver_common.c
  14. 4 3
      src/drivers/driver_common/driver_common.h
  15. 3 31
      src/drivers/opencl/driver_opencl.c
  16. 26 0
      src/sched_policies/heft.c
  17. 756 0
      src/top/starpu_top.c
  18. 158 0
      src/top/starputop_connection.c
  19. 44 0
      src/top/starputop_connection.h
  20. 109 0
      src/top/starputop_message_queue.c
  21. 49 0
      src/top/starputop_message_queue.h
  22. 97 0
      src/top/starputop_task.c
  23. 11 0
      starpu-top/README
  24. 54 0
      starpu-top/StarPU-Top-common.pri
  25. 85 0
      starpu-top/StarPU-Top-qwt-embed.pri
  26. 2 0
      starpu-top/StarPU-Top-qwt-system.pri
  27. 2 0
      starpu-top/StarPU-Top.pro.in
  28. 113 0
      starpu-top/StarPU-Top.pro.user
  29. 251 0
      starpu-top/StarPU-Top.pro.user.1.3
  30. 9 0
      starpu-top/TODO.txt
  31. 44 0
      starpu-top/aboutdialog.cpp
  32. 47 0
      starpu-top/aboutdialog.h
  33. 186 0
      starpu-top/aboutdialog.ui
  34. 155 0
      starpu-top/abstractwidgetwindow.cpp
  35. 81 0
      starpu-top/abstractwidgetwindow.h
  36. 1573 0
      starpu-top/communicationmanager.cpp
  37. 152 0
      starpu-top/communicationmanager.h
  38. 281 0
      starpu-top/communicationthread.cpp
  39. 72 0
      starpu-top/communicationthread.h
  40. 114 0
      starpu-top/configurationmanager.cpp
  41. 63 0
      starpu-top/configurationmanager.h
  42. 397 0
      starpu-top/dataaggregatorwidget.cpp
  43. 89 0
      starpu-top/dataaggregatorwidget.h
  44. 445 0
      starpu-top/datawidget.cpp
  45. 86 0
      starpu-top/datawidget.h
  46. 67 0
      starpu-top/debugconsole.cpp
  47. 61 0
      starpu-top/debugconsole.h
  48. 41 0
      starpu-top/debugconsole.ui
  49. 884 0
      starpu-top/ganttwidget.cpp
  50. 103 0
      starpu-top/ganttwidget.h
  51. BIN
      starpu-top/images/about.png
  52. BIN
      starpu-top/images/add.png
  53. BIN
      starpu-top/images/connect.png
  54. BIN
      starpu-top/images/debugoff.png
  55. BIN
      starpu-top/images/debugon.png
  56. BIN
      starpu-top/images/help.png
  57. BIN
      starpu-top/images/inside.png
  58. BIN
      starpu-top/images/lock.png
  59. BIN
      starpu-top/images/outside.png
  60. BIN
      starpu-top/images/play.png
  61. BIN
      starpu-top/images/preferences.png
  62. BIN
      starpu-top/images/quit.png
  63. BIN
      starpu-top/images/remove.png
  64. BIN
      starpu-top/images/starputop.png
  65. BIN
      starpu-top/images/widget.png
  66. BIN
      starpu-top/images/windows.png
  67. 625 0
      starpu-top/interactivewidget.cpp
  68. 97 0
      starpu-top/interactivewidget.h
  69. 43 0
      starpu-top/main.cpp
  70. 1527 0
      starpu-top/mainwindow.cpp
  71. 290 0
      starpu-top/mainwindow.h
  72. 198 0
      starpu-top/mainwindow.ui
  73. 486 0
      starpu-top/preferencesdialog.cpp
  74. 100 0
      starpu-top/preferencesdialog.h
  75. 268 0
      starpu-top/preferencesdialog.ui
  76. 91 0
      starpu-top/qledindicator/qledindicator.cpp
  77. 83 0
      starpu-top/qledindicator/qledindicator.h
  78. 310 0
      starpu-top/qwt/qwt_abstract_scale.cpp
  79. 70 0
      starpu-top/qwt/qwt_abstract_scale.h
  80. 402 0
      starpu-top/qwt/qwt_abstract_scale_draw.cpp
  81. 136 0
      starpu-top/qwt/qwt_abstract_scale_draw.h
  82. 596 0
      starpu-top/qwt/qwt_abstract_slider.cpp
  83. 189 0
      starpu-top/qwt/qwt_abstract_slider.h
  84. 486 0
      starpu-top/qwt/qwt_clipper.cpp
  85. 35 0
      starpu-top/qwt/qwt_clipper.h
  86. 442 0
      starpu-top/qwt/qwt_color_map.cpp
  87. 197 0
      starpu-top/qwt/qwt_color_map.h
  88. 405 0
      starpu-top/qwt/qwt_curve_fitter.cpp
  89. 130 0
      starpu-top/qwt/qwt_curve_fitter.h
  90. 1189 0
      starpu-top/qwt/qwt_dial.cpp
  91. 223 0
      starpu-top/qwt/qwt_dial.h
  92. 605 0
      starpu-top/qwt/qwt_dial_needle.cpp
  93. 196 0
      starpu-top/qwt/qwt_dial_needle.h
  94. 394 0
      starpu-top/qwt/qwt_double_range.cpp
  95. 88 0
      starpu-top/qwt/qwt_double_range.h
  96. 571 0
      starpu-top/qwt/qwt_dyngrid_layout.cpp
  97. 83 0
      starpu-top/qwt/qwt_dyngrid_layout.h
  98. 46 0
      starpu-top/qwt/qwt_global.h
  99. 334 0
      starpu-top/qwt/qwt_interval.cpp
  100. 0 0
      starpu-top/qwt/qwt_interval.h

+ 13 - 1
Makefile.am

@@ -49,7 +49,19 @@ include_HEADERS = 				\
 	include/starpu_expert.h			\
 	include/starpu_profiling.h		\
 	include/starpu_bound.h			\
-	include/starpu_scheduler.h
+	include/starpu_scheduler.h		\
+	include/starpu_top.h
+
+if BUILD_STARPU_TOP
+all-local:
+	cd starpu-top ; $(QMAKE) ; $(MAKE)
+clean-local:
+	cd starpu-top ; $(MAKE) clean
+# TODO: resources
+install-exec-local:
+	$(MKDIR_P) $(DESTDIR)$(bindir)
+	$(INSTALL_STRIP_PROGRAM) starpu-top/StarPU-Top $(DESTDIR)$(bindir)
+endif
 
 if STARPU_HAVE_WINDOWS
 txtdir = ${prefix}

+ 48 - 0
configure.ac

@@ -979,6 +979,53 @@ fi
 
 ###############################################################################
 #                                                                             #
+#                               StarPU-Top                                    #
+#                                                                             #
+###############################################################################
+
+build_starpu_top=no
+AC_PATH_PROGS([QMAKE], [qmake-qt4 qmake], [not-found])
+if test x$QMAKE != xnot-found; then
+	QMAKE_VERSION=`$QMAKE --version 2>&1 | head -n 1 | cut -d '.' -f 1 | cut -d ' ' -f 3`
+	if test $QMAKE_VERSION -ge 2 ; then
+		PKG_CHECK_EXISTS([QtGui QtNetwork QtOpenGL QtSql], [
+			QT_MAJVERSION=`$PKG_CONFIG --modversion QtGui | cut -d '.' -f 1`
+			QT_MINVERSION=`$PKG_CONFIG --modversion QtGui | cut -d '.' -f 2`
+			if test $QT_MAJVERSION -gt 4 -o \( $QT_MAJVERSION -eq 4 -a $QT_MINVERSION -ge 7 \) ; then
+				build_starpu_top=yes
+			fi
+			QWT_PRI=embed
+			AC_ARG_WITH(qwt-include-dir,
+				[AS_HELP_STRING([--with-qwt-include-dir=<path>],
+				[specify installed libqwt include path])],
+				[
+					STARPU_QWT_CPPFLAGS="-I$withval"
+					AC_SUBST(STARPU_QWT_CPPFLAGS)
+					QWT_PRI=system
+				])
+			AC_ARG_WITH(qwt-lib-dir,
+				[AS_HELP_STRING([--with-qwt-lib-dir=<path>],
+				[specify installed libqwt library path])],
+				[
+					STARPU_QWT_LDFLAGS="-L$withval"
+					QWT_PRI=system
+				])
+			AC_ARG_WITH(qwt-lib,
+				[AS_HELP_STRING([--with-qwt-lib=<path>],
+				[specify installed libqwt library name])],
+				[
+					STARPU_QWT_LDFLAGS="${STARPU_QWT_LDFLAGS} -l$withval"
+					QWT_PRI=system
+				])
+			AC_SUBST(QWT_PRI)
+		])
+	fi
+fi
+
+AM_CONDITIONAL(BUILD_STARPU_TOP, test x$build_starpu_top = xyes)
+
+###############################################################################
+#                                                                             #
 #                           Flags for C Compiler                              #
 #                                                                             #
 ###############################################################################
@@ -1289,6 +1336,7 @@ AC_OUTPUT([
         tests/opt/Makefile
 	doc/Makefile
 	mpi/Makefile
+	starpu-top/StarPU-Top.pro
 ])
 
 AC_MSG_NOTICE([

+ 9 - 0
examples/Makefile.am

@@ -567,3 +567,12 @@ mandelbrot_mandelbrot_CPPFLAGS += $(X_CFLAGS)
 mandelbrot_mandelbrot_LDADD = $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS)
 endif
 
+################
+# Top Examples #
+################
+
+examplebin_PROGRAMS +=				\
+	top/hello_world_top
+
+top_hello_world_top_SOURCES =			\
+	top/hello_world_top.c

+ 10 - 0
examples/stencil/stencil-kernels.c

@@ -124,6 +124,9 @@ int *who_runs_what;
 int *who_runs_what_index;
 struct timeval *last_tick;
 
+/* Achieved iterations */
+static int achieved_iter;
+
 /* Record how many updates each worker performed */
 unsigned update_per_worker[STARPU_NMAXWORKERS];
 
@@ -259,6 +262,8 @@ fprintf(stderr,"!!! DO update_func_cuda z %d CUDA%d !!!\n", block->bz, workerid)
 	if ((cures = cudaStreamSynchronize(starpu_cuda_get_local_stream())) != cudaSuccess)
 		STARPU_CUDA_REPORT_ERROR(cures);
 
+	if (block->bz == 0)
+		starputop_update_data_integer(starputop_achieved_loop, ++achieved_iter);
 }
 #endif /* STARPU_USE_CUDA */
 
@@ -350,6 +355,8 @@ fprintf(stderr,"!!! DO update_func_opencl z %d OPENCL%d !!!\n", block->bz, worke
 	if ((err = clFinish(cq)))
 		STARPU_OPENCL_REPORT_ERROR(err);
 
+	if (block->bz == 0)
+		starputop_update_data_integer(starputop_achieved_loop, ++achieved_iter);
 }
 #endif /* STARPU_USE_OPENCL */
 
@@ -422,6 +429,9 @@ fprintf(stderr,"!!! DO update_func_cpu z %d CPU%d !!!\n", block->bz, workerid);
 		memcpy(new, old, oldb->nx * oldb->ny * oldb->nz * sizeof(*new));
 #endif /* LIFE */
 	}
+
+	if (block->bz == 0)
+		starputop_update_data_integer(starputop_achieved_loop, ++achieved_iter);
 }
 
 /* Performance model and codelet structure */

+ 11 - 1
examples/stencil/stencil.c

@@ -1,7 +1,7 @@
 /* StarPU --- Runtime system for heterogeneous multicore architectures.
  *
  * Copyright (C) 2010  Centre National de la Recherche Scientifique
- * Copyright (C) 2010  Université de Bordeaux 1
+ * Copyright (C) 2010-2011  Université de Bordeaux 1
  *
  * StarPU is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
@@ -36,6 +36,10 @@ static unsigned sizez = 64*SIZE;
 /* Number of blocks (scattered over the different MPI processes) */
 unsigned nbz = 64;
 
+/* StarPU top variables */
+starputop_data* starputop_init_loop;
+starputop_data* starputop_achieved_loop;
+
 /*
  *	Initialization
  */
@@ -109,6 +113,12 @@ static void parse_args(int argc, char **argv)
 static void init_problem(int argc, char **argv, int rank, int world_size)
 {
 	parse_args(argc, argv);
+
+	if (getenv("STARPU_TOP")) {
+		starputop_init_loop = starputop_add_data_integer("Task creation iter", 0, niter, 1);
+		starputop_achieved_loop = starputop_add_data_integer("Task achieved iter", 0, niter, 1);
+		starputop_init_and_wait("stencil_top example");
+	}
 	create_blocks_array(sizex, sizey, sizez, nbz);
 
 	/* Select the MPI process which should compute the different blocks */

+ 4 - 0
examples/stencil/stencil.h

@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <starpu.h>
+#include <starpu_top.h>
 #ifdef STARPU_USE_CUDA
 #include <starpu_cuda.h>
 #endif
@@ -44,6 +45,9 @@ extern void life_update(int bz, const TYPE *old, TYPE *newp, int nx, int ny, int
 #define K	1
 
 #define NDIRS 2
+extern starputop_data* starputop_init_loop;
+extern starputop_data* starputop_achieved_loop;
+
 
 /* Split only on the z axis to make things simple */
 typedef enum {

+ 220 - 0
examples/top/hello_world_top.c

@@ -0,0 +1,220 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2010  Université de Bordeaux 1
+ * Copyright (C) 2010  Centre National de la Recherche Scientifique
+ *
+ * StarPU is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * StarPU is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+/*
+ * This examples demonstrates how to construct and submit a task to StarPU and
+ * more precisely:
+ *  - how to allocate a new task structure (starpu_task_create)
+ *  - how to describe a multi-versionned computational kernel (ie. a codelet) 
+ *  - how to pass an argument to the codelet (task->cl_arg)
+ *  - how to declare a callback function that is called once the task has been
+ *    executed
+ *  - how to specify if starpu_task_submit is a blocking or non-blocking
+ *    operation (task->synchronous)
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <starpu.h>
+#include <starpu_top.h>
+#include <stdlib.h>
+#include <time.h>
+
+/* Example of enum param */
+char* names[] = {"Paul", "Jean", "Jaques", "Alain", "Brian"};
+int names_len = 5;
+int name_selected=2; //must be between 0 and names_len-1
+/* Exemple of int param */
+int number_of_addition = 30;
+/* Exemple of bool param */
+int stop_after_5_task = 0;
+
+/* When the task is done, task->callback_func(task->callback_arg) is called. Any
+ * callback function must have the prototype void (*)(void *).
+ * NB: Callback are NOT allowed to perform potentially blocking operations */
+void callback_func(void *callback_arg)
+{
+	printf("Callback function got argument %p\n", callback_arg);
+}
+
+/* Every implementation of a codelet must have this prototype, the first
+ * argument (buffers) describes the buffers/streams that are managed by the
+ * DSM; the second arguments references read-only data that is passed as an
+ * argument of the codelet (task->cl_arg). Here, "buffers" is unused as there
+ * are no data input/output managed by the DSM (cl.nbuffers = 0) */
+struct params {
+	int i;
+	float f;
+};
+void cpu_func(void *buffers[], void *cl_arg)
+{
+	struct params *params = cl_arg;
+
+	//loosing time for top example...
+	int sum = 0;
+	int i = 0;
+	while(i<number_of_addition*1000000)
+	{
+		sum+=rand();
+		i++;
+	}
+	
+	printf("Hello %s (params = {%i, %f} ) sum=%d\n",
+			names[name_selected],
+			params->i,
+			params->f,
+			sum);
+}
+
+void callback_name_changed(starputop_param* param)
+{
+	char* message = malloc(256);
+	sprintf(message, "Name have been changed to %s", names[name_selected]);
+	starputop_debug_log(message);
+}
+
+void callback_number_addition_changed(starputop_param* param)
+{
+	char* message = malloc(256);
+	sprintf(message, "Number of addition is now %d", number_of_addition);
+
+	starputop_debug_log(message);
+}
+
+starpu_codelet cl =
+{
+	/* this codelet may only be executed on a CPU, and its cpu
+ 	 * implementation is function "cpu_func" */
+	.where = STARPU_CPU,
+	.cpu_func = cpu_func,
+	/* the codelet does not manipulate any data that is managed
+	 * by our DSM */
+	.nbuffers = 0
+};
+
+int main(int argc, char **argv)
+{
+	srand ( time(NULL) );
+	/* initialize StarPU : passing a NULL argument means that we use
+ 	* default configuration for the scheduling policies and the number of
+	* processors/accelerators */
+	starpu_init(NULL);
+	
+	
+	/*init starputop*/
+	starputop_data * loop_count =
+			starputop_add_data_integer("Loop count", 0,124,1);
+	starputop_data * remain_count = 
+			starputop_add_data_integer("Remaining loop", 0,124,1);
+	starputop_data * midle_reach = 
+			starputop_add_data_boolean("Midle reached", 1);
+	starputop_param* name = 
+			starputop_register_parameter_enum("Your name : ",
+											&name_selected,
+											names,
+											names_len,
+											callback_name_changed);
+	starputop_param * number_of_addition_param = 
+			starputop_register_parameter_integer(
+									"Number of Millions of addition", 
+									&number_of_addition, 
+									0,
+									50, 
+									callback_number_addition_changed);
+	starputop_param * stop5_param = 
+			starputop_register_parameter_boolean("Stop after 5 task ?", 
+												&stop_after_5_task,
+												NULL);
+
+
+	//all parameters are initialized, we can connect to UI
+	starputop_init_and_wait("Serveur de test HelloWorld");
+	
+	//set "default value"
+	starputop_update_data_boolean(midle_reach, 0);
+	
+	
+	/* create a new task that is non-blocking by default : the task is not
+	 * submitted to the scheduler until the starpu_task_submit function is
+	 * called */
+
+	/*
+	 * For this simple example, we make 124 iter
+	*/
+	struct starpu_task *task[124];
+	int i;
+	for(i=0; i<124; i++)
+	{
+		starputop_update_data_integer(loop_count, i);
+		starputop_update_data_integer(remain_count, 124-i);
+		if(i==62)
+		{
+			starputop_update_data_boolean(midle_reach, 1);
+		}
+		if(i==25)
+		{
+			//changing name
+			name_selected = 1;
+			starputop_update_parameter(name);
+		}
+		if(i>4 && stop_after_5_task)
+		{
+			break;
+		}
+		
+		task[i]=starpu_task_create();
+
+		/* the task uses codelet "cl" */
+		task[i]->cl = &cl;
+		
+		/* It is possible to pass buffers that are not managed by the DSM to the
+		 * kernels: the second argument of the "cpu_func" function is a pointer to a
+		 * buffer that contains information for the codelet (cl_arg stands for
+		 * codelet argument). In the case of accelerators, it is possible that
+		 * the codelet is given a pointer to a copy of that buffer: this buffer
+		 * is read-only so that any modification is not passed to other copies
+		 * of the buffer.  For this reason, a buffer passed as a codelet
+		 * argument (cl_arg) is NOT a valid synchronization medium! */
+		struct params params = { i, 2.0f };
+		task[i]->cl_arg = &params;
+		task[i]->cl_arg_size = sizeof(params);
+			
+		/* once the task has been executed, callback_func(0x42)
+		 * will be called on a CPU */
+		task[i]->callback_func = callback_func;
+		task[i]->callback_arg = (void*) (uintptr_t) 0x42;
+
+		/* starpu_task_submit will be a blocking call */
+		task[i]->synchronous = 1;
+		
+		/* submit the task to StarPU */
+		if(number_of_addition==42)
+			starputop_debug_lock("debug stop point because of 42 !");
+		
+		starpu_task_submit(task[i]);
+	}
+	/* terminate StarPU: statistics and other debug outputs are not
+	 * guaranteed to be generated unless this function is called. Once it
+	 * is called, it is not possible to submit tasks anymore, and the user
+	 * is responsible for making sure all tasks have already been executed:
+	 * calling starpu_shutdown() before the termination of all the tasks
+	 * results in an undefined behaviour */
+
+	starpu_shutdown();
+	
+	return 0;
+}

+ 271 - 0
include/starpu_top.h

@@ -0,0 +1,271 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2011 William Braik, Yann Courtois, Jean-Marie Couteyen, Anthony
+ * Roy
+ *
+ * StarPU is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * StarPU is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+#ifndef __STARPU_TOP_H__
+#define __STARPU_TOP_H__
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <starpu.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ 
+typedef enum
+{
+	STARPUTOP_DATA_BOOLEAN,
+	STARPUTOP_DATA_INTEGER,
+	STARPUTOP_DATA_FLOAT
+} starputop_data_type;
+
+typedef struct starputop_data_t
+{
+	unsigned int id;
+	const char* name;
+	int int_min_value;
+	int int_max_value;
+	double double_min_value;
+	double double_max_value;
+	int active;
+	starputop_data_type type;
+	struct starputop_data_t * next;
+} starputop_data;
+
+typedef enum
+{
+	STARPUTOP_PARAM_BOOLEAN,
+	STARPUTOP_PARAM_INTEGER,
+	STARPUTOP_PARAM_FLOAT,
+	STARPUTOP_PARAM_ENUM
+} starputop_param_type;
+
+typedef struct starputop_param_t
+{
+	unsigned int id;
+	const char* name;
+	starputop_param_type type;
+	void* value;
+	char** enum_values; /* only for enum type can be NULL */
+	int nb_values;
+	void (*callback)(struct starputop_param_t*);
+	int int_min_value; /* only for integer type */
+	int int_max_value;
+	double double_min_value; /*only for double type */
+	double double_max_value;
+	struct starputop_param_t * next;
+} starputop_param;
+
+typedef enum
+{
+	TOP_TYPE_GO,
+	TOP_TYPE_SET,
+	TOP_TYPE_CONTINUE,
+	TOP_TYPE_ENABLE,
+	TOP_TYPE_DISABLE,
+	TOP_TYPE_DEBUG,
+	TOP_TYPE_UNKNOW	
+} starputop_message_type;
+
+
+/* 
+ * This function returns 1 if starpu_top is initialized. 0 otherwise.
+ */
+int starpu_top_status_get();
+
+/*
+ * Convert timespec to ms
+ */
+unsigned long long starpu_timing_timespec_to_ms(const struct timespec *ts);
+
+/*****************************************************
+****   Functions to call BEFORE initialisation   *****
+*****************************************************/
+/*
+ * This fonction register a data named data_name of type boolean
+ * If active=0, the value will NOT be displayed to user by default.
+ * Any other value will make the value displayed by default.
+*/
+starputop_data * starputop_add_data_boolean(
+			const char* data_name,
+			int active);
+/*
+ * This fonction register a data named data_name of type integer
+ * The minimum and maximum value will be usefull to define the scale in UI
+ * If active=0, the value will NOT be displayed to user by default.
+ * Any other value will make the value displayed by default.
+*/
+starputop_data * starputop_add_data_integer(
+			const char* data_name, 
+			int minimum_value, 
+			int maximum_value, 
+			int active);
+/*
+ * This fonction register a data named data_name of type float
+ * The minimum and maximum value will be usefull to define the scale in UI
+ * If active=0, the value will NOT be displayed to user by default.
+ * Any other value will make the value displayed by default.
+*/
+starputop_data* starputop_add_data_float(const char* data_name, 
+			double minimum_value, 
+			double maximum_value, 
+			int active);
+
+/*
+ * This fonction register a parameter named parameter_name, of type boolean.
+ * The callback fonction will be called when the parameter is modified by UI, 
+ * and can be null.
+*/
+starputop_param* starputop_register_parameter_boolean(
+			const char* param_name, 
+			int* parameter_field, 
+			void (*callback)(struct starputop_param_t*));
+/*
+ * This fonction register a parameter named param_name, of type integer.
+ * Minimum and maximum value will be used to prevent user seting incorrect
+ * value.
+ * The callback fonction will be called when the parameter is modified by UI, 
+ * and can be null.
+*/
+starputop_param* starputop_register_parameter_integer(const char* param_name, 
+			int* parameter_field, 
+			int minimum_value, 
+			int maximum_value,
+			void (*callback)(struct starputop_param_t*));
+/*
+ * This fonction register a parameter named param_name, of type float.
+ * Minimum and maximum value will be used to prevent user seting incorrect
+ * value.
+ * The callback fonction will be called when the parameter is modified by UI,
+ * and can be null.
+*/
+starputop_param* starputop_register_parameter_float(
+			const char* param_name, 
+			double* parameter_field, 
+			double minimum_value, 
+			double maximum_value, 
+			void (*callback)(struct starputop_param_t*));
+
+/*
+ * This fonction register a parameter named param_name, of type enum.
+ * Minimum and maximum value will be used to prevent user seting incorrect
+ * value.
+ * The callback fonction will be called when the parameter is modified by UI,
+ * and can be null.
+*/
+starputop_param* starputop_register_parameter_enum(
+			const char* param_name, 
+			int* parameter_field, 
+			char** values,
+			int nb_values, 
+			void (*callback)(struct starputop_param_t*));
+
+
+
+
+/****************************************************
+******************* Initialisation ******************
+*****************************************************/
+/*
+ * This function must be called when all parameters and
+ * data have been registered AND initialised (for parameters).
+ * This function will wait for a TOP to connect, send initialisation
+ * sentences, and wait for the GO message.
+ */
+void starputop_init_and_wait(const char* server_name);
+
+/****************************************************
+************ To call after initialisation************
+*****************************************************/
+
+/*
+ * This function should be called after every modification
+ * of a parameter from something other than starpu_top.
+ * This fonction notice UI that the configuration changed
+ */ 
+void starputop_update_parameter(const starputop_param* param);
+
+/*
+ * This functions update the value of the starputop_data on UI
+ */
+void starputop_update_data_boolean(
+			const starputop_data* data, 
+			int value);
+void starputop_update_data_integer(
+			const starputop_data* data, 
+			int value);
+void starputop_update_data_float(
+			const starputop_data* data, 
+			double value);
+
+/*
+ * This functions notify UI than the task has started or ended
+ */
+void starputop_task_started(
+			struct starpu_task *task, 
+			int devid, 
+			const struct timespec* ts);
+void starputop_task_ended(
+			struct starpu_task *task, 
+			int devid, 
+			const struct timespec* ts );
+/*
+ * This functions notify UI than the task have been planed to 
+ * run from timestamp_begin to timestamp_end, on computation-core
+ */
+void starputop_task_prevision_timespec(
+			struct starpu_task *task, 
+			int devid, 
+			const struct timespec* start, 
+			const struct timespec* end);
+void starputop_task_prevision(
+			struct starpu_task *task, 
+			int devid, unsigned long long start, 
+			unsigned long long end);
+
+ 
+/*
+ * This functions are usefull in debug mode. The starpu developper doesn't need
+ * to check if the debug mode is active.
+ * This is checked by starputop itsefl.
+ * 
+ * top_debug_log just send a message to display by UI
+ * top_debug_lock send a message and wait for a continue message from UI 
+ * to return
+ * 
+ * The lock (wich create a stop-point) should be called only by the main thread.
+ * Calling it from more than one thread is not supported.
+ */
+void starputop_debug_log(const char* message);
+void starputop_debug_lock(const char* message);
+
+/****************************************************
+***************** Callback function *****************
+*****************************************************/
+
+void starputop_process_input_message(char *message);
+	
+	
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STARPU_TOP_H__ */
+

+ 8 - 2
src/Makefile.am

@@ -105,7 +105,9 @@ noinst_HEADERS = 						\
 	profiling/bound.h					\
 	profiling/profiling.h					\
 	util/starpu_insert_task_utils.h				\
-	starpu_parameters.h
+	starpu_parameters.h					\
+	top/starputop_message_queue.h				\
+	top/starputop_connection.h
 
 libstarpu_la_SOURCES = 						\
 	common/barrier.c					\
@@ -195,7 +197,11 @@ libstarpu_la_SOURCES = 						\
 	debug/structures_size.c					\
 	profiling/profiling.c					\
 	profiling/bound.c					\
-	profiling/profiling_helpers.c
+	profiling/profiling_helpers.c				\
+	top/starpu_top.c					\
+	top/starputop_task.c					\
+	top/starputop_message_queue.c				\
+	top/starputop_connection.c
 
 if STARPU_USE_CPU
 libstarpu_la_SOURCES += drivers/cpu/driver_cpu.c

+ 2 - 1
src/core/jobs.c

@@ -24,6 +24,7 @@
 #include <common/utils.h>
 #include <profiling/profiling.h>
 #include <profiling/bound.h>
+#include <starpu_top.h>
 
 size_t _starpu_job_get_data_size(starpu_job_t j)
 {
@@ -68,7 +69,7 @@ starpu_job_t __attribute__((malloc)) _starpu_job_create(struct starpu_task *task
 	job->terminated = 0;
 
 #ifndef STARPU_USE_FXT
-	if (_starpu_bound_recording)
+	if (_starpu_bound_recording || starpu_top_status_get())
 #endif
 		job->job_id = STARPU_ATOMIC_ADD(&job_cnt, 1);
 #ifdef STARPU_USE_FXT

+ 3 - 36
src/drivers/cpu/driver_cpu.c

@@ -18,8 +18,6 @@
 
 #include <math.h>
 #include <starpu.h>
-#include <starpu_profiling.h>
-#include <profiling/profiling.h>
 #include <drivers/driver_common/driver_common.h>
 #include <common/utils.h>
 #include <core/debug.h>
@@ -31,17 +29,12 @@ static int execute_job_on_cpu(starpu_job_t j, struct starpu_worker_s *cpu_args,
 	int ret;
 	struct timespec codelet_start, codelet_end;
 
-	unsigned calibrate_model = 0;
-	int workerid = cpu_args->workerid;
 	struct starpu_task *task = j->task;
 	struct starpu_codelet_t *cl = task->cl;
 
 	STARPU_ASSERT(cl);
 	STARPU_ASSERT(cl->cpu_func);
 
-	if (cl->model && cl->model->benchmarking)
-		calibrate_model = 1;
-
 	if (rank == 0)
 	{
 		ret = _starpu_fetch_task_input(task, 0);
@@ -56,51 +49,25 @@ static int execute_job_on_cpu(starpu_job_t j, struct starpu_worker_s *cpu_args,
 	if (is_parallel_task)
 		PTHREAD_BARRIER_WAIT(&j->before_work_barrier);
 
-	STARPU_TRACE_START_CODELET_BODY(j);
-
-	struct starpu_task_profiling_info *profiling_info = NULL;
-	int profiling = starpu_profiling_status_get();
-
-	if (rank == 0)
-	{
-		profiling_info = task->profiling_info;
-	
-		if ((profiling && profiling_info) || calibrate_model)
-		{
-			starpu_clock_gettime(&codelet_start);
-			_starpu_worker_register_executing_start_date(workerid, &codelet_start);
-		}
+	_starpu_driver_start_job(cpu_args, j, &codelet_start, rank);
 
-	}
-	
-	cpu_args->status = STATUS_EXECUTING;
-	task->status = STARPU_TASK_RUNNING;	
-	
 	/* In case this is a Fork-join parallel task, the worker does not
 	 * execute the kernel at all. */
 	if ((rank == 0) || (cl->type != STARPU_FORKJOIN))
 	{
 		cl_func func = cl->cpu_func;
+		STARPU_ASSERT(func);
 		func(task->interfaces, task->cl_arg);
 	}
 	
 	if (is_parallel_task)
 		PTHREAD_BARRIER_WAIT(&j->after_work_barrier);
 
-	STARPU_TRACE_END_CODELET_BODY(j, perf_arch);
-
-	cpu_args->status = STATUS_UNKNOWN;
-
 	if (rank == 0)
 	{
-		cl->per_worker_stats[workerid]++;
-		
-		if ((profiling && profiling_info) || calibrate_model)
-			starpu_clock_gettime(&codelet_end);
-
 		_starpu_push_task_output(task, 0);
 
-		_starpu_driver_update_job_feedback(j, cpu_args, profiling_info,
+		_starpu_driver_update_job_feedback(j, cpu_args,
 				perf_arch, &codelet_start, &codelet_end);
 	}
 

+ 3 - 26
src/drivers/cuda/driver_cuda.c

@@ -18,14 +18,12 @@
 
 #include <starpu.h>
 #include <starpu_cuda.h>
-#include <starpu_profiling.h>
 #include <common/utils.h>
 #include <common/config.h>
 #include <core/debug.h>
 #include <drivers/driver_common/driver_common.h>
 #include "driver_cuda.h"
 #include <core/sched_policy.h>
-#include <profiling/profiling.h>
 
 /* the number of CUDA devices */
 static int ncudagpus;
@@ -166,7 +164,6 @@ static int execute_job_on_cuda(starpu_job_t j, struct starpu_worker_s *args)
 	struct timespec codelet_start, codelet_end;
 
 	unsigned calibrate_model = 0;
-	int workerid = args->workerid;
 
 	STARPU_ASSERT(task);
 	struct starpu_codelet_t *cl = task->cl;
@@ -190,42 +187,22 @@ static int execute_job_on_cuda(starpu_job_t j, struct starpu_worker_s *args)
 			STARPU_CUDA_REPORT_ERROR(cures);
 	}
 
-	STARPU_TRACE_START_CODELET_BODY(j);
-
-	struct starpu_task_profiling_info *profiling_info;
-	int profiling = starpu_profiling_status_get();
-	profiling_info = task->profiling_info;
+	_starpu_driver_start_job(args, j, &codelet_start, 0);
 
 #ifdef HAVE_CUDA_MEMCPY_PEER
 	/* We make sure we do manipulate the proper device */
 	cures = cudaSetDevice(args->devid);
 #endif
 
-	if ((profiling && profiling_info) || calibrate_model)
-	{
-		starpu_clock_gettime(&codelet_start);
-		_starpu_worker_register_executing_start_date(workerid, &codelet_start);
-	}
-
-	args->status = STATUS_EXECUTING;
-	task->status = STARPU_TASK_RUNNING;	
-
 	cl_func func = cl->cuda_func;
 	STARPU_ASSERT(func);
 	func(task->interfaces, task->cl_arg);
 
-	cl->per_worker_stats[workerid]++;
-
-	if ((profiling && profiling_info) || calibrate_model)
-		starpu_clock_gettime(&codelet_end);
-
-	enum starpu_perf_archtype archtype = args->perf_arch;
-	STARPU_TRACE_END_CODELET_BODY(j, archtype);
-	args->status = STATUS_UNKNOWN;
+	_starpu_driver_end_job(args, j, &codelet_end, 0);
 
 	_starpu_push_task_output(task, mask);
 
-	_starpu_driver_update_job_feedback(j, args, profiling_info, archtype,
+	_starpu_driver_update_job_feedback(j, args, profiling_info, args->perf_arch,
 			&codelet_start, &codelet_end);
 
 	return 0;

+ 62 - 1
src/drivers/driver_common/driver_common.c

@@ -22,12 +22,73 @@
 #include <common/utils.h>
 #include <core/debug.h>
 #include <drivers/driver_common/driver_common.h>
+#include <starpu_top.h>
 
+void _starpu_driver_start_job(struct starpu_worker_s *args, starpu_job_t j, struct timespec *codelet_start, int rank)
+{
+	struct starpu_task *task = j->task;
+	struct starpu_codelet_t *cl = task->cl;
+	struct starpu_task_profiling_info *profiling_info;
+	int profiling = starpu_profiling_status_get();
+	int starpu_top=starpu_top_status_get();
+	int workerid = args->workerid;
+	unsigned calibrate_model = 0;
+
+	if (cl->model && cl->model->benchmarking)
+		calibrate_model = 1;
+
+	args->status = STATUS_EXECUTING;
+	task->status = STARPU_TASK_RUNNING;	
+
+	if (rank == 0) {
+		cl->per_worker_stats[workerid]++;
+
+		profiling_info = task->profiling_info;
+	
+		if ((profiling && profiling_info) || calibrate_model || starpu_top)
+		{
+			starpu_clock_gettime(codelet_start);
+			_starpu_worker_register_executing_start_date(workerid, codelet_start);
+		}
+	}
+
+	if (starpu_top)
+		starputop_task_started(task,workerid,codelet_start);
+
+	STARPU_TRACE_START_CODELET_BODY(j);
+}
+
+void _starpu_driver_end_job(struct starpu_worker_s *args, starpu_job_t j, struct timespec *codelet_end, int rank)
+{
+	struct starpu_task *task = j->task;
+	struct starpu_codelet_t *cl = task->cl;
+	struct starpu_task_profiling_info *profiling_info = task->profiling_info;
+	int profiling = starpu_profiling_status_get();
+	int starpu_top=starpu_top_status_get();
+	int workerid = args->workerid;
+	unsigned calibrate_model = 0;
+	enum starpu_perf_archtype archtype = args->perf_arch;
+
+	STARPU_TRACE_END_CODELET_BODY(j, archtype);
+
+	if (cl->model && cl->model->benchmarking)
+		calibrate_model = 1;
+
+	if (rank == 0) {
+		if ((profiling && profiling_info) || calibrate_model || starpu_top)
+			starpu_clock_gettime(codelet_end);
+	}
+
+	if (starpu_top)
+	  starputop_task_ended(task,workerid,codelet_end);
+
+	args->status = STATUS_UNKNOWN;
+}
 void _starpu_driver_update_job_feedback(starpu_job_t j, struct starpu_worker_s *worker_args,
-					struct starpu_task_profiling_info *profiling_info,
 					enum starpu_perf_archtype perf_arch,
 					struct timespec *codelet_start, struct timespec *codelet_end)
 {
+	struct starpu_task_profiling_info *profiling_info = j->task->profiling_info;
 	struct timespec measured_ts;
 	double measured;
 	int workerid = worker_args->workerid;

+ 4 - 3
src/drivers/driver_common/driver_common.h

@@ -20,13 +20,14 @@
 
 #include <sys/time.h>
 #include <starpu.h>
-#include <starpu_profiling.h>
 #include <core/jobs.h>
-#include <profiling/profiling.h>
 #include <common/utils.h>
 
+void _starpu_driver_start_job(struct starpu_worker_s *args, starpu_job_t j,
+		struct timespec *codelet_start, int rank);
+void _starpu_driver_end_job(struct starpu_worker_s *args, starpu_job_t j,
+		struct timespec *codelet_end, int rank);
 void _starpu_driver_update_job_feedback(starpu_job_t j, struct starpu_worker_s *worker_args,
-		struct starpu_task_profiling_info *profiling_info,
 		enum starpu_perf_archtype perf_arch,
 		struct timespec *codelet_start, struct timespec *codelet_end);
 

+ 3 - 31
src/drivers/opencl/driver_opencl.c

@@ -18,7 +18,6 @@
 
 #include <math.h>
 #include <starpu.h>
-#include <starpu_profiling.h>
 #include <common/config.h>
 #include <common/utils.h>
 #include <core/debug.h>
@@ -27,7 +26,6 @@
 #include "driver_opencl.h"
 #include "driver_opencl_utils.h"
 #include <common/utils.h>
-#include <profiling/profiling.h>
 
 static pthread_mutex_t big_lock = PTHREAD_MUTEX_INITIALIZER;
 
@@ -516,16 +514,10 @@ static int _starpu_opencl_execute_job(starpu_job_t j, struct starpu_worker_s *ar
 
 	struct timespec codelet_start, codelet_end;
 
-	unsigned calibrate_model = 0;
-	int workerid = args->workerid;
-
 	STARPU_ASSERT(task);
 	struct starpu_codelet_t *cl = task->cl;
 	STARPU_ASSERT(cl);
 
-	if (cl->model && cl->model->benchmarking)
-		calibrate_model = 1;
-
 	ret = _starpu_fetch_task_input(task, mask);
 	if (ret != 0) {
 		/* there was not enough memory, so the input of
@@ -534,37 +526,17 @@ static int _starpu_opencl_execute_job(starpu_job_t j, struct starpu_worker_s *ar
 		return -EAGAIN;
 	}
 
-	STARPU_TRACE_START_CODELET_BODY(j);
-
-	struct starpu_task_profiling_info *profiling_info;
-	int profiling = starpu_profiling_status_get();
-	profiling_info = task->profiling_info;
-
-	if ((profiling && profiling_info) || calibrate_model)
-	{
-		starpu_clock_gettime(&codelet_start);
-		_starpu_worker_register_executing_start_date(workerid, &codelet_start);
-	}
-
-	args->status = STATUS_EXECUTING;
-	task->status = STARPU_TASK_RUNNING;	
+	_starpu_driver_start_job(args, j, &codelet_start, 0);
 
 	cl_func func = cl->opencl_func;
 	STARPU_ASSERT(func);
 	func(task->interfaces, task->cl_arg);
 
-	cl->per_worker_stats[workerid]++;
-
-	if ((profiling && profiling_info) || calibrate_model)
-		starpu_clock_gettime(&codelet_end);
-
-	enum starpu_perf_archtype archtype = args->perf_arch;
-	STARPU_TRACE_END_CODELET_BODY(j, archtype);
-	args->status = STATUS_UNKNOWN;
+	_starpu_driver_end_job(args, j, &codelet_end, 0);
 
 	_starpu_push_task_output(task, mask);
 
-	_starpu_driver_update_job_feedback(j, args, profiling_info, archtype,
+	_starpu_driver_update_job_feedback(j, args, args->perf_arch,
 							&codelet_start, &codelet_end);
 
 	return EXIT_SUCCESS;

+ 26 - 0
src/sched_policies/heft.c

@@ -23,6 +23,7 @@
 #include <core/perfmodel/perfmodel.h>
 #include <starpu_parameters.h>
 #include <starpu_task_bundle.h>
+#include <starpu_top.h>
 
 static unsigned nworkers;
 
@@ -39,6 +40,21 @@ static double exp_end[STARPU_NMAXWORKERS];
 static double exp_len[STARPU_NMAXWORKERS];
 static double ntasks[STARPU_NMAXWORKERS];
 
+const float alpha_minimum=0;
+const float alpha_maximum=10.0;
+const float beta_minimum=0;
+const float beta_maximum=10.0;
+const float gamma_minimum=0;
+const float gamma_maximum=10000.0;
+const float idle_power_minimum=0;
+const float idle_power_maximum=10000.0;
+
+void param_modified(struct starputop_param_t* d){
+	//just to show parameter modification
+	fprintf(stderr,"%s has been modified : alpha=%f|beta=%f|gamma=%f|idle_power=%f !\n", 
+		d->name, alpha,beta,_gamma,idle_power);
+}
+
 static void heft_init(struct starpu_machine_topology_s *topology, 
 	 __attribute__ ((unused)) struct starpu_sched_policy_s *_policy) 
 {
@@ -59,6 +75,11 @@ static void heft_init(struct starpu_machine_topology_s *topology,
 	const char *strval_idle_power = getenv("STARPU_IDLE_POWER");
 	if (strval_idle_power)
 		idle_power = atof(strval_idle_power);
+	
+	starputop_register_parameter_float("HEFT_ALPHA", &alpha, alpha_minimum,alpha_maximum,param_modified);
+	starputop_register_parameter_float("HEFT_BETA", &beta, beta_minimum,beta_maximum,param_modified);
+	starputop_register_parameter_float("HEFT_GAMMA", &_gamma, gamma_minimum,gamma_maximum,param_modified);
+	starputop_register_parameter_float("HEFT_IDLE_POWER", &idle_power, idle_power_minimum,idle_power_maximum,param_modified);
 
 	unsigned workerid;
 	for (workerid = 0; workerid < nworkers; workerid++)
@@ -129,6 +150,11 @@ static int push_task_on_best_worker(struct starpu_task *task, int best_workerid,
 
 	task->predicted = predicted;
 
+	if (starpu_top_status_get())
+		starputop_task_prevision(task, best_workerid, 
+					(unsigned long long)(exp_end[best_workerid]-predicted)/1000,
+					(unsigned long long)exp_end[best_workerid]/1000);
+
 	if (starpu_get_prefetch_flag())
 	{
 		unsigned memory_node = starpu_worker_get_memory_node(best_workerid);

+ 756 - 0
src/top/starpu_top.c

@@ -0,0 +1,756 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2011 William Braik, Yann Courtois, Jean-Marie Couteyen, Anthony
+ * Roy
+ *
+ * StarPU is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * StarPU is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+
+#include <starpu_top.h>
+#include <top/starputop_message_queue.h>
+#include <top/starputop_connection.h>
+#include <profiling/profiling.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <pthread.h>
+#include <timing.h>
+
+extern starputop_message_queue_t*  starputop_mt;
+int starpu_top = 0;
+int starputop_debug_on = 0;
+unsigned int starputop_data_cpt = 0;
+unsigned int starputop_param_cpt = 0;
+starputop_data* starputop_first_data = NULL;
+starputop_param* starputop_first_param = NULL;
+starputop_data** starputop_datas;
+starputop_param** starputop_params;
+
+sem_t starputop_wait_for_go;
+pthread_mutex_t starputop_wait_for_continue_mutex;
+pthread_cond_t starputop_wait_for_continue_cond = PTHREAD_COND_INITIALIZER;
+
+int starpu_top_status_get()
+{
+  return starpu_top;
+}
+
+
+unsigned long long int current_timestamp();
+
+/*********************************************
+*****************INIT FUNC********************
+**********************************************/
+
+char *message_for_topdata_init(starputop_data* data);
+char *message_for_topparam_init(starputop_param* param);
+
+/*
+ * we store data and param in a tab to offer a O(1) access when the program  is
+ * running
+ */
+void copy_data_and_param()
+{
+	printf("%s:%d trace\n", __FILE__, __LINE__);
+	//copying datas
+	starputop_datas = malloc(starputop_data_cpt*sizeof(starputop_data*));
+	starputop_data* cur = starputop_first_data;
+	unsigned int i = 0;
+	for(i = 0; i < starputop_data_cpt; i++)
+	{
+		starputop_datas[i] = cur;
+		cur = cur->next;
+	}
+	//copying params
+	starputop_params = malloc(starputop_param_cpt*sizeof(starputop_param*));
+	starputop_param* cur2 = starputop_first_param;
+	for(i = 0; i < starputop_param_cpt; i++)
+	{
+		starputop_params[i] = cur2;
+		cur2 = cur2->next;
+	}
+}
+
+static void starputop_get_device_type(int id, char* type){
+	enum starpu_archtype device_type=starpu_worker_get_type(id);
+	switch (device_type)
+	{
+	case STARPU_CPU_WORKER:
+		strncpy(type, "CPU",9);
+		break;
+	case STARPU_CUDA_WORKER:
+		strncpy(type, "CUDA",9);
+		break;
+	case STARPU_OPENCL_WORKER:
+		strncpy(type, "OPENCL",9);
+		break;
+	case STARPU_GORDON_WORKER:
+		strncpy(type, "GORDON",9);
+		break;
+	}  
+}
+
+static void starputop_send_devices_info()
+{
+	char* message=malloc(5*sizeof(char));
+	snprintf(message,5,"DEV\n");
+	starputop_message_add(starputop_mt,message);
+
+	unsigned int i;
+	for(i=0;i<starpu_worker_get_count();i++)
+	{
+		message=malloc(sizeof(char)*128);
+		char dev_type[10];
+		char dev_name[64];
+		starputop_get_device_type(i,dev_type);
+		starpu_worker_get_name(i, dev_name,64);
+		snprintf(message, 128, "%d;%s;%s\n", i, dev_type, dev_name);
+		starputop_message_add(starputop_mt,message);    
+	}
+
+	message=malloc(6*sizeof(char));                             
+	snprintf(message,6,"/DEV\n");                
+	starputop_message_add(starputop_mt,message);  
+}
+
+
+void starputop_init_and_wait(const char* server_name){
+	starpu_top=1;
+	sem_init(&starputop_wait_for_go,0,0);
+	
+	pthread_mutex_init(&starputop_wait_for_continue_mutex, NULL);
+	
+	//profiling activation
+	starpu_profiling_status_set(STARPU_PROFILING_ENABLE);
+
+	//init locked queue before adding the first message
+	starputop_mt = starputop_message_queue_new();
+
+	//waiting for UI to connect
+	printf("%s:%d launching network threads\n", __FILE__, __LINE__);
+	starputop_communications_threads_launcher();
+
+	//sending server information (report to protocol)
+	char* message = malloc(strlen("SERVERINFO\n")+1);
+	sprintf(message, "%s", "SERVERINFO\n");  
+	starputop_message_add(starputop_mt,message);
+	message = malloc(strlen(server_name)+2);
+	sprintf(message, "%s\n", server_name);
+	starputop_message_add(starputop_mt,message);
+	message = malloc(25);
+	sprintf(message, "%lld\n", current_timestamp());
+	starputop_message_add(starputop_mt,message);
+	message = malloc(strlen("/SERVERINFO\n")+1);
+	sprintf(message,"%s", "/SERVERINFO\n");
+	starputop_message_add(starputop_mt,message);
+
+
+	//sending data list
+	message = malloc(strlen("DATA\n")+1);
+	sprintf(message, "%s", "DATA\n");
+	starputop_message_add(starputop_mt,message);
+	starputop_data * cur_data = starputop_first_data;
+	while(cur_data != NULL)
+	{
+		starputop_message_add(starputop_mt,message_for_topdata_init(cur_data));
+		cur_data = cur_data->next;
+	}
+	message = malloc(strlen("/DATA\n")+1);
+	sprintf(message, "%s", "/DATA\n");
+	starputop_message_add(starputop_mt,message);
+	
+	//sending parameter list
+	message = malloc(strlen("PARAMS\n")+1);
+	sprintf(message, "%s", "PARAMS\n");
+	starputop_message_add(starputop_mt,message);
+	starputop_param * cur_param = starputop_first_param;
+	printf("%s:%d sending parameters\n", __FILE__, __LINE__);
+	while(cur_param != NULL){
+	  starputop_message_add(starputop_mt,message_for_topparam_init(cur_param));
+	  cur_param = cur_param->next;
+	}
+	printf("%s:%d parameters sended\n", __FILE__, __LINE__);
+	message = malloc(strlen("/PARAMS\n")+1);
+	sprintf(message, "%s", "/PARAMS\n");
+	starputop_message_add(starputop_mt,message);
+	
+	
+	//sending DEVICE list
+	printf("%s:%d sending devices info\n", __FILE__, __LINE__);
+	starputop_send_devices_info();
+	printf("%s:%d devices_info sended\n", __FILE__, __LINE__);
+	//copying data and params
+	copy_data_and_param();
+	
+	//sending READY message
+	message = malloc(strlen("READY\n")+1);
+	sprintf(message, "%s", "READY\n");
+	starputop_message_add(starputop_mt,message);
+	
+	//This threads keeps locked while we don't receive an GO message from UI
+	printf("%s:%d waiting for GO message\n", __FILE__, __LINE__);
+	sem_wait(&starputop_wait_for_go);
+}
+
+void starputop_enqueue_data(starputop_data * data)
+{
+	if(starputop_first_data == NULL)
+	{
+		starputop_first_data = data;
+	}
+	else
+	{
+		starputop_data * cur = starputop_first_data;
+		while(cur->next != NULL)
+			cur = cur->next;
+		cur->next = data;
+	}
+}
+
+starputop_data * starputop_add_data_boolean(
+			const char* data_name,
+			int active)
+{		
+	starputop_data * data = malloc(sizeof(starputop_data));
+	data->id = starputop_data_cpt++;
+	data->name = data_name;
+	data->type = STARPUTOP_DATA_BOOLEAN;
+	data->active = active;
+	data->next = NULL;
+
+	starputop_enqueue_data(data);
+
+	return data;
+}
+
+starputop_data * starputop_add_data_integer(
+			const char* data_name,
+			int minimum_value,
+			int maximum_value,
+			int active)
+{	
+	starputop_data * data = malloc(sizeof(starputop_data));
+	data->id = starputop_data_cpt++;
+	data->name = data_name; 
+	data->type = STARPUTOP_DATA_INTEGER;
+	data->int_min_value = minimum_value;
+	data->int_max_value = maximum_value;
+	data->active = active;
+	data->next = NULL;
+
+	starputop_enqueue_data(data);
+
+	return data;
+}
+
+starputop_data* starputop_add_data_float(
+			const char* data_name,
+			double minimum_value,
+			double maximum_value,
+			int active)
+{
+	starputop_data * data = malloc(sizeof(starputop_data));
+	data->id = starputop_data_cpt++;
+	data->name = data_name;
+	data->type = STARPUTOP_DATA_FLOAT;
+	data->double_min_value = minimum_value;
+	data->double_max_value = maximum_value;
+	data->active = active;
+	data->next = NULL;
+
+	starputop_enqueue_data(data);
+
+	return data;
+}
+
+char *message_for_topdata_init(starputop_data* data)
+{
+	char*message = malloc(256+strlen(data->name));
+	switch(data->type)
+	{
+		case STARPUTOP_DATA_BOOLEAN:
+			sprintf(message,
+					"BOOL;%d;%s;%d\n",
+					data->id,
+					data->name,
+					data->active ? 1 : 0);
+			break;
+		case STARPUTOP_DATA_INTEGER:
+			sprintf(message,
+					"INT;%d;%s;%d;%d;%d\n",
+					data->id,
+					data->name,
+					data->int_min_value,
+					data->int_max_value,
+					data->active ? 1 : 0);
+			break;
+		case STARPUTOP_DATA_FLOAT:
+			sprintf(message,
+					"FLOAT;%d;%s;%f;%f;%d\n",
+					data->id,
+					data->name,
+					data->double_min_value,
+					data->double_max_value,
+					data->active ? 1 : 0);
+			break;
+	}
+	return message;
+}
+
+char *message_for_topparam_init(starputop_param* param)
+{
+	char*message = NULL;
+	int i;
+	int length=0;
+	switch(param->type)
+	{
+	case STARPUTOP_PARAM_BOOLEAN:
+		message = malloc(256);
+		sprintf(message,
+				"BOOL;%d;%s;%d\n",
+				param->id,
+				param->name,
+				(*(int*)(param->value)) ? 1 : 0);
+		break;
+	case STARPUTOP_PARAM_INTEGER:
+		message = malloc(256);
+		sprintf(message,
+				"INT;%d;%s;%d;%d;%d\n",param->id,
+				param->name,
+				param->int_min_value,
+				param->int_max_value,
+				*(int*)(param->value));
+		break;
+	case STARPUTOP_PARAM_FLOAT:
+		message = malloc(256);
+		sprintf(message,
+				"FLOAT;%d;%s;%f;%f;%f\n",
+				param->id,
+				param->name,
+				param->double_min_value,
+				param->double_max_value,
+				*(double*)(param->value));
+		break;
+	case STARPUTOP_PARAM_ENUM:
+		//compute message lenght
+		for(i = 0; i < param->nb_values; i++)
+		{
+			length += strlen(param->enum_values[i])+1;
+		}
+		message = malloc(256+length);
+		sprintf(message,
+				"ENUM;%d;%s;",
+				param->id,
+				param->name);
+		
+		//compute the begin of enums elements in message
+		char* cur = message+strlen(message);
+		//add each enum element
+		for(i = 0; i < param->nb_values; i++)
+		{
+			strcpy(cur, param->enum_values[i]);
+			cur+=strlen(cur);
+			*cur=';';
+			cur++;
+		}
+		sprintf(cur,
+				"%d\n",
+				*((int*)(param->value)));
+		break;
+	}
+	return message;
+}
+
+void starputop_enqueue_param(starputop_param* param)
+{
+	if(starputop_first_param == NULL)
+	{
+		starputop_first_param = param;
+	}
+	else
+	{
+		starputop_param * cur = starputop_first_param;
+		while(cur->next != NULL)
+			cur = cur->next;
+		cur->next = param;
+	}
+}
+
+
+starputop_param* starputop_register_parameter_boolean(
+			const char* param_name,
+			int* parameter_field,
+			void (*callback)(struct starputop_param_t*))
+{
+    STARPU_ASSERT(!starpu_top_status_get());
+	starputop_param * param = malloc(sizeof(starputop_param));
+	param->callback = callback;
+	param->name = param_name;
+	param->id = starputop_param_cpt++;
+	param->type = STARPUTOP_PARAM_BOOLEAN;
+	param->value = (void*)parameter_field;
+	param->next = NULL;
+	
+	starputop_enqueue_param(param);
+	
+	return param;
+}
+
+
+starputop_param* starputop_register_parameter_integer(const char* param_name,
+			int* parameter_field,
+			int minimum_value,
+			int maximum_value,
+			void (*callback)(struct starputop_param_t*))
+{	
+	STARPU_ASSERT(!starpu_top_status_get());
+	starputop_param * param = malloc(sizeof(starputop_param));
+	param->callback = callback;
+	param->name = param_name;
+	param->id = starputop_param_cpt++;
+	param->type = STARPUTOP_PARAM_INTEGER;
+	param->value = (void*)parameter_field;
+	param->int_min_value = minimum_value;
+	param->int_max_value = maximum_value;
+	param->next = NULL;
+
+	starputop_enqueue_param(param);
+	
+	return param;
+}
+starputop_param* starputop_register_parameter_float(
+			const char* param_name,
+			double* parameter_field,
+			double minimum_value,
+			double maximum_value,
+			void (*callback)(struct starputop_param_t*))
+{
+	STARPU_ASSERT(!starpu_top_status_get());
+	starputop_param * param = malloc(sizeof(starputop_param));
+	param->callback = callback;
+	param->name = param_name;
+	param->id = starputop_param_cpt++;
+	param->type = STARPUTOP_PARAM_FLOAT;
+	param->value = (void*)parameter_field;
+	param->double_min_value = minimum_value;
+	param->double_max_value = maximum_value;
+	param->next = NULL;
+
+	starputop_enqueue_param(param);
+
+	return param;
+}
+
+starputop_param* starputop_register_parameter_enum(
+			const char* param_name,
+			int* parameter_field,
+			char** values,
+			int nb_values,
+			void (*callback)(struct starputop_param_t*))
+{
+	STARPU_ASSERT(!starpu_top_status_get());
+	starputop_param * param = malloc(sizeof(starputop_param));
+	param->callback = callback;
+	param->name = param_name;
+	param->id = starputop_param_cpt++;
+	param->type = STARPUTOP_PARAM_ENUM;
+	param->value = (void*)parameter_field;
+	param->enum_values = values;
+	param->nb_values = nb_values;
+	param->next = NULL;
+	
+	starputop_enqueue_param(param);
+
+	return param;
+}
+/*********************************************
+*****************UPDATE FUNC******************
+**********************************************/
+
+void starputop_update_data_boolean(const starputop_data* data, int value){
+	if (!starpu_top_status_get())
+		return;
+	if(data->active)
+	{
+		char*message = malloc(256+strlen(data->name));
+		sprintf(message,
+				"U;%d;%d;%lld\n",
+				data->id,
+				(value?1:0),
+				current_timestamp());
+		starputop_message_add(starputop_mt,message);
+	}
+}
+void starputop_update_data_integer(const starputop_data* data,int value){
+	if (!starpu_top_status_get())
+		return;
+	if(data->active)
+	{
+		char*message = malloc(256+strlen(data->name));
+		sprintf(message,
+				"U;%d;%d;%lld\n",
+				data->id,
+				value,
+				current_timestamp());
+		starputop_message_add(starputop_mt,message);
+	}
+}
+void starputop_update_data_float(const starputop_data* data, double value){
+	if (!starpu_top_status_get())
+		return;
+	if(data->active)
+	{
+		char*message = malloc(256+strlen(data->name));
+		sprintf(message,
+				"U;%d;%f;%lld\n",
+				data->id, value,
+				current_timestamp());
+		starputop_message_add(starputop_mt,message);
+	}
+}
+void starputop_update_parameter(const starputop_param* param){
+	if (!starpu_top_status_get())
+		return;
+	char*message = malloc(50);
+
+	switch(param->type)
+	{
+		case STARPUTOP_PARAM_BOOLEAN:
+		case STARPUTOP_PARAM_INTEGER:
+		case STARPUTOP_PARAM_ENUM:
+			sprintf(message,
+					"SET;%d;%d;%lld\n",
+					param->id,
+					*((int*)param->value),
+					current_timestamp());
+			break;
+		
+		case STARPUTOP_PARAM_FLOAT:
+			sprintf(message,
+					"SET;%d;%f;%lld\n",
+					param->id,
+					*((double*)param->value),
+					current_timestamp());
+			break;
+	}
+	
+	starputop_message_add(starputop_mt,message);	
+}
+
+/*********************************************
+*****************DEBUG FUNC******************
+**********************************************/
+
+void starputop_debug_log(const char* debug_message)
+{
+	if(starputop_debug_on)
+	{
+		//length can be up to strlen*2, if message contains only unwanted chars
+		char * message = malloc(strlen(debug_message)*2+16);
+		sprintf(message,"MESSAGE;");
+		
+		//escape unwanted char : ; and \n
+		char* cur = message+8;
+		while(*debug_message!='\0')
+		{
+			if(*debug_message=='\n' || *debug_message==';')
+			{
+				*cur='\\';
+				cur++;
+			}
+			*cur = *debug_message;
+			cur++;
+			debug_message++;
+		}
+		*cur='\n';
+		cur++;
+		*cur='\0';
+
+		starputop_message_add(starputop_mt,message);
+	}
+}
+void starputop_debug_lock(const char* debug_message)
+{
+	if(starputop_debug_on)
+	{
+		char * message = malloc(strlen(debug_message)*2+16);
+		sprintf(message,"LOCK;");
+		char* cur = message+5;
+		while(*debug_message!='\0')
+		{
+			if(*debug_message=='\n' || *debug_message==';')
+			{
+				*cur='\\';
+				cur++;
+			}
+			*cur = *debug_message;
+			cur++;
+			debug_message++;
+		}
+		*cur='\n';
+		*(cur+1)='\0';
+
+		starputop_message_add(starputop_mt,message);
+
+		//This threads keeps locked while we don't receive an STEP message
+		pthread_mutex_lock(&starputop_wait_for_continue_mutex);
+		pthread_cond_wait(&starputop_wait_for_continue_cond,&starputop_wait_for_continue_mutex);
+		pthread_mutex_unlock(&starputop_wait_for_continue_mutex);
+	}
+}
+
+ 
+ 
+/********************************************
+ **************TIME FUNCTION****************
+ *******************************************/
+
+unsigned long long int current_timestamp()
+{
+	struct timespec now;
+	starpu_clock_gettime(&now);
+	return starpu_timing_timespec_to_ms(&now);
+}
+
+unsigned long long starpu_timing_timespec_to_ms(const struct timespec *ts)
+{
+  return (1000.0*ts->tv_sec) + (0.000001*ts->tv_nsec);
+}
+
+/********************************************
+ **************INPUT PROCESSING**************
+ *******************************************/
+
+starputop_message_type starputop_get_message_type(const char* message)
+{
+	if(!strncmp("GO\n", message,3))
+		return TOP_TYPE_GO;
+	else if(!strncmp("SET;", message,4))
+		return TOP_TYPE_SET;
+	else if(!strncmp("STEP\n", message,9))
+		return TOP_TYPE_CONTINUE;
+	else if(!strncmp("ENABLE;", message,7))
+		return TOP_TYPE_ENABLE;
+	else if(!strncmp("DISABLE;", message,8))
+		return TOP_TYPE_DISABLE;
+	else if(!strncmp("DEBUG;", message,6))
+		return TOP_TYPE_DEBUG;
+	else 
+		return TOP_TYPE_UNKNOW;
+}
+
+
+void starputop_unlock_starpu()
+{
+	sem_post(&starputop_wait_for_go);
+	printf("%s:%d starpu started\n", __FILE__, __LINE__);
+}
+
+void starputop_change_data_active(char* message, int active)
+{
+	char* debut = strstr(message, ";")+1;
+	char* fin = strstr(debut+1, "\n");
+	*fin = '\0';
+	int data_id = atoi(debut);
+	printf("%s:%d data %d %s\n", __FILE__, __LINE__, data_id, active ? "ENABLED" : "DISABLE");
+	starputop_datas[data_id]->active = active;
+}
+
+void starputop_change_parameter_value(const char* message){
+	const char*tmp = strstr(message, ";")+1;
+	int param_id = atoi(tmp);
+	starputop_param* param = starputop_params[param_id];
+	tmp = strstr(tmp+1,";")+1;
+	int* val_ptr_int;
+	double* val_ptr_double;
+
+	switch(param->type)
+	{
+		case STARPUTOP_PARAM_BOOLEAN:
+		case STARPUTOP_PARAM_INTEGER:
+			val_ptr_int = (int*)param->value;
+			*val_ptr_int = atoi(tmp);
+		break;
+		
+		case STARPUTOP_PARAM_FLOAT:
+			val_ptr_double = (double*)param->value;
+			*val_ptr_double = atof(tmp);
+		break;
+
+		case STARPUTOP_PARAM_ENUM:
+			val_ptr_int = (int*)param->value;
+			*val_ptr_int = atoi(tmp);
+		break;
+		
+	}
+	if(param->callback != NULL)
+		param->callback(param);
+}
+
+void starputop_change_debug_mode(const char*message)
+{
+	const char* debut = strstr(message, ";")+1;
+	if(!strncmp("ON",debut, 2))
+	{
+		starputop_debug_on = 1;
+		printf("%s:%d debug is now ON\n", __FILE__, __LINE__);
+	}
+	else
+	{
+		starputop_debug_on = 0;
+		printf("%s:%d debug is now OFF\n", __FILE__, __LINE__);
+	}
+
+	char * m = malloc(strlen(message)+1);
+	sprintf(m,"%s",message);
+	starputop_message_add(starputop_mt,m);
+}
+
+/*
+ * Unlock starpu if it was locked in debug state
+*/
+void starputop_debug_next_step()
+{
+	pthread_cond_signal(&starputop_wait_for_continue_cond);
+}
+
+
+void starputop_process_input_message(char *buffer)
+{
+	starputop_message_type message_type = starputop_get_message_type(buffer);
+	switch(message_type)
+	{
+		case TOP_TYPE_GO:
+			starputop_unlock_starpu();
+		break;
+		case TOP_TYPE_ENABLE:
+			starputop_change_data_active(buffer, 1);
+		break;
+		case TOP_TYPE_DISABLE:
+			starputop_change_data_active(buffer, 0);
+		break;
+		case TOP_TYPE_SET:
+			starputop_change_parameter_value(buffer);
+		break;
+		case TOP_TYPE_DEBUG:
+			starputop_change_debug_mode(buffer);
+		break;
+		case TOP_TYPE_CONTINUE:
+			starputop_debug_next_step();
+		break;
+		default:
+			printf("%s:%d unknow message : '%s'\n", __FILE__, __LINE__, buffer);
+	}
+}
+
+

+ 158 - 0
src/top/starputop_connection.c

@@ -0,0 +1,158 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2011 William Braik, Yann Courtois, Jean-Marie Couteyen, Anthony
+ * Roy
+ *
+ * StarPU is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * StarPU is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+#include <top/starputop_connection.h>
+#include <top/starputop_message_queue.h>
+#include <starpu_top.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <stdlib.h>
+
+const char *STARPUTOP_PORT = "2011";
+const int STARPUTOP_BUFFER_SIZE=1024;
+
+extern starputop_message_queue_t*  starputop_mt;
+
+//client socket after fopen
+FILE* starputop_socket_fd_read;
+FILE* starputop_socket_fd_write;
+//client socket (file descriptor)
+int starputop_socket_fd;
+
+
+void * message_from_ui(void * p)
+{
+	(void) p;
+	char str[STARPUTOP_BUFFER_SIZE];
+	while(1)
+	{
+		char * check=fgets (str, STARPUTOP_BUFFER_SIZE, starputop_socket_fd_read);
+
+		printf("Message from UI : %s",str);
+		if (check)
+		{
+			starputop_process_input_message(str);
+		}
+		else
+		{
+			fprintf(stderr,"Connection dropped\n");
+			//unlocking StarPU.
+			starputop_process_input_message("GO\n");
+			starputop_process_input_message("DEBUG;OFF\n");
+			starputop_process_input_message("STEP\n");
+			return NULL;
+		}
+	}
+	return NULL;
+}
+
+void * message_to_ui(void * p)
+{
+	(void) p;
+	while(1)
+	{
+		char* message = starputop_message_remove(starputop_mt);
+		int len=strlen(message);
+		int check=fwrite(message, sizeof(char), len, starputop_socket_fd_write);
+		int check2=fflush(starputop_socket_fd_write);
+		free(message);
+		if (check!=len || check2==EOF )
+		{
+			fprintf(stderr,"Connection dropped : message no longer send\n");
+			while(1)
+			{
+				message=starputop_message_remove(starputop_mt);
+				free(message);
+			}
+		}
+	}
+	return NULL;
+}
+
+void starputop_communications_threads_launcher()
+{
+	pthread_t from_ui;
+	pthread_t to_ui;
+	pthread_attr_t threads_attr;
+
+  
+	//Connection to UI & Socket Initilization
+	printf("%s:%d Connection to UI initilization\n",__FILE__, __LINE__);
+	struct sockaddr_storage from;
+	struct addrinfo req, *ans;
+	int code;
+	req.ai_flags = AI_PASSIVE;
+	req.ai_family = PF_UNSPEC;            
+	req.ai_socktype = SOCK_STREAM;
+	req.ai_protocol = 0;  
+  
+	if ((code = getaddrinfo(NULL, STARPUTOP_PORT, &req, &ans)) != 0)
+	{
+		fprintf(stderr, " getaddrinfo failed %d\n", code);
+		exit(EXIT_FAILURE);
+   	}
+  	int sock=socket(ans->ai_family, ans->ai_socktype, ans->ai_protocol);
+	int optval = 1;
+	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+
+	if (bind(sock, ans->ai_addr, ans->ai_addrlen) < 0)
+	{
+		perror("bind");
+		exit(EXIT_FAILURE);
+	}
+
+	listen(sock, 2);
+
+	socklen_t len = sizeof(from);
+
+   	if ((starputop_socket_fd=accept(sock, (struct sockaddr *) &from, &len)) ==-1)
+	{
+		fprintf(stderr, "accept error\n");
+		perror("accept");
+		exit(EXIT_FAILURE);
+	}
+	
+	if ( (starputop_socket_fd_read=fdopen(starputop_socket_fd, "r")) == NULL)
+	{
+		perror("fdopen");
+		exit(EXIT_FAILURE);
+	}
+
+	starputop_socket_fd=dup(starputop_socket_fd);
+	
+	if ((starputop_socket_fd_write=fdopen(starputop_socket_fd, "w")) == NULL)
+	{
+		perror("fdopen");
+		exit(EXIT_FAILURE);
+	}
+	
+	close(sock);
+	
+	//Threads creation
+	fprintf(stderr,"Threads Creation\n");
+	pthread_attr_init(&threads_attr);
+	pthread_attr_setdetachstate(&threads_attr, PTHREAD_CREATE_DETACHED);
+	
+	pthread_create(&from_ui, &threads_attr, message_from_ui, NULL);
+	pthread_create(&to_ui, &threads_attr, message_to_ui, NULL);
+}
+

+ 44 - 0
src/top/starputop_connection.h

@@ -0,0 +1,44 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2011 William Braik, Yann Courtois, Jean-Marie Couteyen, Anthony
+ * Roy
+ *
+ * StarPU is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * StarPU is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+#ifndef __STARPUTOP_CONNECTION_H__
+#define __STARPUTOP_CONNECTION_H__
+
+#include <stdlib.h>
+#include <top/starputop_message_queue.h>
+#include <starpu_top.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  extern starputop_message_queue_t*  starputop_mt;
+
+/*
+ * This function initialize the two communications threads.
+ * It initializes the connection and then launches the threads.
+ * The function wait the UI connection before launching the threads.
+ * About mt : mt MUST be allocated before call. 
+ * All messages in the queue are freed after used. 
+ */
+  void starputop_communications_threads_launcher();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __STARPUTOP_CONNECTION_H__
+

+ 109 - 0
src/top/starputop_message_queue.c

@@ -0,0 +1,109 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2011 William Braik, Yann Courtois, Jean-Marie Couteyen, Anthony
+ * Roy
+ *
+ * StarPU is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * StarPU is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+#include  "starputop_message_queue.h"
+#include  <string.h>
+#include  <stdio.h>
+#include  <stdlib.h>
+
+//this global queue is used both by API and by network threads
+starputop_message_queue_t*  starputop_mt = NULL;
+
+
+/* Will always return the pointer to starputop_message_queue */
+starputop_message_queue_t* starputop_message_add(
+			starputop_message_queue_t* s,
+			char* msg)
+{
+	starputop_message_queue_item_t* p = malloc( 1 * sizeof(*p) );
+	pthread_mutex_lock(&(s->mutex));
+	if( NULL == p )
+	{
+		fprintf(stderr, "IN %s, %s: malloc() failed\n", __FILE__, "list_add");
+		pthread_mutex_unlock(&(s->mutex));
+		return s;
+	}
+
+	p->message = msg;
+	p->next = NULL;
+
+	if( NULL == s )
+	{
+		printf("Queue not initialized\n");
+		pthread_mutex_unlock(&(s->mutex));
+		return s;
+	}
+	else if( NULL == s->head && NULL == s->tail )
+	{
+		/* printf("Empty list, adding p->num: %d\n\n", p->num);  */
+		sem_post(&(s->semaphore));
+		s->head = s->tail = p;
+		pthread_mutex_unlock(&(s->mutex));
+		return s;
+	}
+	else
+	{
+		/* printf("List not empty, adding element to tail\n"); */
+		sem_post(&(s->semaphore));
+		s->tail->next = p;
+		s->tail = p;
+	}
+	pthread_mutex_unlock(&(s->mutex));
+	return s;
+}
+
+//this is a queue and it is FIFO, so we will always remove the first element
+char* starputop_message_remove(starputop_message_queue_t* s)
+{
+	sem_wait(&(s->semaphore));
+	starputop_message_queue_item_t* h = NULL;
+	starputop_message_queue_item_t* p = NULL;
+
+	if( NULL == s )
+	{
+		printf("List is null\n");
+		return NULL;
+	}
+	pthread_mutex_lock(&(s->mutex));
+	h = s->head;
+	p = h->next;
+	char* value = h->message;
+	free(h);
+	s->head = p;
+
+	
+	if( NULL == s->head )
+		//the element tail was pointing to is free(), so we need an update
+		s->tail = s->head;
+	pthread_mutex_unlock(&(s->mutex));
+	return value;
+}
+
+
+starputop_message_queue_t* starputop_message_queue_new(void)
+{
+	starputop_message_queue_t* p = malloc( 1 * sizeof(*p));
+	if( NULL == p )
+	{
+		fprintf(stderr, "LINE: %d, malloc() failed\n", __LINE__);
+	}
+
+	p->head = p->tail = NULL;
+	sem_init(&(p->semaphore),0,0);
+	pthread_mutex_init(&(p->mutex), NULL);
+	return p;
+}

+ 49 - 0
src/top/starputop_message_queue.h

@@ -0,0 +1,49 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2011 William Braik, Yann Courtois, Jean-Marie Couteyen, Anthony
+ * Roy
+ *
+ * StarPU is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * StarPU is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+#include <semaphore.h> 
+#include <pthread.h>
+
+#ifndef __STARPUTOP_MESSAGE_QUEUE_H__
+#define __STARPUTOP_MESSAGE_QUEUE_H__
+
+typedef struct starputop_message_queue_item
+{
+	char *message;
+	struct starputop_message_queue_item* next;
+} starputop_message_queue_item_t;
+
+typedef struct starputop_message_queue
+{
+	struct starputop_message_queue_item* head;
+	struct starputop_message_queue_item* tail;
+	sem_t semaphore;
+	pthread_mutex_t mutex;
+} starputop_message_queue_t;
+
+
+starputop_message_queue_t *starputop_message_add(
+			starputop_message_queue_t*,
+			char*);
+
+char* starputop_message_remove(starputop_message_queue_t*);
+
+starputop_message_queue_t* starputop_message_queue_new();
+starputop_message_queue_t* starputop_message_queue_free(
+			starputop_message_queue_t*);
+
+#endif

+ 97 - 0
src/top/starputop_task.c

@@ -0,0 +1,97 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2011 William Braik, Yann Courtois, Jean-Marie Couteyen, Anthony
+ * Roy
+ *
+ * StarPU is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * StarPU is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+#include <starpu_top.h>
+#include <top/starputop_message_queue.h>
+#include <top/starputop_connection.h>
+#include <core/task.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <timing.h>
+
+/********************************************
+ **************TASK RELATED FUNCTIONS********
+ *******************************************/
+
+void starputop_task_started(
+			struct starpu_task *task, 
+			int devid, 
+			const struct timespec *ts)
+{
+	unsigned long long taskid = _starpu_get_job_associated_to_task(task)->job_id;
+	STARPU_ASSERT(starpu_top_status_get());
+	char *str = malloc(sizeof(char)*64);
+	snprintf(str, 64,
+				"START;%llu;%d;%llu\n",
+				taskid, 
+				devid, 
+				starpu_timing_timespec_to_ms(ts));
+
+	starputop_message_add(starputop_mt, str);
+}
+
+void starputop_task_ended(
+			struct starpu_task *task, 
+			int devid, 
+			const struct timespec *ts)
+{
+	unsigned long long taskid = _starpu_get_job_associated_to_task(task)->job_id;
+	(void) devid; //unused
+	STARPU_ASSERT(starpu_top_status_get());
+	char *str = malloc(sizeof(char)*64);
+	snprintf(str, 64,
+				"END;%llu;%llu\n", 
+				taskid, 
+				starpu_timing_timespec_to_ms(ts));
+
+	starputop_message_add(starputop_mt, str);
+}
+
+void starputop_task_prevision_timespec(
+			struct starpu_task *task,
+			int devid, 
+			const struct timespec* start, 
+			const struct timespec* end)
+{
+	starputop_task_prevision(task, 
+							devid, 
+							starpu_timing_timespec_to_ms(start),
+							starpu_timing_timespec_to_ms(end));
+}
+
+void starputop_task_prevision(
+			struct starpu_task *task, 
+			int devid, 
+			unsigned long long start, 
+			unsigned long long end)
+{
+	unsigned long long taskid = _starpu_get_job_associated_to_task(task)->job_id;
+	STARPU_ASSERT(starpu_top_status_get());
+	struct timespec now;
+	starpu_clock_gettime(&now);
+	char * str=malloc(sizeof(char)*200);
+	snprintf(str, 128, 
+				"PREV;%llu;%d;%llu;%llu;%llu\n",
+				taskid,
+				devid,
+				starpu_timing_timespec_to_ms(&now),
+				start,
+				end);
+
+	starputop_message_add(starputop_mt, str);
+}

+ 11 - 0
starpu-top/README

@@ -0,0 +1,11 @@
+Software needed
+
+libqt4 >= 4.7
+libqt4-network
+libqt4-opengl
+libqt4-sql
+
+Building
+
+$ qmake-qt4
+$ make

+ 54 - 0
starpu-top/StarPU-Top-common.pri

@@ -0,0 +1,54 @@
+# -------------------------------------------------
+# Project created by QtCreator 2011-01-22T11:55:16
+# -------------------------------------------------
+QT += network
+QT += opengl
+QT += sql
+
+TARGET = StarPU-Top
+TEMPLATE = app
+SOURCES += main.cpp \
+#STARPU-TOP
+    mainwindow.cpp \
+    configurationmanager.cpp \
+    widgetwindowsmanager.cpp \
+    communicationthread.cpp \
+    communicationmanager.cpp \
+    preferencesdialog.cpp \
+    datawidget.cpp \
+    interactivewidget.cpp \
+    ganttwidget.cpp \
+    debugconsole.cpp \
+    dataaggregatorwidget.cpp \
+    taskmanager.cpp \
+    abstractwidgetwindow.cpp \
+    sessionsetupmanager.cpp \
+#QLEDINDICATOR
+    qledindicator/qledindicator.cpp \
+    aboutdialog.cpp
+HEADERS += mainwindow.h \
+#STARPU-TOP
+    starputoptypes.h \
+    widgetwindowsmanager.h \
+    configurationmanager.h \
+    communicationthread.h \
+    communicationmanager.h \
+    preferencesdialog.h \
+    datawidget.h \
+    interactivewidget.h \
+    ganttwidget.h \
+    debugconsole.h \
+    dataaggregatorwidget.h \
+    taskmanager.h \
+    abstractwidgetwindow.h \
+    sessionsetupmanager.h \
+#QLEDINDICATOR
+    qledindicator/qledindicator.h \
+    aboutdialog.h
+
+FORMS += mainwindow.ui \
+    preferencesdialog.ui \
+    debugconsole.ui \
+    aboutdialog.ui
+RESOURCES += resources.qrc
+OTHER_FILES += TODO.txt

+ 85 - 0
starpu-top/StarPU-Top-qwt-embed.pri

@@ -0,0 +1,85 @@
+SOURCES += \
+    qwt/qwt_thermo.cpp \
+    qwt/qwt_math.cpp \
+    qwt/qwt_scale_engine.cpp \
+    qwt/qwt_scale_draw.cpp \
+    qwt/qwt_scale_map.cpp \
+    qwt/qwt_scale_div.cpp \
+    qwt/qwt_painter.cpp \
+    qwt/qwt_abstract_scale.cpp \
+    qwt/qwt_abstract_scale_draw.cpp \
+    qwt/qwt_interval.cpp \
+    qwt/qwt_text.cpp \
+    qwt/qwt_text_engine.cpp \
+    qwt/qwt_clipper.cpp \
+    qwt/qwt_color_map.cpp \
+    qwt/qwt_plot.cpp \
+    qwt/qwt_plot_dict.cpp \
+    qwt/qwt_plot_layout.cpp \
+    qwt/qwt_scale_widget.cpp \
+    qwt/qwt_text_label.cpp \
+    qwt/qwt_legend.cpp \
+    qwt/qwt_dyngrid_layout.cpp \
+    qwt/qwt_plot_canvas.cpp \
+    qwt/qwt_plot_item.cpp \
+    qwt/qwt_legend_item.cpp \
+    qwt/qwt_symbol.cpp \
+    qwt/qwt_plot_axis.cpp \
+    qwt/qwt_plot_xml.cpp \
+    qwt/qwt_knob.cpp \
+    qwt/qwt_abstract_slider.cpp \
+    qwt/qwt_round_scale_draw.cpp \
+    qwt/qwt_double_range.cpp \
+    qwt/qwt_wheel.cpp \
+    qwt/qwt_slider.cpp \
+    qwt/qwt_plot_curve.cpp \
+    qwt/qwt_plot_seriesitem.cpp \
+    qwt/qwt_series_data.cpp \
+    qwt/qwt_point_polar.cpp \
+    qwt/qwt_curve_fitter.cpp \
+    qwt/qwt_spline.cpp \
+    qwt/qwt_dial.cpp \
+    qwt/qwt_dial_needle.cpp
+HEADERS += \
+    qwt/qwt_thermo.h \
+    qwt/qwt_math.h \
+    qwt/qwt_scale_engine.h \
+    qwt/qwt_scale_draw.h \
+    qwt/qwt_scale_map.h \
+    qwt/qwt_scale_div.h \
+    qwt/qwt_painter.h \
+    qwt/qwt_global.h \
+    qwt/qwt_abstract_scale.h \
+    qwt/qwt_abstract_scale_draw.h \
+    qwt/qwt_interval.h \
+    qwt/qwt_text.h \
+    qwt/qwt_text_engine.h \
+    qwt/qwt_clipper.h \
+    qwt/qwt_color_map.h \
+    qwt/qwt_plot.h \
+    qwt/qwt_plot_dict.h \
+    qwt/qwt_plot_layout.h \
+    qwt/qwt_scale_widget.h \
+    qwt/qwt_text_label.h \
+    qwt/qwt_legend.h \
+    qwt/qwt_dyngrid_layout.h \
+    qwt/qwt_plot_canvas.h \
+    qwt/qwt_plot_item.h \
+    qwt/qwt_legend_itemmanager.h \
+    qwt/qwt_legend_item.h \
+    qwt/qwt_symbol.h \
+    qwt/qwt_knob.h \
+    qwt/qwt_abstract_slider.h \
+    qwt/qwt_round_scale_draw.h \
+    qwt/qwt_double_range.h \
+    qwt/qwt_wheel.h \
+    qwt/qwt_slider.h \
+    qwt/qwt_plot_curve.h \
+    qwt/qwt_plot_seriesitem.h \
+    qwt/qwt_series_data.h \
+    qwt/qwt_point_polar.h \
+    qwt/qwt_curve_fitter.h \
+    qwt/qwt_spline.h \
+    qwt/qwt_dial.h \
+    qwt/qwt_dial_needle.h
+INCLUDEPATH += qwt

+ 2 - 0
starpu-top/StarPU-Top-qwt-system.pri

@@ -0,0 +1,2 @@
+LIBS += -lqwt-qt4
+INCLUDEPATH += /usr/include/qwt-qt4

+ 2 - 0
starpu-top/StarPU-Top.pro.in

@@ -0,0 +1,2 @@
+include (StarPU-Top-common.pri)
+include (StarPU-Top-qwt-@QWT_PRI@.pri)

+ 113 - 0
starpu-top/StarPU-Top.pro.user

@@ -0,0 +1,113 @@
+<!DOCTYPE QtCreatorProject>
+<qtcreator>
+ <data>
+  <variable>ProjectExplorer.Project.ActiveTarget</variable>
+  <value type="int">0</value>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.EditorSettings</variable>
+  <valuemap type="QVariantMap">
+   <value key="EditorConfiguration.Codec" type="QByteArray">UTF-8</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.Target.0</variable>
+  <valuemap type="QVariantMap">
+   <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Bureau</value>
+   <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Target.DesktopTarget</value>
+   <value key="ProjectExplorer.Target.ActiveBuildConfiguration" type="int">0</value>
+   <value key="ProjectExplorer.Target.ActiveRunConfiguration" type="int">0</value>
+   <valuemap key="ProjectExplorer.Target.BuildConfiguration.0" type="QVariantMap">
+    <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
+     <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">qmake</value>
+     <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value>
+     <valuelist key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QVariantList"/>
+    </valuemap>
+    <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.1" type="QVariantMap">
+     <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+     <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+     <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value>
+     <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList"/>
+     <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+    </valuemap>
+    <value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">2</value>
+    <valuemap key="ProjectExplorer.BuildConfiguration.CleanStep.0" type="QVariantMap">
+     <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+     <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+     <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value>
+     <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList">
+      <value type="QString">clean</value>
+     </valuelist>
+     <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+    </valuemap>
+    <value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">1</value>
+    <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
+    <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+    <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Déboguer</value>
+    <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
+    <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">2</value>
+    <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">C:/Users/Will/Documents/My Dropbox/Projets/Projets partagés/StarPU-Top-build-desktop</value>
+    <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">14</value>
+    <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="int">2</value>
+    <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value>
+   </valuemap>
+   <valuemap key="ProjectExplorer.Target.BuildConfiguration.1" type="QVariantMap">
+    <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
+     <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">qmake</value>
+     <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value>
+     <valuelist key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QVariantList"/>
+    </valuemap>
+    <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.1" type="QVariantMap">
+     <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+     <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+     <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value>
+     <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList"/>
+     <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+    </valuemap>
+    <value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">2</value>
+    <valuemap key="ProjectExplorer.BuildConfiguration.CleanStep.0" type="QVariantMap">
+     <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+     <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+     <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value>
+     <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList">
+      <value type="QString">clean</value>
+     </valuelist>
+     <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+    </valuemap>
+    <value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">1</value>
+    <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
+    <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+    <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Release</value>
+    <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
+    <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">0</value>
+    <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">C:/Users/Will/Documents/My Dropbox/Projets/Projets partagés/StarPU-Top-build-desktop</value>
+    <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">14</value>
+    <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="int">2</value>
+    <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value>
+   </valuemap>
+   <value key="ProjectExplorer.Target.BuildConfigurationCount" type="int">2</value>
+   <valuemap key="ProjectExplorer.Target.RunConfiguration.0" type="QVariantMap">
+    <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">StarPU-Top</value>
+    <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value>
+    <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value>
+    <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QVariantList"/>
+    <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">StarPU-Top.pro</value>
+    <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value>
+    <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value>
+    <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+    <value key="Qt4ProjectManager.Qt4RunConfiguration.UserSetName" type="bool">false</value>
+    <value key="Qt4ProjectManager.Qt4RunConfiguration.UserSetWorkingDirectory" type="bool">false</value>
+    <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value>
+   </valuemap>
+   <value key="ProjectExplorer.Target.RunConfigurationCount" type="int">1</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.TargetCount</variable>
+  <value type="int">1</value>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
+  <value type="int">4</value>
+ </data>
+</qtcreator>

+ 251 - 0
starpu-top/StarPU-Top.pro.user.1.3

@@ -0,0 +1,251 @@
+<!DOCTYPE QtCreatorProject>
+<qtcreator>
+ <data>
+  <variable>RunConfiguration0-BaseEnvironmentBase</variable>
+  <value type="int">2</value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-CommandLineArguments</variable>
+  <valuelist type="QVariantList"/>
+ </data>
+ <data>
+  <variable>RunConfiguration0-ProFile</variable>
+  <value type="QString">StarPU-Top.pro</value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-RunConfiguration.name</variable>
+  <value type="QString">StarPU-Top</value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-UseDyldImageSuffix</variable>
+  <value type="bool">false</value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-UseTerminal</variable>
+  <value type="bool">false</value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-UserEnvironmentChanges</variable>
+  <valuelist type="QVariantList"/>
+ </data>
+ <data>
+  <variable>RunConfiguration0-UserSetName</variable>
+  <value type="bool">false</value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-UserSetWorkingDirectory</variable>
+  <value type="bool">false</value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-UserWorkingDirectory</variable>
+  <value type="QString"></value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-type</variable>
+  <value type="QString">Qt4ProjectManager.Qt4RunConfiguration</value>
+ </data>
+ <data>
+  <variable>activeRunConfiguration</variable>
+  <value type="int">0</value>
+ </data>
+ <data>
+  <variable>activebuildconfiguration</variable>
+  <value type="QString">Debug</value>
+ </data>
+ <data>
+  <variable>buildConfiguration-Debug</variable>
+  <valuemap type="QVariantMap">
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">Debug</value>
+   <value key="QtVersionId" type="int">0</value>
+   <value key="ToolChain" type="int">0</value>
+   <value key="buildConfiguration" type="int">2</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildConfiguration-Release</variable>
+  <valuemap type="QVariantMap">
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">Release</value>
+   <value key="QtVersionId" type="int">0</value>
+   <value key="buildConfiguration" type="int">0</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfiguration-Debug-buildstep0</variable>
+  <valuemap type="QVariantMap">
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">Debug</value>
+   <valuelist key="abstractProcess.Environment" type="QVariantList">
+    <value type="QString">DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-xjteyoVy4U,guid=2ff41d777326f17fae0e40cc4d946e56</value>
+    <value type="QString">DESKTOP_SESSION=gnome</value>
+    <value type="QString">DISPLAY=:0.0</value>
+    <value type="QString">DM_CONTROL=/var/run/xdmctl</value>
+    <value type="QString">FLUENT_EDUCATIONAL=yes</value>
+    <value type="QString">GNOME_DESKTOP_SESSION_ID=this-is-deprecated</value>
+    <value type="QString">GNOME_KEYRING_CONTROL=/tmp/keyring-rP2qY8</value>
+    <value type="QString">GPG_AGENT_INFO=/tmp/gpg-G3amdS/S.gpg-agent:4516:1</value>
+    <value type="QString">GTK_MODULES=canberra-gtk-module</value>
+    <value type="QString">HOME=/net/cremi/wbraik</value>
+    <value type="QString">HOOPS_DRIVER=X11</value>
+    <value type="QString">JAVA=/usr/lib/jvm/java-6-sun/bin/java</value>
+    <value type="QString">JAVA_HOME=/usr/lib/jvm/java-6-sun</value>
+    <value type="QString">KRB5CCNAME=FILE:/tmp/krb5cc_18733_aqBO3a</value>
+    <value type="QString">LANG=fr_FR.UTF-8</value>
+    <value type="QString">LD_LIBRARY_PATH=/usr/lib/qtcreator</value>
+    <value type="QString">LOGNAME=wbraik</value>
+    <value type="QString">ORBIT_SOCKETDIR=/tmp/orbit-wbraik</value>
+    <value type="QString">PATH=/usr/bin:/usr/lib/jvm/java-6-sun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games</value>
+    <value type="QString">PWD=/net/cremi/wbraik</value>
+    <value type="QString">QTDIR=/usr/share/qt4</value>
+    <value type="QString">SESSION_MANAGER=local/lebris:@/tmp/.ICE-unix/3965,unix/lebris:/tmp/.ICE-unix/3965</value>
+    <value type="QString">SHELL=/bin/bash</value>
+    <value type="QString">SHLVL=0</value>
+    <value type="QString">SPEECHD_PORT=25293</value>
+    <value type="QString">SSH_AGENT_PID=4515</value>
+    <value type="QString">SSH_AUTH_SOCK=/tmp/keyring-rP2qY8/ssh</value>
+    <value type="QString">UDEdir=</value>
+    <value type="QString">USER=wbraik</value>
+    <value type="QString">USERCACHE=/tmp/cache-wbraik</value>
+    <value type="QString">WINDOWPATH=8</value>
+    <value type="QString">XDG_CONFIG_DIRS=/usr/share/ubuntustudio-menu/:/etc/xdg/</value>
+    <value type="QString">XDG_DATA_DIRS=/usr/share/gnome:/usr/local/share/:/usr/share/</value>
+    <value type="QString">XDG_SESSION_COOKIE=a3e0486a642ad65955ad302d4ce13336-1301573197.240134-346611465</value>
+    <value type="QString">XDM_MANAGED=method=classic</value>
+   </valuelist>
+   <valuelist key="abstractProcess.arguments" type="QVariantList">
+    <value type="QString">/autofs/netapp/account/cremi/wbraik/Dropbox/Projets/Projets partagés/StarPU-Top/StarPU-Top.pro</value>
+    <value type="QString">-spec</value>
+    <value type="QString">linux-g++</value>
+    <value type="QString">-r</value>
+    <value type="QString">CONFIG+=debug</value>
+   </valuelist>
+   <value key="abstractProcess.command" type="QString">/usr/bin/qmake-qt4</value>
+   <value key="abstractProcess.enabled" type="bool">true</value>
+   <value key="abstractProcess.workingDirectory" type="QString">/autofs/netapp/account/cremi/wbraik/Dropbox/Projets/Projets partagés/StarPU-Top</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfiguration-Debug-buildstep1</variable>
+  <valuemap type="QVariantMap">
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">Debug</value>
+   <valuelist key="abstractProcess.Environment" type="QVariantList">
+    <value type="QString">DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-xjteyoVy4U,guid=2ff41d777326f17fae0e40cc4d946e56</value>
+    <value type="QString">DESKTOP_SESSION=gnome</value>
+    <value type="QString">DISPLAY=:0.0</value>
+    <value type="QString">DM_CONTROL=/var/run/xdmctl</value>
+    <value type="QString">FLUENT_EDUCATIONAL=yes</value>
+    <value type="QString">GNOME_DESKTOP_SESSION_ID=this-is-deprecated</value>
+    <value type="QString">GNOME_KEYRING_CONTROL=/tmp/keyring-rP2qY8</value>
+    <value type="QString">GPG_AGENT_INFO=/tmp/gpg-G3amdS/S.gpg-agent:4516:1</value>
+    <value type="QString">GTK_MODULES=canberra-gtk-module</value>
+    <value type="QString">HOME=/net/cremi/wbraik</value>
+    <value type="QString">HOOPS_DRIVER=X11</value>
+    <value type="QString">JAVA=/usr/lib/jvm/java-6-sun/bin/java</value>
+    <value type="QString">JAVA_HOME=/usr/lib/jvm/java-6-sun</value>
+    <value type="QString">KRB5CCNAME=FILE:/tmp/krb5cc_18733_aqBO3a</value>
+    <value type="QString">LANG=fr_FR.UTF-8</value>
+    <value type="QString">LD_LIBRARY_PATH=/usr/lib/qtcreator</value>
+    <value type="QString">LOGNAME=wbraik</value>
+    <value type="QString">ORBIT_SOCKETDIR=/tmp/orbit-wbraik</value>
+    <value type="QString">PATH=/usr/bin:/usr/lib/jvm/java-6-sun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games</value>
+    <value type="QString">PWD=/net/cremi/wbraik</value>
+    <value type="QString">QTDIR=/usr/share/qt4</value>
+    <value type="QString">SESSION_MANAGER=local/lebris:@/tmp/.ICE-unix/3965,unix/lebris:/tmp/.ICE-unix/3965</value>
+    <value type="QString">SHELL=/bin/bash</value>
+    <value type="QString">SHLVL=0</value>
+    <value type="QString">SPEECHD_PORT=25293</value>
+    <value type="QString">SSH_AGENT_PID=4515</value>
+    <value type="QString">SSH_AUTH_SOCK=/tmp/keyring-rP2qY8/ssh</value>
+    <value type="QString">UDEdir=</value>
+    <value type="QString">USER=wbraik</value>
+    <value type="QString">USERCACHE=/tmp/cache-wbraik</value>
+    <value type="QString">WINDOWPATH=8</value>
+    <value type="QString">XDG_CONFIG_DIRS=/usr/share/ubuntustudio-menu/:/etc/xdg/</value>
+    <value type="QString">XDG_DATA_DIRS=/usr/share/gnome:/usr/local/share/:/usr/share/</value>
+    <value type="QString">XDG_SESSION_COOKIE=a3e0486a642ad65955ad302d4ce13336-1301573197.240134-346611465</value>
+    <value type="QString">XDM_MANAGED=method=classic</value>
+   </valuelist>
+   <value key="abstractProcess.IgnoreReturnValue" type="bool">false</value>
+   <valuelist key="abstractProcess.arguments" type="QVariantList">
+    <value type="QString">-w</value>
+   </valuelist>
+   <value key="abstractProcess.command" type="QString">/usr/bin/make</value>
+   <value key="abstractProcess.enabled" type="bool">true</value>
+   <value key="abstractProcess.workingDirectory" type="QString">/autofs/netapp/account/cremi/wbraik/Dropbox/Projets/Projets partagés/StarPU-Top</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfiguration-Debug-cleanstep0</variable>
+  <valuemap type="QVariantMap">
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">Debug</value>
+   <value key="cleanConfig" type="bool">true</value>
+   <valuelist key="makeargs" type="QVariantList">
+    <value type="QString">clean</value>
+   </valuelist>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfiguration-Release-buildstep0</variable>
+  <valuemap type="QVariantMap">
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">Release</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfiguration-Release-buildstep1</variable>
+  <valuemap type="QVariantMap">
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">Release</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfiguration-Release-cleanstep0</variable>
+  <valuemap type="QVariantMap">
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">Release</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfigurations</variable>
+  <valuelist type="QVariantList">
+   <value type="QString">Debug</value>
+   <value type="QString">Release</value>
+  </valuelist>
+ </data>
+ <data>
+  <variable>buildstep0</variable>
+  <valuemap type="QVariantMap">
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString"></value>
+   <value key="mkspec" type="QString"></value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildstep1</variable>
+  <valuemap type="QVariantMap">
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString"></value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildsteps</variable>
+  <valuelist type="QVariantList">
+   <value type="QString">trolltech.qt4projectmanager.qmake</value>
+   <value type="QString">trolltech.qt4projectmanager.make</value>
+  </valuelist>
+ </data>
+ <data>
+  <variable>cleanstep0</variable>
+  <valuemap type="QVariantMap">
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString"></value>
+   <value key="clean" type="bool">true</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>cleansteps</variable>
+  <valuelist type="QVariantList">
+   <value type="QString">trolltech.qt4projectmanager.make</value>
+  </valuelist>
+ </data>
+ <data>
+  <variable>defaultFileEncoding</variable>
+  <value type="QByteArray">System</value>
+ </data>
+ <data>
+  <variable>project</variable>
+  <valuemap type="QVariantMap"/>
+ </data>
+</qtcreator>

+ 9 - 0
starpu-top/TODO.txt

@@ -0,0 +1,9 @@
+FONCTIONS :
+- cleanup dans le destructeur final (~MainWindow)
+- mettre en place l'interface DescriptionProvider
+
+BUGS :
+- parfois un QLIST ASSERT (index out of range)
+lors de la restauration de session (a priori assez difficile à reproduire)?
+
+TESTS :

+ 44 - 0
starpu-top/aboutdialog.cpp

@@ -0,0 +1,44 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "aboutdialog.h"
+#include "ui_aboutdialog.h"
+#include <QDebug>
+
+AboutDialog::AboutDialog(QWidget *parent) :
+    QDialog(parent),
+    ui(new Ui::AboutDialog)
+{
+    ui->setupUi(this);
+
+    qDebug() << "AboutDialog : initializing";
+}
+
+AboutDialog::~AboutDialog()
+{
+    qDebug() << "AboutDialog : terminating";
+
+    delete ui;
+}

+ 47 - 0
starpu-top/aboutdialog.h

@@ -0,0 +1,47 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef ABOUTDIALOG_H
+#define ABOUTDIALOG_H
+
+#include <QDialog>
+
+namespace Ui {
+    class AboutDialog;
+}
+
+class AboutDialog : public QDialog
+{
+    Q_OBJECT
+
+public:
+    explicit AboutDialog(QWidget *parent = 0);
+    ~AboutDialog();
+
+private:
+    Ui::AboutDialog *ui;
+};
+
+#endif // ABOUTDIALOG_H

+ 186 - 0
starpu-top/aboutdialog.ui

@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AboutDialog</class>
+ <widget class="QDialog" name="AboutDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>328</width>
+    <height>340</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>0</width>
+    <height>0</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>About StarPU-Top...</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="resources.qrc">
+    <normaloff>:/images/about.png</normaloff>:/images/about.png</iconset>
+  </property>
+  <property name="modal">
+   <bool>true</bool>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="3" column="0" colspan="2">
+    <widget class="QGroupBox" name="developersGroupBox">
+     <property name="maximumSize">
+      <size>
+       <width>16777215</width>
+       <height>110</height>
+      </size>
+     </property>
+     <property name="title">
+      <string>Developers</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_2">
+      <item row="0" column="0">
+       <widget class="QListWidget" name="developersList">
+        <property name="enabled">
+         <bool>true</bool>
+        </property>
+        <property name="selectionMode">
+         <enum>QAbstractItemView::NoSelection</enum>
+        </property>
+        <item>
+         <property name="text">
+          <string>William BRAIK</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Yann COURTOIS</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Jean-Marie COUTEYEN</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Anthony ROY</string>
+         </property>
+        </item>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="QLabel" name="titleLabel">
+     <property name="maximumSize">
+      <size>
+       <width>16777215</width>
+       <height>50</height>
+      </size>
+     </property>
+     <property name="styleSheet">
+      <string notr="true">font: 12pt &quot;MS Shell Dlg 2&quot;;</string>
+     </property>
+     <property name="text">
+      <string>StarPU-Top, for StarPU</string>
+     </property>
+     <property name="scaledContents">
+      <bool>false</bool>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="0">
+    <widget class="QLabel" name="label">
+     <property name="maximumSize">
+      <size>
+       <width>120</width>
+       <height>110</height>
+      </size>
+     </property>
+     <property name="text">
+      <string/>
+     </property>
+     <property name="pixmap">
+      <pixmap resource="resources.qrc">:/images/starputop.png</pixmap>
+     </property>
+     <property name="scaledContents">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0" colspan="2">
+    <widget class="QGroupBox" name="groupBox">
+     <property name="minimumSize">
+      <size>
+       <width>0</width>
+       <height>0</height>
+      </size>
+     </property>
+     <property name="maximumSize">
+      <size>
+       <width>16777215</width>
+       <height>90</height>
+      </size>
+     </property>
+     <property name="title">
+      <string>Software</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_3">
+      <item row="0" column="0">
+       <widget class="QListWidget" name="listWidget">
+        <property name="enabled">
+         <bool>true</bool>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>0</width>
+          <height>0</height>
+         </size>
+        </property>
+        <property name="maximumSize">
+         <size>
+          <width>16777215</width>
+          <height>16777215</height>
+         </size>
+        </property>
+        <property name="selectionMode">
+         <enum>QAbstractItemView::NoSelection</enum>
+        </property>
+        <item>
+         <property name="text">
+          <string>Year : 2011</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Version : 0.1</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>Licence : LGPL</string>
+         </property>
+        </item>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources>
+  <include location="resources.qrc"/>
+ </resources>
+ <connections/>
+</ui>

+ 155 - 0
starpu-top/abstractwidgetwindow.cpp

@@ -0,0 +1,155 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "abstractwidgetwindow.h"
+#include "widgetwindowsmanager.h"
+#include "mainwindow.h"
+#include <QVBoxLayout>
+
+AbstractWidgetWindow::AbstractWidgetWindow(
+        WidgetWindowsManager *widgetWindowsManager,
+        MainWindow *mainWindow,
+        bool inside)
+            : QWidget(mainWindow)
+{
+    _widgetWindowsManager = widgetWindowsManager;
+    _mainWindow = mainWindow;
+    _inside = inside;
+
+    // Init id
+    _windowId = generateWindowId();
+
+    // Init GUI
+    _sizeGrip = new QSizeGrip(this);
+    _sizeGrip->move(width()-32,height()-32);
+    _sizeGrip->resize(32,32);
+    _inOutButton = new QToolButton();
+    QObject::connect(_inOutButton, SIGNAL(clicked()),
+                     this, SLOT(on_inOutButton_clicked()));
+    _inside ? _inOutButton->setToolTip(tr("To flying window"))
+        : _inOutButton->setToolTip(tr("To MDI"));
+    _inside ? _inOutButton->setIcon(QIcon(":/images/outside.png"))
+        : _inOutButton->setIcon(QIcon(":/images/inside.png"));
+
+    // Set attributes
+    setAttribute(Qt::WA_DeleteOnClose);
+}
+
+AbstractWidgetWindow::~AbstractWidgetWindow()
+{
+    delete _sizeGrip;
+    delete _inOutButton;
+}
+
+/* -------------------------------------------------------------------------- */
+/* Events                                                                     */
+/* -------------------------------------------------------------------------- */
+
+void AbstractWidgetWindow::mousePressEvent(QMouseEvent *event)
+{
+    if ((isInside() == false) && (event->button() == Qt::LeftButton))
+    {
+        dragPosition = event->globalPos() - frameGeometry().topLeft();
+        event->accept();
+    }
+}
+
+void AbstractWidgetWindow::mouseMoveEvent(QMouseEvent *event)
+{
+    if ((isInside() == false) && (event->buttons() & Qt::LeftButton))
+    {
+        move(event->globalPos() - dragPosition);
+        event->accept();
+    }
+}
+
+void AbstractWidgetWindow::resizeEvent(QResizeEvent *event)
+{
+    _sizeGrip->move(width()-32,height()-32);
+    _sizeGrip->resize(32,32);
+}
+
+/* -------------------------------------------------------------------------- */
+/* Getters                                                                    */
+/* -------------------------------------------------------------------------- */
+
+int AbstractWidgetWindow::windowId() const
+{
+    return _windowId;
+}
+
+bool AbstractWidgetWindow::isInside() const
+{
+    return _inside;
+}
+
+/* -------------------------------------------------------------------------- */
+/* Setters                                                                    */
+/* -------------------------------------------------------------------------- */
+
+void AbstractWidgetWindow::setInside(bool inside)
+{
+    _inside = inside;
+
+    if(isInside() == false)
+    {
+        _inOutButton->setToolTip(tr("To MDI"));
+        _inOutButton->setIcon(QIcon(":/images/inside.png"));
+    }
+    else
+    {
+        _inOutButton->setToolTip(tr("To flying window"));
+        _inOutButton->setIcon(QIcon(":/images/outside.png"));
+    }
+}
+
+/* -------------------------------------------------------------------------- */
+/* GUI interactions                                                           */
+/* -------------------------------------------------------------------------- */
+
+void AbstractWidgetWindow::on_inOutButton_clicked()
+{
+    setInside(!isInside());
+
+    if(_inside)
+    {
+        _widgetWindowsManager->flyingWindowToMdi(this);
+    }
+    else
+    {
+        _widgetWindowsManager->mdiToFlyingWindow(this);
+    }
+}
+
+/* -------------------------------------------------------------------------- */
+/* Window ID generation                                                       */
+/* -------------------------------------------------------------------------- */
+
+int AbstractWidgetWindow::generateWindowId()
+{
+    static int windowId = 0;
+
+    return windowId++;
+}

+ 81 - 0
starpu-top/abstractwidgetwindow.h

@@ -0,0 +1,81 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef ABSTRACTWIDGETWINDOW_H
+#define ABSTRACTWIDGETWINDOW_H
+
+class WidgetWindowsManager;
+class MainWindow;
+
+#include <QWidget>
+#include <QSizeGrip>
+#include <QToolButton>
+#include <QMouseEvent>
+
+class AbstractWidgetWindow : public QWidget
+{ /* Abstract class representing a widget window.
+     It can be put "outside" (flying window) or "inside" (MDI) at any moment.
+     The widget window is managed by the widget windows manager. */
+    Q_OBJECT
+
+public:
+    explicit AbstractWidgetWindow(
+            WidgetWindowsManager *widgetWindowsManager,
+            MainWindow *mainWindow,
+            bool inside = false);
+    virtual ~AbstractWidgetWindow();
+
+    // Getters
+    int windowId() const;
+    bool isInside() const;
+    // Setters
+    void setInside(bool inside);
+
+protected:
+    // Components
+    WidgetWindowsManager *_widgetWindowsManager;
+    MainWindow *_mainWindow;
+    QPoint dragPosition;
+    // GUI components
+    QSizeGrip *_sizeGrip;
+    QToolButton *_inOutButton;
+    // Metadata
+    int _windowId;
+    bool _inside;
+
+    // Window id generation
+    int generateWindowId();
+    // Events
+    void mousePressEvent(QMouseEvent *event);
+    void mouseMoveEvent(QMouseEvent *event);
+    void resizeEvent(QResizeEvent *event);
+    virtual void closeEvent(QCloseEvent *ce) = 0;
+
+private slots:
+    // GUI interactions
+    void on_inOutButton_clicked();
+};
+
+#endif // ABSTRACTWIDGETWINDOW_H

File diff suppressed because it is too large
+ 1573 - 0
starpu-top/communicationmanager.cpp


+ 152 - 0
starpu-top/communicationmanager.h

@@ -0,0 +1,152 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef COMMUNICATIONMANAGER_H
+#define COMMUNICATIONMANAGER_H
+
+#include <QTcpSocket>
+#include "starputoptypes.h"
+
+class CommunicationManager : public QTcpSocket
+{ /* Receives protocol messages from server, parses them
+     and notifies the GUI appropriately using signals.
+     Sends protocol messages to server when the GUI notifies. */
+    Q_OBJECT
+
+public:
+    CommunicationManager(QObject *parent = 0);
+    ~CommunicationManager();
+
+private:
+    // Protocol message strings
+    QHash<QString, CommunicationInMessageType> _inMessageStrings;
+    QHash<CommunicationOutMessageType, QString> _outMessageStrings;
+    QSet<QString> _typeMessageStrings;
+    QSet<QString> _beginEndMessageStrings;
+    QSet<QString> _widgetStatusChangeMessageStrings;
+    QSet<QString> _debugMessageStrings;
+    QSet<QString> _loopMessageStrings;
+    // Metadata
+    int _serverInfoMsgCount;
+    QString _serverID;
+    qlonglong _serverTimestamp;
+    QList<DataDescription*> *_dataDescriptions;
+    QList<ParamDescription*> *_paramDescriptions;
+    QList<StarputopDevice> *_serverDevices;
+    // Communication states
+    CommunicationState _state;
+    bool _initServerInfoCompleted;
+    bool _initDataCompleted;
+    bool _initParamsCompleted;
+    bool _initDevCompleted;
+    // Getters
+    // Get communication states
+    CommunicationState state() const;
+    bool isInitCompleted() const;
+    // Get session descriptions
+    DataDescription *dataDescriptionFromId(int dataId) const;
+    ParamDescription *paramDescriptionFromId(int paramId) const;
+
+    // Init protocol message strings
+    void initInMessageStrings();
+    void initOutMessageStrings();
+
+private slots:
+    // Initialize a new session
+    void initializeSession();
+    // Receive protocol messages
+    void messageReceived();
+    // Parse different protocol messages
+    void parseInitMessage(QString messageString);
+    void parseInitServerInfoMessage(QString messageString);
+    void parseInitDataMessage(QString messageString);
+    void parseInitParamsMessage(QString messageString);
+    void parseInitDevMessage(QString messageString);
+    void parseReadyMessage(QString messageString);
+    void parseLoopMessage(QString messageString);
+    void parseTaskPrevMessage(QString messageString);
+    void parseTaskStartMessage(QString messageString);
+    void parseTaskEndMessage(QString messageString);
+    void parseDataUpdateMessage(QString messageString);
+    void parseParamNotificationMessage(QString messageString);
+    void parseDebugEnabledMessage(QString messageString);
+    void parseDebugMessageMessage(QString messageString);
+    void parseDebugLockMessage(QString messageString);
+
+public slots:
+    // Build different protocol messages
+    QString buildGoMessage();
+    QString buildDataEnableMessage(int dataId);
+    QString buildDataDisableMessage(int dataId);
+    QString buildParamSetMessage(int paramId, bool paramValue);
+    QString buildParamSetMessage(int paramId, int paramValue);
+    QString buildParamSetMessage(int paramId, double paramValue);
+    QString buildDebugEnabledMessage(bool enabled);
+    QString buildStepMessage();
+    // Send different protocol messages
+    void sendMessage(QString messageString);
+    void sendGoMessage();
+    void sendDataEnableMessage(int dataId);
+    void sendDataDisableMessage(int dataId);
+    void sendParamSetMessage(int paramId, bool paramValue);
+    void sendParamSetMessage(int paramId, int paramValue);
+    void sendParamSetMessage(int paramId, double paramValue);
+    void sendDebugEnabledMessage(bool enabled);
+    void sendStepMessage();
+    // Clear session descriptions
+    void clearDescriptions();
+
+signals:
+    // Reference time received from server
+    void sessionTimeSynchronized(qlonglong serverTimestamp);
+    // Send init session data to GUI
+    void serverInitCompleted(QString serverID,
+                             QList<DataDescription*> *dataDescriptions,
+                             QList<ParamDescription*> *paramDescriptions,
+                             QList<StarputopDevice> *serverDevices);
+    // Notify GUI with a protocol message
+    // Protocol error
+    void protocolError(QString errorMessage);
+    // Debug protocol messages
+    void notifyDebugEnabled(bool enabled);
+    void notifyDebugMessage(QString debugMessage);
+    void notifyDebugLock(QString lockMessage);
+    // Data update protocol messages
+    void notifyDataUpdate(int dataId, bool dataValue, qlonglong timestamp);
+    void notifyDataUpdate(int dataId, int dataValue, qlonglong timestamp);
+    void notifyDataUpdate(int dataId, double dataValue, qlonglong timestamp);
+    // Parameter update protocol messages
+    void notifyParamUpdate(int paramId, bool paramValue, qlonglong timestamp);
+    void notifyParamUpdate(int paramId, int paramValue, qlonglong timestamp);
+    void notifyParamUpdate(int paramId, double paramValue, qlonglong timestamp);
+    // Task update protocol messages
+    void notifyTaskPrevUpdate(int taskId, int deviceId,  qlonglong timestamp,
+                              qlonglong timestampStart, qlonglong timestampEnd);
+    void notifyTaskStartUpdate(int taskId, int deviceId,  qlonglong timestamp);
+    void notifyTaskEndUpdate(int taskId, qlonglong timestamp);
+    void protoConnected();
+};
+
+#endif // COMMUNICATIONMANAGER_H

+ 281 - 0
starpu-top/communicationthread.cpp

@@ -0,0 +1,281 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+Copyright (C) 2011 Université de Bordeaux 1
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include <QMessageBox>
+#include "communicationthread.h"
+#include "configurationmanager.h"
+#include "mainwindow.h"
+#include "communicationmanager.h"
+#include "starputoptypes.h"
+
+const int MAX_CONNECTION_ATTEMPTS = 10;
+
+CommunicationThread::CommunicationThread(
+        MainWindow *mainWindow,
+        ConfigurationManager *configurationManager)
+{
+    static bool instanciated = false;
+
+    Q_ASSERT_X(instanciated == false, "CommunicationThread's' constructor",
+               "Singleton pattern violated - "
+               "CommunicationThread instanciated more than once");
+
+    _mainWindow = mainWindow;
+    _configurationManager = configurationManager;
+    _communicationManager = 0;
+    _SSHProcess = NULL;
+
+    instanciated = true;
+
+    QObject::connect(this, SIGNAL(progress(QString)),
+                   _mainWindow, SLOT(updateStatusBarMessage(QString)));
+    QObject::connect(this, SIGNAL(disconnected()),
+                    _mainWindow, SLOT(disconnected()));
+    QObject::connect(this, SIGNAL(abort(QString)),
+                   _mainWindow, SLOT(connectionAborted(QString)));
+
+    qDebug() << "CommunicationThread : initializing";
+}
+
+CommunicationThread::~CommunicationThread()
+{
+    qDebug() << "CommunicationThread : terminating";
+
+    delete _communicationManager;
+}
+
+void CommunicationThread::createNewCommunicationManager(void)
+{
+    emit progress(tr("Connecting..."));
+
+    if (_communicationManager == 0)
+        delete(_communicationManager );
+
+    _communicationManager = new CommunicationManager(this);
+
+    // Type registering is necessary for Qt "Queued Connections"
+    // as we are going to send signals to a different thread
+    qRegisterMetaType<QAbstractSocket::SocketError> (
+            "QAbstractSocket::SocketError");
+
+    // Connection events
+    QObject::connect(_communicationManager, SIGNAL(protoConnected()),
+                   _mainWindow, SLOT(connectionSucceeded()));
+    QObject::connect(_communicationManager, SIGNAL(protoConnected()),
+                   this, SLOT(connectionSucceeded()));
+    QObject::connect(_communicationManager, SIGNAL(error(QAbstractSocket::SocketError)),
+                   this, SLOT(connectionError(QAbstractSocket::SocketError)));
+    QObject::connect(_communicationManager, SIGNAL(disconnected()),
+                    this, SLOT(connectionDisconnected()));
+
+    // Change communication state
+    QObject::connect(_communicationManager, SIGNAL(protocolError(QString)),
+                     _mainWindow, SLOT(protocolErrorCaught(QString)));
+    QObject::connect(_communicationManager,
+                     SIGNAL(sessionTimeSynchronized(qlonglong)),
+                     _mainWindow,
+                     SLOT(synchronizeSessionTime(qlonglong)));
+    QObject::connect(_communicationManager,
+                     SIGNAL(serverInitCompleted(QString,
+                                                QList<DataDescription*>*,
+                                                QList<ParamDescription*>*,
+                                                QList<StarputopDevice>*)),
+                     _mainWindow, SLOT(initClient(
+                             QString,
+                             QList<DataDescription*>*,
+                             QList<ParamDescription*>*,
+                             QList<StarputopDevice>*)));
+    // Output data
+    QObject::connect(_mainWindow, SIGNAL(clientLaunched()),
+                     _communicationManager, SLOT(sendGoMessage()));
+    QObject::connect(_mainWindow, SIGNAL(dataEnabled(int)),
+                     _communicationManager, SLOT(sendDataEnableMessage(int)));
+    QObject::connect(_mainWindow, SIGNAL(dataDisabled(int)),
+                     _communicationManager, SLOT(sendDataDisableMessage(int)));
+    QObject::connect(_mainWindow, SIGNAL(paramValueUpdated(int,bool)),
+                     _communicationManager, SLOT(sendParamSetMessage(int,bool)));
+    QObject::connect(_mainWindow, SIGNAL(paramValueUpdated(int,int)),
+                     _communicationManager, SLOT(sendParamSetMessage(int,int)));
+    QObject::connect(_mainWindow, SIGNAL(paramValueUpdated(int,double)),
+                     _communicationManager, SLOT(sendParamSetMessage(int,double)));
+    QObject::connect(_mainWindow, SIGNAL(debugEnabled(bool)),
+                     _communicationManager, SLOT(sendDebugEnabledMessage(bool)));
+    QObject::connect(_mainWindow, SIGNAL(debugStepped()),
+                     _communicationManager, SLOT(sendStepMessage()));
+    // Input data
+    QObject::connect(_communicationManager,
+                     SIGNAL(notifyDebugEnabled(bool)),
+                     _mainWindow, SLOT(setDebug(bool)));
+    QObject::connect(_communicationManager,
+                     SIGNAL(notifyDebugMessage(QString)), _mainWindow,
+                     SLOT(setDebugMessage(QString)));
+    QObject::connect(_communicationManager,
+                     SIGNAL(notifyDebugLock(QString)), _mainWindow,
+                     SLOT(setDebugLock(QString)));
+    QObject	::connect(_communicationManager,
+                      SIGNAL(notifyParamUpdate(int,bool,qlonglong)),
+                      _mainWindow, SLOT(updateInteractiveWidget(int,bool,qlonglong)));
+    QObject::connect(_communicationManager, 
+                     SIGNAL(notifyParamUpdate(int,int,qlonglong)),
+                     _mainWindow, SLOT(updateInteractiveWidget(int,int,qlonglong)));
+    QObject::connect(_communicationManager, 
+                     SIGNAL(notifyParamUpdate(int,double,qlonglong)),
+                     _mainWindow, SLOT(updateInteractiveWidget(int,double,qlonglong)));
+    QObject::connect(_communicationManager, 
+                     SIGNAL(notifyTaskPrevUpdate(int,int,qlonglong,qlonglong,qlonglong)),
+                     _mainWindow,
+                     SLOT(updateTaskPrev(int,int,qlonglong,qlonglong,qlonglong)));
+    QObject::connect(_communicationManager, 
+                     SIGNAL(notifyTaskStartUpdate(int,int,qlonglong)),
+                     _mainWindow, SLOT(updateTaskStart(int,int,qlonglong)));
+    QObject::connect(_communicationManager, 
+                     SIGNAL(notifyTaskEndUpdate(int,qlonglong)),
+                     _mainWindow, SLOT(updateTaskEnd(int,qlonglong)));
+    QObject::connect(_communicationManager, 
+                     SIGNAL(notifyDataUpdate(int,bool,qlonglong)),
+                     _mainWindow, SLOT(updateDataWidget(int,bool,qlonglong)));
+    QObject::connect(_communicationManager, 
+                     SIGNAL(notifyDataUpdate(int,int,qlonglong)),
+                     _mainWindow, SLOT(updateDataWidget(int,int,qlonglong)));
+    QObject::connect(_communicationManager, 
+                     SIGNAL(notifyDataUpdate(int,double,qlonglong)),
+                     _mainWindow, SLOT(updateDataWidget(int,double,qlonglong)));
+
+    _communicationManager->connectToHost(_configurationManager->serverHost(),
+                                         _configurationManager->serverPort());
+}
+
+void CommunicationThread::run()
+{
+    if(_configurationManager->ssh())
+        {
+                _connectionAttemptsCount = 0;
+                QString commandLine;
+
+                #ifdef WIN32
+                commandLine.append("cmd /c start ");
+                #else
+                commandLine.append("xterm -e ");
+                #endif
+
+                commandLine.append(_configurationManager->commandLine());
+
+                qDebug() << "CommunicationThread : executing SSH command line : "
+                        << commandLine;
+
+                _SSHProcess = new QProcess();
+                _SSHProcess->start(commandLine);
+        }
+
+
+    createNewCommunicationManager();
+
+    exec();
+}
+
+void CommunicationThread::connectionError(QAbstractSocket::SocketError error)
+{
+    qDebug() << "CommunicationThread : connection error occured" << error;
+
+    switch (error)
+    {
+    case QAbstractSocket::ConnectionRefusedError:
+        if (_configurationManager->ssh()) {
+            if (_connectionAttemptsCount++ <= MAX_CONNECTION_ATTEMPTS) {
+                qDebug() << "refused, retrying";
+                emit progress(tr("Connecting refused, retrying (") + QString::number(_connectionAttemptsCount)+(")..."));
+                this->sleep(1);
+                _communicationManager->connectToHost(_configurationManager->serverHost(),
+                                                     _configurationManager->serverPort());
+                break;
+            }
+        }
+
+	qDebug() << "Too many retries, giving up";
+
+        emit abort(tr("Connection refused by server (port : ") + QString::number(
+                   _configurationManager->serverPort()) + tr(") !"));
+
+        delete _SSHProcess;
+        exit(1);
+        break;
+
+    case QAbstractSocket::RemoteHostClosedError:
+        if (_connectionAttemptsCount == INT_MAX) {
+            _communicationManager->abort();
+	} else {
+            if (_configurationManager->ssh()) {
+                if (_connectionAttemptsCount++ <= MAX_CONNECTION_ATTEMPTS) {
+                    qDebug() << "closed, retrying";
+                    emit progress(tr("Connecting closed, retrying (") + QString::number(_connectionAttemptsCount)+(")..."));
+                    _communicationManager->abort();
+                    break;
+                }
+            }
+
+            qDebug() << "Too many retries, giving up";
+            emit abort(tr("Server closed the connection !"));
+        }
+
+        delete _SSHProcess;
+        exit(1);
+        break;
+
+
+    case QAbstractSocket::HostNotFoundError:
+        emit abort(tr("Server not found (host name : ")
+                + _configurationManager->serverHost() + tr(") !"));
+        delete _SSHProcess;
+        exit(1);
+        break;
+
+    default:
+        emit abort(tr("Connection to server is broken !"));
+        delete _SSHProcess;
+        exit(1);
+    }
+}
+
+
+void CommunicationThread::connectionSucceeded()
+{
+    /* Connected at application level, do not try to reconnect on closure */
+    _connectionAttemptsCount = INT_MAX;
+}
+
+void CommunicationThread::connectionDisconnected()
+{
+    if (_connectionAttemptsCount == INT_MAX) {
+        /* Only raise to mainWindow if we had connected */
+        emit disconnected();
+    } else {
+        /* Just closing for a retry, do retry */
+        qDebug() << "and retrying";
+        this->sleep(1);
+        createNewCommunicationManager();
+    }
+}

+ 72 - 0
starpu-top/communicationthread.h

@@ -0,0 +1,72 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef COMMUNICATIONTHREAD_H
+#define COMMUNICATIONTHREAD_H
+
+class MainWindow;
+class ConfigurationManager;
+class CommunicationManager;
+
+#include <QThread>
+#include <QProcess>
+#include <QTcpSocket>
+
+class CommunicationThread : public QThread
+{
+    Q_OBJECT
+public:
+    CommunicationThread(
+            MainWindow *mainWindow,
+            ConfigurationManager *configurationManager);
+    ~CommunicationThread();
+
+    // Thread execution loop
+    void run();
+
+private:
+    // Linked components
+    MainWindow *_mainWindow;
+    ConfigurationManager *_configurationManager;
+    CommunicationManager *_communicationManager;
+
+    QProcess * _SSHProcess;
+    int _connectionAttemptsCount;
+
+    void createNewCommunicationManager(void);
+
+private slots:
+    void connectionError(QAbstractSocket::SocketError error);
+    void connectionSucceeded();
+    void connectionDisconnected();
+
+signals:
+    void SocketError(QAbstractSocket::SocketError);
+    void progress(QString message);
+    void abort(QString message);
+    void disconnected();
+};
+
+#endif // COMMUNICATIONTHREAD_H

+ 114 - 0
starpu-top/configurationmanager.cpp

@@ -0,0 +1,114 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "configurationmanager.h"
+
+#include <QDebug>
+
+ConfigurationManager::ConfigurationManager()
+{
+    static bool instanciated = false;
+
+    Q_ASSERT_X(instanciated == false, "ConfigurationManager's' constructor",
+               "Singleton pattern violated - "
+               "ConfigurationManager instanciated more than once");
+
+    qDebug() << "ConfigurationManager : initializing";
+
+    // Init settings
+    _applicationSettings = new QSettings(CONFIG_FILE_DIR+"/"+CONFIG_FILE_NAME,
+                                         QSettings::IniFormat);
+
+    instanciated = true;
+}
+
+ConfigurationManager::~ConfigurationManager()
+{
+    qDebug() << "ConfigurationManager : terminating";
+
+    delete _applicationSettings;
+}
+
+// Getters
+QString ConfigurationManager::serverHost() const
+{
+    return _applicationSettings->value("connection/serverhost",
+                                       QString("localhost")).toString();
+}
+
+int ConfigurationManager::serverPort() const
+{
+    return _applicationSettings->value("connection/serverport", 2011).toInt();
+}
+
+bool ConfigurationManager::ssh() const
+{
+    return _applicationSettings->value("connection/ssh", false).toBool();
+}
+
+QString ConfigurationManager::commandLine() const
+{
+    return _applicationSettings->value("connection/commandline",
+                                       QString("ssh -L")).toString();
+}
+
+bool ConfigurationManager::antialiasing() const
+{
+    return _applicationSettings->value("display/antialiasing", true).toBool();
+}
+
+// Setters
+void ConfigurationManager::setServerHost(QString serverIP)
+{
+    _applicationSettings->setValue("connection/serverhost", serverIP);
+}
+
+void ConfigurationManager::setServerPort(int serverPort)
+{
+    _applicationSettings->setValue("connection/serverport", serverPort);
+}
+
+void ConfigurationManager::setSSH(bool enabled)
+{
+    _applicationSettings->setValue("connection/ssh", enabled);
+}
+
+void ConfigurationManager::setCommandLine(QString commandLine)
+{
+    _applicationSettings->setValue("connection/commandline", commandLine);
+}
+
+void ConfigurationManager::setAntialiasing(bool enabled)
+{
+    _applicationSettings->setValue("display/antialiasing", enabled);
+}
+
+// Other methods
+void ConfigurationManager::syncConfiguration()
+{
+    qDebug() << "ConfigurationManager : synchronizing application settings";
+
+    _applicationSettings->sync();
+}

+ 63 - 0
starpu-top/configurationmanager.h

@@ -0,0 +1,63 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef CONFIGURATIONMANAGER_H
+#define CONFIGURATIONMANAGER_H
+
+#include <QSettings>
+
+static const QString CONFIG_FILE_DIR = ".";
+static const QString CONFIG_FILE_NAME = "starputop.cfg";
+
+class ConfigurationManager
+{ /* Contains and manages all the application settings
+of the current instance, and remembers them for use
+in the next instances */
+
+public:
+    ConfigurationManager();
+    ~ConfigurationManager();
+
+    // Getters
+    QString serverHost() const;
+    int serverPort() const;
+    bool ssh() const;
+    QString commandLine() const;
+    bool antialiasing() const;
+    // Setters
+    void setServerHost(QString serverIP);
+    void setServerPort(int serverPort);
+    void setSSH(bool enabled);
+    void setCommandLine(QString commandLine);
+    void setAntialiasing(bool enabled);
+    // Other methods
+    void syncConfiguration();
+
+private:
+    // Data
+    QSettings *_applicationSettings;
+};
+
+#endif // CONFIGURATIONMANAGER_H

+ 397 - 0
starpu-top/dataaggregatorwidget.cpp

@@ -0,0 +1,397 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "dataaggregatorwidget.h"
+#include "mainwindow.h"
+#include "widgetwindowsmanager.h"
+#include "datawidget.h"
+#include "configurationmanager.h"
+#include <qwt_plot_item.h>
+#include <qwt_plot_curve.h>
+#include <qwt_legend.h>
+#include <qwt_plot.h>
+#include <QToolBar>
+#include <QVBoxLayout>
+#include <QCloseEvent>
+
+DataAggregatorWidget::DataAggregatorWidget(
+        WidgetWindowsManager *widgetWindowsManager, MainWindow *mainWindow,
+        bool inside, QList<int> dataIds) :
+	AbstractWidgetWindow(widgetWindowsManager, mainWindow, inside)
+{
+    // Init UI
+    setWindowTitle(tr("Aggregator"));
+    setWindowIcon(QIcon(":/images/widget.png"));
+    // Buttons
+    QToolBar *buttonsToolBar = new QToolBar();
+    // In/out button
+    buttonsToolBar->addWidget(_inOutButton);
+    // Add data button
+    _addDataButton = new QToolButton();
+    _addDataButton->setIcon(QIcon(":/images/add.png"));
+    _addDataButton->setPopupMode(QToolButton::InstantPopup);
+    _addDataButton->setToolTip(tr("Add data source"));
+    buttonsToolBar->addSeparator();
+    buttonsToolBar->addWidget(_addDataButton);
+    // Remove data button
+    _removeDataButton = new QToolButton();
+    _removeDataButton->setIcon(QIcon(":/images/remove.png"));
+    _removeDataButton->setPopupMode(QToolButton::InstantPopup);
+    _removeDataButton->setToolTip(tr("Remove data source"));
+    buttonsToolBar->addWidget(_removeDataButton);
+    // Set layout
+    QVBoxLayout *layout = new QVBoxLayout();
+    setLayout(layout);
+    layout->addWidget(buttonsToolBar);
+
+    // Init actions
+    for (int i = 0; i < _mainWindow->dataDescriptions()->count(); i++)
+    {
+        if (_mainWindow->dataDescriptions()->at(i)->type != DATA_TYPE_BOOL)
+        {
+            QAction *addDataAction = new QAction(
+                    _mainWindow->dataDescriptions()->at(i)->descriptionString,
+                    _addDataButton);
+            addDataAction->setData(_mainWindow->dataDescriptions()->at(i)->id);
+
+            QObject::connect(addDataAction, SIGNAL(triggered()), this,
+                             SLOT(dataAdded()));
+
+            if (_mainWindow->dataDescriptions()->at(i)->widget
+                == DATA_WIDGET_NONE)
+            {
+                addDataAction->setEnabled(false);
+            }
+            _addDataButton->addAction(addDataAction);
+        }
+    }
+
+    // Init curve colors
+    _curveColors.append(Qt::black);
+    _curveColors.append(Qt::red);
+    _curveColors.append(Qt::green);
+    _curveColors.append(Qt::blue);
+    _curveColors.append(Qt::magenta);
+    _curveColors.append(Qt::yellow);
+    _curveColors.append(Qt::gray);
+    _curveColors.append(Qt::darkRed);
+    _curveColors.append(Qt::darkGreen);
+    _curveColors.append(Qt::darkBlue);
+    _curveColors.append(Qt::darkCyan);
+    _curveColors.append(Qt::darkMagenta);
+    _curveColors.append(Qt::darkYellow);
+    _curveColors.append(Qt::cyan);
+    _colorIterator = new QListIterator<QColor> (_curveColors);
+
+    // Create internal widget
+    createInternalWidget();
+
+    // Know when a data source is disabled / enabled
+    QObject::connect(_mainWindow, SIGNAL(dataDisabled(int)),
+                     this, SLOT(disableData(int)));
+    QObject::connect(_mainWindow, SIGNAL(dataEnabled(int)),
+                     this, SLOT(enableData(int)));
+
+    // Init data
+    if (dataIds.empty() == false)
+    {
+        for (int i = 0; i < dataIds.count(); i++)
+        {
+            addData(dataIds.at(i));
+        }
+    }
+
+    // Setup automatic cleanup
+    QObject::connect(this, SIGNAL(destroyed()), _mainWindow,
+                     SLOT(removeDestroyedDataAggregatorWidgets()));
+
+    qDebug() << "DataAggregatorWidget" << windowId() << ": initializing";
+}
+
+DataAggregatorWidget::~DataAggregatorWidget()
+{
+    delete _colorIterator;
+    delete _addDataButton;
+    delete _removeDataButton;
+    delete _plot;
+
+    qDebug() << "DataAggregatorWidget" << windowId() << ": terminating";
+}
+
+void DataAggregatorWidget::closeEvent(QCloseEvent *ce)
+{
+    ce->accept();
+}
+
+void DataAggregatorWidget::createInternalWidget()
+{
+    _plot = new QwtPlot(QwtText(tr("Aggregator")));
+    QwtLegend *legend = new QwtLegend;
+    legend->setItemMode(QwtLegend::CheckableItem);
+    _plot->insertLegend(legend, QwtPlot::BottomLegend);
+    _plot->setMinimumSize(300, 200);
+    _plot->setAttribute(Qt::WA_DeleteOnClose);
+    layout()->addWidget(_plot);
+
+    QObject::connect(_plot, SIGNAL(legendChecked(QwtPlotItem *, bool)),
+                     SLOT(curveChecked(QwtPlotItem *, bool)));
+}
+
+void DataAggregatorWidget::addData(int dataId)
+{
+    DataWidget *dataWidget = _mainWindow->dataWidgetFromDataId(dataId);
+    if (dataWidget != 0)
+    {
+        qDebug() << "Aggregator" << _windowId << ": adding new data of id"
+                << dataId;
+
+        switch (dataWidget->description()->type)
+        {
+        case DATA_TYPE_INT:
+            {
+                QObject::connect(dataWidget, SIGNAL(valueChanged(int,int)),
+                                 this, SLOT(update(int,int)));
+                break;
+            }
+
+        case DATA_TYPE_FLOAT:
+            {
+                QObject::connect(dataWidget, SIGNAL(valueChanged(double,int)),
+                                 this, SLOT(update(double,int)));
+                break;
+            }
+
+        default:
+            qDebug() << "Aggregator" << _windowId
+                    << ": attempt to add data of unsupported type (id :"
+                    << dataId << ")";
+        }
+
+        QwtPlotCurve *curve = new QwtPlotCurve(
+                _mainWindow->dataDescriptionFromId(dataId)->descriptionString);
+        if (_mainWindow->configurationManager()->antialiasing() == true)
+        {
+            curve->setRenderHint(QwtPlotItem::RenderAntialiased);
+        }
+        QColor c;
+        if (_colorIterator->hasNext())
+        {
+            c = _colorIterator->next();
+            c.setAlpha(150);
+            curve->setPen(c);
+        }
+        _curves.insert(dataId, curve);
+        CurveData curveData;
+        curveData.xData = new QVector<double> ();
+        curveData.yData = new QVector<double> ();
+        _curvesData.insert(dataId, curveData);
+        curve->attach(_plot);
+    }
+    else
+    {
+        qDebug() << "Aggregator" << _windowId << ": failed to add data of id"
+                << dataId;
+    }
+}
+
+void DataAggregatorWidget::removeData(int dataId)
+{
+    DataWidget *dataWidget = _mainWindow->dataWidgetFromDataId(dataId);
+    if (dataWidget != 0)
+    {
+        qDebug() << "Aggregator" << _windowId << ": removing data of id"
+                << dataId;
+
+        switch (dataWidget->description()->type)
+        {
+        case DATA_TYPE_INT:
+            QObject::disconnect(dataWidget, SIGNAL(valueChanged(int,int)),
+                                this, SLOT(update(int,int)));
+            break;
+
+        case DATA_TYPE_FLOAT:
+            QObject::disconnect(dataWidget, SIGNAL(valueChanged(double,int)),
+                                this, SLOT(update(double,int)));
+            break;
+
+        default:
+            ;
+        }
+
+        _curves.value(dataId)->detach();
+        _curvesData.remove(dataId);
+        _curves.remove(dataId);
+    }
+    else
+    {
+        qDebug() << "Aggregator" << _windowId
+                << ": failed to remove data of id" << dataId;
+    }
+}
+
+void DataAggregatorWidget::update(int value, int dataId)
+{
+    qDebug() << "Aggregator" << _windowId << ": updating data of id" << dataId
+            << "with value" << value;
+
+    _curvesData.value(dataId).xData->append(_mainWindow
+                                            ->effectiveRunningTime());
+    _curvesData.value(dataId).yData->append(value);
+#if QWT_VERSION >= 0x060000
+    _curves.value(dataId)->setRawSamples(
+            _curvesData.value(dataId).xData->data(),
+            _curvesData.value(dataId).yData->data(),
+            _curvesData.value(dataId).xData->size());
+#else
+#  warning Old version of qwt being used, data aggregator will not work.
+#endif
+    _plot->replot();
+}
+
+void DataAggregatorWidget::update(double value, int dataId)
+{
+    qDebug() << "Aggregator" << _windowId << ": updating data of id" << dataId
+            << "with value" << value;
+
+    _curvesData.value(dataId).xData->append(_mainWindow
+                                            ->effectiveRunningTime());
+    _curvesData.value(dataId).yData->append(value);
+#if QWT_VERSION >= 0x060000
+    _curves.value(dataId)->setRawSamples(
+            _curvesData.value(dataId).xData->data(),
+            _curvesData.value(dataId).yData->data(),
+            _curvesData.value(dataId).xData->size());
+#else
+#  warning Old version of qwt being used, data aggregator will not work.
+#endif
+    _plot->replot();
+}
+
+QSize DataAggregatorWidget::minimumInternalWidgetSize() const
+{
+    return _plot->minimumSize();
+}
+
+QList<int> DataAggregatorWidget::aggregatedData() const
+{
+    QList<int> addedData;
+
+    for (int i = 0; i < _curves.values().count(); i++)
+    {
+        addedData.append(_curves.key(_curves.values().at(i)));
+    }
+
+    return addedData;
+}
+
+void DataAggregatorWidget::curveChecked(QwtPlotItem *curve, bool checked)
+{
+    curve->setVisible(!checked);
+}
+
+void DataAggregatorWidget::dataAdded()
+{
+    QAction *action = (QAction*) QObject::sender();
+    int dataId = action->data().toInt();
+
+    _addDataButton->removeAction(action);
+    addData(dataId);
+
+    QAction *removeDataAction = new QAction(
+            _mainWindow->dataDescriptionFromId(dataId)->descriptionString,
+            _removeDataButton);
+    removeDataAction->setData(dataId);
+    QObject::connect(removeDataAction, SIGNAL(triggered()), this,
+                     SLOT(dataRemoved()));
+    _removeDataButton->addAction(removeDataAction);
+}
+
+void DataAggregatorWidget::dataRemoved()
+{
+    QAction *action = (QAction*) QObject::sender();
+    int dataId = action->data().toInt();
+
+    _removeDataButton->removeAction(action);
+    removeData(dataId);
+
+    QAction *addDataAction = new QAction(
+            _mainWindow->dataDescriptionFromId(dataId)->descriptionString,
+            _addDataButton);
+    addDataAction->setData(dataId);
+    QObject::connect(addDataAction, SIGNAL(triggered()), this,
+                     SLOT(dataAdded()));
+    _addDataButton->addAction(addDataAction);
+}
+
+void DataAggregatorWidget::disableData(int dataId)
+{
+    // Search the action on the add button
+    for (int i = 0; i < _addDataButton->actions().count(); i++)
+    {
+        if (_addDataButton->actions().at(i)->data().toInt() == dataId)
+        {
+            _addDataButton->actions().at(i)->setEnabled(false);
+
+            return;
+        }
+    }
+    // If not found, it has already been added
+    for (int i = 0; i < _removeDataButton->actions().count(); i++)
+    {
+        if (_removeDataButton->actions().at(i)->data().toInt() == dataId)
+        {
+            _removeDataButton->removeAction(_removeDataButton->actions().at(i));
+            removeData(dataId);
+
+            QAction
+                    *action =
+                    new QAction(
+                            _mainWindow->dataDescriptionFromId(dataId)
+                            ->descriptionString,
+                            _addDataButton);
+            action->setData(dataId);
+            QObject::connect(action, SIGNAL(triggered()), this,
+                             SLOT(dataAdded()));
+            action->setEnabled(false);
+            _addDataButton->addAction(action);
+
+            return;
+        }
+    }
+}
+
+void DataAggregatorWidget::enableData(int dataId)
+{
+    // Search the action on the add button
+    for (int i = 0; i < _addDataButton->actions().count(); i++)
+    {
+        if (_addDataButton->actions().at(i)->data().toInt() == dataId)
+        {
+            _addDataButton->actions().at(i)->setEnabled(true);
+
+            return;
+        }
+    }
+}

+ 89 - 0
starpu-top/dataaggregatorwidget.h

@@ -0,0 +1,89 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef DATAAGGREGATORWIDGET_H
+#define DATAAGGREGATORWIDGET_H
+
+class MainWindow;
+class WidgetWindowsManager;
+class QwtPlotItem;
+class QwtPlotCurve;
+class QwtPlot;
+
+#include <QHash>
+#include <QAction>
+#include "starputoptypes.h"
+#include "abstractwidgetwindow.h"
+
+class DataAggregatorWidget : public AbstractWidgetWindow
+{ /* Aggregates data from different data sources so they can
+     be easily compared. Each data source is displayed as a curve
+     in a plot widget. */
+    Q_OBJECT
+
+public:
+    explicit DataAggregatorWidget(
+            WidgetWindowsManager *widgetWindowsManager,
+            MainWindow *mainWindow,
+            bool inside = false,
+            QList<int> dataIds = QList<int>());
+    ~DataAggregatorWidget();
+
+    // Getters
+    QSize minimumInternalWidgetSize() const;
+    QList<int> aggregatedData() const;
+
+private:
+    // Metadata
+    // Curve colors
+    QList<QColor> _curveColors;
+    QListIterator<QColor> *_colorIterator;
+    // Bound data descriptions
+    QHash<int, QwtPlotCurve*> _curves;
+    QHash<int, CurveData> _curvesData;
+    // GUI components
+    QToolButton *_addDataButton;
+    QToolButton *_removeDataButton;
+    QwtPlot *_plot;
+
+    // Events
+    void closeEvent(QCloseEvent *ce);
+
+public slots:
+    void addData(int dataId);
+    void removeData(int dataId);
+
+private slots:
+    void createInternalWidget();
+    void update(int value, int dataId);
+    void update(double value, int dataId);
+    void curveChecked(QwtPlotItem *curve, bool checked);
+    void dataAdded();
+    void dataRemoved();
+    void disableData(int dataId);
+    void enableData(int dataId);
+};
+
+#endif // DATAAGGREGATORWIDGET_H

+ 445 - 0
starpu-top/datawidget.cpp

@@ -0,0 +1,445 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "datawidget.h"
+#include "mainwindow.h"
+#include "widgetwindowsmanager.h"
+#include "configurationmanager.h"
+#include <qwt_thermo.h>
+#include <qwt_plot.h>
+#include <qwt_dial.h>
+#include <qwt_dial_needle.h>
+#include <qwt_plot_curve.h>
+#include <qwt_plot.h>
+#include "qledindicator/qledindicator.h"
+#include <QAction>
+#include <QCloseEvent>
+#include <QLCDNumber>
+#include <QCheckBox>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+
+DataWidget::DataWidget(DataDescription *dataDescription,
+                       WidgetWindowsManager *widgetWindowsManager,
+                       MainWindow *mainWindow,
+                       bool inside) :
+AbstractWidgetWindow(widgetWindowsManager, mainWindow, inside)
+{
+    _dataDescription = dataDescription;
+    _internalWidget = 0;
+    // For the plot widget
+    _curve = 0;
+    _curveData = 0;
+
+    _dataWidgetNames = _mainWindow->dataWidgetNames();
+    _dataWidgetPossibilities = _mainWindow->dataWidgetPossibilities() ->value(
+            _dataDescription->type).values();
+
+    // Init context menu actions
+    QActionGroup *actionGroup = new QActionGroup(this);
+    for (int i = 0; i < _dataWidgetPossibilities.count(); i++)
+    {
+        QAction *action = new QAction(
+                _dataWidgetNames ->value(_dataWidgetPossibilities.at(i)),
+                actionGroup);
+        action->setCheckable(true);
+        if (_dataWidgetPossibilities.at(i) == _dataDescription->widget)
+        {
+            action->setChecked(true);
+        }
+        QObject::connect(action, SIGNAL(triggered()), this,
+                         SLOT(widgetTypeChanged()));
+        actionGroup->addAction(action);
+    }
+    addActions(actionGroup->actions());
+
+    // Set attributes
+    setContextMenuPolicy(Qt::ActionsContextMenu);
+
+    // Init GUI
+    setWindowTitle(_dataDescription->descriptionString);
+    setWindowIcon(QIcon(":/images/widget.png"));
+    // Set layout
+    QVBoxLayout *globalLayout = new QVBoxLayout();
+    setLayout(globalLayout);
+    QHBoxLayout *topLayout = new QHBoxLayout();
+    topLayout->addWidget(_inOutButton);
+    QString labelText = _dataDescription->descriptionString;
+    if (_dataDescription->descriptionString.size() > 14)
+    {
+        labelText.truncate(12);
+        labelText.append("...");
+    }
+    QLabel *dataTitle = new QLabel(labelText);
+    dataTitle->setToolTip(_dataDescription->descriptionString);
+    topLayout->addWidget(dataTitle, 0, Qt::AlignHCenter);
+    dataTitle->setFixedHeight(dataTitle->sizeHint().height());
+    globalLayout->addLayout(topLayout);
+
+    // Create internal widget
+    createInternalWidget();
+
+    setParent(0); // Needed if it is a flying window
+    // Will be updated anyway if it goes into the MDI area
+    // However the object HAS to be constructed with the main window as parent
+    // so it can connect to its slots.
+
+    // Setup automatic cleanup
+    QObject::connect(this, SIGNAL(destroyed()), _mainWindow,
+                     SLOT(removeDestroyedDataWidgets()));
+
+    qDebug() << "DataWidget : initializing [desc"
+            << _dataDescription->descriptionString << "; id"
+            << _dataDescription->id << "; type" << _dataDescription->type
+            << "; min" << _dataDescription->valMin << "; max"
+            << _dataDescription->valMax << "; widget"
+            << _dataDescription->widget << "]";
+}
+
+DataWidget::~DataWidget()
+{
+    qDebug() << "DataWidget" << _dataDescription->id << ": terminating";
+
+    delete _internalWidget;
+}
+
+void DataWidget::closeEvent(QCloseEvent *ce)
+{
+    if (isEnabled() == true)
+    {// The widget is alive (session active)
+        _mainWindow->updateDataWidgetType(_dataDescription->id,
+                                          DATA_WIDGET_NONE);
+    }
+
+    ce->accept();
+}
+
+void DataWidget::recreateInternalWidget()
+{
+    if (_internalWidget != 0)
+    {
+        _internalWidget->close();
+        _internalWidget = 0;
+    }
+
+    createInternalWidget();
+
+    adjustSize();
+    if (isInside() == true)
+    {
+        parentWidget()->resize(minimumInternalWidgetSize() + QSize(85, 85));
+    }
+    updateAction(_dataDescription->widget);
+}
+
+void DataWidget::updateAction(DataWidgetType newWidget)
+{
+    for (int i = 0; i < actions().count(); i++)
+    {
+        if (actions().at(i)->text().compare(_dataWidgetNames->value(newWidget))
+            == 0)
+            {
+            actions().at(i)->setChecked(true);
+            return;
+        }
+    }
+}
+
+void DataWidget::createInternalWidget()
+{
+    qDebug() << "Creating the data widget for data id" << _dataDescription->id;
+
+    switch (_dataDescription->widget)
+    {
+    case DATA_WIDGET_LCD:
+	{
+            _internalWidget = new QLCDNumber(this);
+            _internalWidget->setMinimumSize(50, 50);
+            break;
+	}
+
+    case DATA_WIDGET_PLOT:
+	{
+            _internalWidget = new QwtPlot(this);
+            _curve = new QwtPlotCurve(_dataDescription->descriptionString);
+            if (_mainWindow->configurationManager()->antialiasing() == true)
+            {
+                _curve->setRenderHint(QwtPlotItem::RenderAntialiased);
+            }
+            _curve->attach((QwtPlot*) _internalWidget);
+            _curveData = new CurveData;
+            _curveData->xData = new QVector<double> ();
+            _curveData->yData = new QVector<double> ();
+            _internalWidget->setMinimumSize(300, 200);
+            break;
+	}
+
+    case DATA_WIDGET_LEVEL:
+	{
+            _internalWidget = new QwtThermo(this);
+
+            QwtThermo *widget = (QwtThermo*) _internalWidget;
+            widget->setRange(_dataDescription->valMin, _dataDescription->valMax);
+            _internalWidget->setMinimumSize(100, 200);
+            break;
+	}
+
+    case DATA_WIDGET_LED:
+	{
+            _internalWidget = new QLedIndicator(this);
+            _internalWidget->setMinimumSize(50, 50);
+            break;
+	}
+
+    case DATA_WIDGET_DIAL:
+	{
+            _internalWidget = new QwtDial(this);
+            _internalWidget->setMinimumSize(250, 250);
+            QwtDial *widget = (QwtDial*) _internalWidget;
+            widget->setReadOnly(true);
+            widget->setWrapping(false);
+            widget->setOrigin(135.0);
+            widget->setRange(_dataDescription->valMin, _dataDescription->valMax);
+            widget->setScaleArc(0.0, 270.0);
+            widget->scaleDraw()->setSpacing(8);
+            QwtDialSimpleNeedle *needle = new QwtDialSimpleNeedle(
+                    QwtDialSimpleNeedle::Arrow, true, Qt::red,
+                    QColor(Qt::gray).light(130));
+            widget->setNeedle(needle);
+            widget->setScaleOptions(QwtDial::ScaleTicks | QwtDial::ScaleLabel);
+            widget->setScaleTicks(0, 4, 8);
+	}
+
+    default:
+        ;
+    }
+
+    _internalWidget->setAttribute(Qt::WA_DeleteOnClose);
+    layout()->addWidget(_internalWidget);
+}
+
+/* -------------------------------------------------------------------------- */
+/* Getters                                                                    */
+/* -------------------------------------------------------------------------- */
+
+DataDescription *DataWidget::description() const
+{
+    return _dataDescription;
+}
+
+QSize DataWidget::minimumInternalWidgetSize() const
+{
+    return _internalWidget->minimumSize();
+}
+
+/* -------------------------------------------------------------------------- */
+/* Setters                                                                    */
+/* -------------------------------------------------------------------------- */
+
+void DataWidget::setValue(bool value)
+{
+    switch (_dataDescription->widget)
+    {
+    case DATA_WIDGET_LED:
+	{
+            QLedIndicator *widget = qobject_cast<QLedIndicator*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->setChecked(value);
+            }
+            else
+            {
+                qDebug() << "Bad data widget cast (DataWidget::setValue()) !";
+            }
+            break;
+	}
+
+    default:
+        ;
+    }
+
+    emit valueChanged(value, _dataDescription->id);
+}
+
+void DataWidget::setValue(int value)
+{
+    switch (_dataDescription->widget)
+    {
+    case DATA_WIDGET_PLOT:
+	{
+            QwtPlot *widget = qobject_cast<QwtPlot*> (_internalWidget);
+            if (widget != 0)
+            {
+                _curveData->xData->append(_mainWindow->effectiveRunningTime());
+                _curveData->yData->append(value);
+#if QWT_VERSION >= 0x060000
+                _curve->setRawSamples(_curveData->xData->data(),
+                                      _curveData->yData->data(), _curveData->xData->size());
+#else
+#  warning Old version of qwt being used, data aggregator will not work.
+#endif
+                widget->replot();
+            }
+            else
+            {
+                qDebug() << "Bad data widget cast (DataWidget::setValue()) !";
+            }
+            break;
+	}
+
+    case DATA_WIDGET_LCD:
+	{
+            QLCDNumber *widget = qobject_cast<QLCDNumber*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->display(value);
+            }
+            else
+            {
+                qDebug() << "Bad data widget cast (DataWidget::setValue()) !";
+            }
+            break;
+	}
+
+    case DATA_WIDGET_LEVEL:
+	{
+            QwtThermo *widget = qobject_cast<QwtThermo*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->setValue(value);
+            }
+            else
+            {
+                qDebug() << "Bad data widget cast (DataWidget::setValue()) !";
+            }
+            break;
+	}
+
+    case DATA_WIDGET_DIAL:
+	{
+            QwtDial *widget = qobject_cast<QwtDial*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->setValue(value);
+            }
+            else
+            {
+                qDebug() << "Bad data widget cast (DataWidget::setValue()) !";
+            }
+            break;
+	}
+
+    default:
+        ;
+    }
+
+    emit valueChanged(value, _dataDescription->id);
+}
+
+void DataWidget::setValue(double value)
+{
+    switch (_dataDescription->widget)
+    {
+    case DATA_WIDGET_PLOT:
+	{
+            QwtPlot *widget = qobject_cast<QwtPlot*> (_internalWidget);
+            if (widget != 0)
+            {
+                _curveData->xData->append(_mainWindow->effectiveRunningTime());
+                _curveData->yData->append(value);
+#if QWT_VERSION >= 0x060000
+                _curve->setRawSamples(_curveData->xData->data(),
+                                      _curveData->yData->data(), _curveData->xData->size());
+#else
+#  warning Old version of qwt being used, data aggregator will not work.
+#endif
+                widget->replot();
+            }
+            else
+            {
+                qDebug() << "Bad data widget cast (DataWidget::setValue()) !";
+            }
+            break;
+	}
+
+    case DATA_WIDGET_LCD:
+	{
+            QLCDNumber *widget = qobject_cast<QLCDNumber*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->display(value);
+            }
+            else
+            {
+                qDebug() << "Bad data widget cast (DataWidget::setValue()) !";
+            }
+            break;
+	}
+
+    case DATA_WIDGET_LEVEL:
+	{
+            QwtThermo *widget = qobject_cast<QwtThermo*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->setValue(value);
+            }
+            else
+            {
+                qDebug() << "Bad data widget cast (DataWidget::setValue()) !";
+            }
+            break;
+	}
+
+    case DATA_WIDGET_DIAL:
+	{
+            QwtDial *widget = qobject_cast<QwtDial*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->setValue(value);
+            }
+            else
+            {
+                qDebug() << "Bad data widget cast (DataWidget::setValue()) !";
+            }
+            break;
+	}
+
+    default:
+        ;
+    }
+
+    emit valueChanged(value, _dataDescription->id);
+}
+
+void DataWidget::widgetTypeChanged()
+{
+    QAction *action = (QAction*) QObject::sender();
+
+    if(_dataDescription->widget != _dataWidgetNames->key(action->text()))
+    {
+        _mainWindow->updateDataWidgetType(_dataDescription->id,
+                                          _dataWidgetNames->key(action->text()));
+    }
+}

+ 86 - 0
starpu-top/datawidget.h

@@ -0,0 +1,86 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef DATAWIDGET_H
+#define DATAWIDGET_H
+
+class MainWindow;
+class WidgetWindowsManager;
+class QwtPlotCurve;
+class QwtPlot;
+
+#include "starputoptypes.h"
+#include "abstractwidgetwindow.h"
+
+class DataWidget : public AbstractWidgetWindow
+{ /* Displays a single type of data in an internal widget,
+     under different forms defined by the data widget specifications.
+     The internal widget can be changed at any time. */
+    Q_OBJECT
+
+public:
+    explicit DataWidget(
+            DataDescription *dataDescription,
+            WidgetWindowsManager *widgetWindowManager,
+            MainWindow *mainWindow,
+            bool inside = false);
+    ~DataWidget();
+
+    // Getters
+    DataDescription *description() const;
+    QSize minimumInternalWidgetSize() const;
+
+private:
+    // Events
+    void closeEvent(QCloseEvent *ce);
+    // Metadata
+    DataDescription *_dataDescription;
+    const QHash<DataWidgetType, QString> *_dataWidgetNames;
+    QList<DataWidgetType> _dataWidgetPossibilities;
+    // GUI components
+    QWidget *_internalWidget;
+    QwtPlotCurve *_curve;
+    CurveData *_curveData;
+
+public slots:
+    // Setters
+    void setValue(bool value);
+    void setValue(int value);
+    void setValue(double value);
+    // Other methods
+    void recreateInternalWidget();
+
+private slots:
+    void createInternalWidget();
+    void widgetTypeChanged();
+    void updateAction(DataWidgetType newWidget);
+
+signals:
+    void valueChanged(bool value, int dataId);
+    void valueChanged(int value, int dataId);
+    void valueChanged(double value, int dataId);
+};
+
+#endif // DATAWIDGET_H

+ 67 - 0
starpu-top/debugconsole.cpp

@@ -0,0 +1,67 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "debugconsole.h"
+#include "ui_debugconsole.h"
+
+DebugConsole::DebugConsole(QWidget *parent) :
+        QWidget(parent),
+        ui(new Ui::DebugConsole)
+{
+    ui->setupUi(this);
+
+    ui->stepButton->setEnabled(false);
+    QObject::connect(ui->stepButton, SIGNAL(clicked()),
+                     this, SLOT(step()));
+}
+
+DebugConsole::~DebugConsole()
+{
+    delete ui;
+}
+
+void DebugConsole::appendDebugLogMessage(QString debugMessage)
+{
+    ui->console->append("INFO : " + debugMessage);
+}
+
+void DebugConsole::appendDebugLockMessage(QString lockMessage)
+{
+    ui->stepButton->setEnabled(true);
+
+    ui->console->append("LOCK : " + lockMessage);
+}
+
+void DebugConsole::clearConsole()
+{
+    ui->console->clear();
+}
+
+void DebugConsole::step()
+{
+    ui->stepButton->setEnabled(false);
+
+    emit stepped();
+}

+ 61 - 0
starpu-top/debugconsole.h

@@ -0,0 +1,61 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef DEBUGCONSOLE_H
+#define DEBUGCONSOLE_H
+
+#include <QWidget>
+
+namespace Ui {
+    class DebugConsole;
+}
+
+class DebugConsole : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit DebugConsole(QWidget *parent);
+    ~DebugConsole();
+
+    // Display debug message
+    void appendDebugLogMessage(QString debugMessage);
+    void appendDebugLockMessage(QString lockMessage);
+    // Clear console
+    void clearConsole();
+
+private:
+    // GUI components
+    Ui::DebugConsole *ui;
+
+private slots:
+    // Perform a debug step (unlock)
+    void step();
+
+signals:
+    // Step performed
+    void stepped();
+};
+
+#endif // DEBUGCONSOLE_H

+ 41 - 0
starpu-top/debugconsole.ui

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DebugConsole</class>
+ <widget class="QWidget" name="DebugConsole">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>710</width>
+    <height>50</height>
+   </rect>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>500</width>
+    <height>50</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QTextEdit" name="console">
+     <property name="readOnly">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="QPushButton" name="stepButton">
+     <property name="text">
+      <string>Step</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 884 - 0
starpu-top/ganttwidget.cpp

@@ -0,0 +1,884 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "ganttwidget.h"
+#include "mainwindow.h"
+#include "taskmanager.h"
+#include <math.h>
+#include <QtOpenGL>
+#include <QTimer>
+#include <sstream>
+
+const int MAX_CPU_NUM = 6;
+const int MAX_GPU_NUM = 3;
+const int MARGIN = 5;
+const int DEFAULT_TIME_TOTAL = 20000;
+const int HEIGHT_TIME_AXIS = 20;
+const int WIDTH_GLOBAL_PU = 50; // Width of the big CPU rect
+const int WIDTH_PROGRAM = 50;
+const int WIDTH_PU = 70;
+const int GRAD_NUM = 5; // Number of gradations between each label
+const int WIDTH_PRESENT_LINE = 1;
+const int SIGNIF_NUM = 100;
+const int FIRST_THRESHOLD = 25;
+const int SECOND_THRESHOLD = 75;
+const int SHIFT_LEFT_TIME_AXIS = 3;
+const int SHIFT_TOP_TIME_AXIS = 3;
+
+const QColor GANTT_BACKGROUND_COLOR = Qt::gray;
+const QFont::StyleHint GANTT_TEXT_FONT = QFont::Times;
+const QColor GANTT_TEXT_COLOR = Qt::white;
+const QColor GANTT_PU_COLOR = Qt::blue;
+const QColor GANTT_TIMELINE_COLOR = Qt::blue;
+const QColor GANTT_PRESENTLINE_COLOR = Qt::black;
+const QColor GANTT_IDLE_COLOR = Qt::red;
+const QColor GANTT_WORKING_COLOR = Qt::green;
+const QColor GANTT_PREV_COLOR = Qt::yellow;
+
+GanttWidget::GanttWidget(MainWindow *mainWindow, TaskManager *taskManager) :
+	QGLWidget(QGLFormat(QGL::SampleBuffers), mainWindow)
+{
+    _mainWindow = mainWindow;
+    _taskManager = taskManager;
+
+    setAutoFillBackground(false);
+    _background = QBrush(GANTT_BACKGROUND_COLOR);
+    _textPen = QPen(GANTT_TEXT_COLOR);
+    _textFont.setPixelSize(50);
+    _textFont.setStyleHint(GANTT_TEXT_FONT);
+
+    _coordxPresentLine = 0;
+    _numPUs = 0;
+    _wasRunning = false;
+    _timeTotal = DEFAULT_TIME_TOTAL;
+    _timeBefore = _timeTotal * 0.66;
+    _timeAfter = _timeTotal * 0.34;
+    _lastValPrevLine = 66;
+    _timePresent = 0;
+    _timeToShow = 0;
+    _numCPUs = 0;
+    _numGPUs = 0;
+    _heightPU = 0;
+    _initCompleted = false;
+    _PUsByDevice = 0;
+    _PUsByPos = 0;
+
+    // Start display update timer
+    _timer = new QTimer(this);
+    _timer->start(35);
+
+    // Connect events
+    QObject::connect(_mainWindow, SIGNAL(sessionOpened()),
+                     this, SLOT(connected()));
+    QObject::connect(_mainWindow, SIGNAL(sessionClosed()),
+                     this, SLOT(disconnected()));
+    QObject::connect(_mainWindow, SIGNAL(debugLocked()),
+                     this, SLOT(ganttLocked()));
+    QObject::connect(_mainWindow, SIGNAL(debugStepped()),
+                     this, SLOT(ganttUnlocked()));
+    QObject::connect(_timer, SIGNAL(timeout()),
+                     this, SLOT(update()));
+}
+
+GanttWidget::~GanttWidget()
+{
+    delete _timer;
+    delete _rectPUs;
+}
+
+void GanttWidget::defaultScreen(QPainter *painter)
+{
+    painter->setPen(GANTT_TEXT_COLOR);
+    drawPresentLine(painter);
+    drawTime(painter);
+}
+
+// Called each time the window is resized
+void GanttWidget::resizeGL(int width, int height)
+{
+    update();
+}
+
+void GanttWidget::paintEvent(QPaintEvent *event)
+{
+    QPainter painter;
+    painter.begin(this);
+    painter.setRenderHint(QPainter::Antialiasing);
+    paint(&painter, event);
+    painter.end();
+}
+
+/* Draw CPU and GPU rects */
+void GanttWidget::drawPUs(QPainter *painter)
+{
+    QFont f;
+    QPen penRect;
+    QPen penText;
+    QPointF coordTxt;
+    QString txt;
+    QStaticText name;
+
+    f.setFamily("utf8");
+    f.setWeight(QFont::Bold);
+    f.setPixelSize(12);
+    painter->setFont(f);
+    penRect.setColor(GANTT_PU_COLOR);
+    penText.setColor(GANTT_TEXT_COLOR);
+    painter->setPen(penRect);
+    _rectPUs = new QRectF[_numCPUs + _numGPUs];
+    int height_allowed = size().height() - HEIGHT_TIME_AXIS - MARGIN;
+    // height of each processor unit rectangles
+    int height = height_allowed / (_numCPUs + _numGPUs);
+    _heightPU = height;
+    int height_cpublock = height * _numCPUs;
+    int height_gpublock = height * _numGPUs;
+
+    /* The CPUs rect */
+    if (_numCPUs > 0)
+    {
+        _rectCPUblock = QRectF(WIDTH_PROGRAM + MARGIN,
+                               HEIGHT_TIME_AXIS + MARGIN, WIDTH_GLOBAL_PU,
+                               height_cpublock - MARGIN);
+        painter->drawRect(_rectCPUblock);
+        painter->fillRect(_rectCPUblock, GANTT_PU_COLOR);
+        painter->setPen(penText);
+        coordTxt = QPointF(
+                _rectCPUblock.center().rx() - (WIDTH_GLOBAL_PU / 2) + 3,
+                _rectCPUblock.center().ry() - f.pixelSize());
+        txt = QString("CPU(s)");
+        name = QStaticText(txt);
+        name.setPerformanceHint(QStaticText::AggressiveCaching);
+
+        painter->drawStaticText(coordTxt, name);
+    }
+
+    f.setWeight(QFont::Light);
+    f.setPixelSize(10);
+    painter->setFont(f);
+    painter->setPen(penRect);
+
+    /* devices */
+    for (int i = 0; i < _numCPUs + _numGPUs; i++)
+    {
+        painter->setPen(penRect);
+        _rectPUs[i] = QRectF(WIDTH_PROGRAM + MARGIN + WIDTH_GLOBAL_PU + MARGIN,
+                             HEIGHT_TIME_AXIS + MARGIN + i * height, WIDTH_PU,
+                             height - MARGIN);
+        painter->drawRect(_rectPUs[i]);
+        painter->fillRect(_rectPUs[i], Qt::blue);
+        painter->setPen(penText);
+        if (_heightPU >= f.pixelSize() * 2)
+        {
+            painter->drawText(_rectPUs[i], Qt::AlignVCenter, _PUsByPos[i].name);
+        }
+    }
+
+    f.setFamily("utf8");
+    f.setWeight(QFont::Bold);
+    f.setPixelSize(12);
+    painter->setFont(f);
+    painter->setPen(penRect);
+    /* The GPUs rect */
+    if (_numGPUs > 0)
+    {
+        _rectGPUblock = QRectF(WIDTH_PROGRAM + MARGIN,
+                               HEIGHT_TIME_AXIS + MARGIN + height_cpublock, WIDTH_GLOBAL_PU,
+                               height_gpublock - MARGIN);
+        painter->drawRect(_rectGPUblock);
+        painter->fillRect(_rectGPUblock, Qt::blue);
+        coordTxt = QPointF(
+                _rectGPUblock.center().rx() - (WIDTH_GLOBAL_PU / 2) + 3,
+                _rectGPUblock.center().ry() - f.pixelSize());
+        txt = QString("GPU(s)");
+        name = QStaticText(txt);
+        name.setPerformanceHint(QStaticText::AggressiveCaching);
+        painter->setPen(penText);
+        painter->drawStaticText(coordTxt, name);
+    }
+}
+
+/* calculate abscissa on the screen for a given time (in ms) if it's displayable
+ return -1 if timestampMs is outside time displayable because of scale*/
+qreal GanttWidget::coordxForTime(qlonglong timestampMs)
+{
+    qreal startx = (qreal) WIDTH_PROGRAM + MARGIN + WIDTH_GLOBAL_PU + MARGIN
+                   + WIDTH_PU + MARGIN;
+    qreal widthAllowed = (qreal) size().width() - startx;
+    qreal scale = (qreal) widthAllowed / _timeTotal;
+    qreal coordx = -1;
+
+    if (timestampMs >= 0)
+    {
+        if ((timestampMs <= _timePresent) && (timestampMs >= (_timePresent
+                                                              - _timeBefore)))
+        {
+            coordx = (qreal) startx + (qreal)(
+                    (_timeBefore - (_timePresent - timestampMs)) * scale);
+        }
+        else if ((timestampMs > _timePresent) && timestampMs <= (_timeAfter
+                                                                 + _timePresent))
+        {
+            coordx = (qreal) _coordxPresentLine + (qreal)(
+                    (timestampMs - _timePresent) * scale);
+        }
+    }
+
+    return coordx;
+}
+
+void GanttWidget::drawTime(QPainter *painter)
+{
+    QFont f;
+    QPen penRect;
+    QPen penText;
+    penRect.setColor(GANTT_TIMELINE_COLOR);
+    penText.setColor(GANTT_TEXT_COLOR);
+    painter->setPen(penRect);
+    f.setFamily("utf8");
+    f.setWeight(QFont::DemiBold);
+    f.setPixelSize(10);
+    painter->setFont(f);
+
+    _rectTime = QRectF(0, 0, size().width(), 20);
+    painter->drawRect(_rectTime);
+    painter->fillRect(_rectTime, Qt::blue);
+    QString titre = QString("Time (ms)");
+    QStaticText titreTxt = QStaticText(titre);
+    titreTxt.setPerformanceHint(QStaticText::AggressiveCaching);
+    QPointF coordRect = QPointF(_rectTime.left() + SHIFT_LEFT_TIME_AXIS,
+                                _rectTime.center().ry() - f.pixelSize() + SHIFT_TOP_TIME_AXIS);
+    painter->setPen(penText);
+    painter->drawStaticText(coordRect, titreTxt);
+    f.setWeight(QFont::Light);
+    f.setPixelSize(10);
+    painter->setFont(f);
+
+    qreal ourStartx = WIDTH_PROGRAM + MARGIN + WIDTH_GLOBAL_PU + MARGIN
+                      + WIDTH_PU + MARGIN;
+    qreal widthAvailable = ((qreal)(size().width() - ourStartx));
+    qreal scale = ((qreal)(_timeBefore + _timeAfter) / widthAvailable);
+    qreal scale_time_px = (qreal) widthAvailable / (_timeBefore + _timeAfter);
+    int timeInterval = computeTimeInterval(_timeTotal);
+    qreal sizeInterval = ((qreal)(timeInterval * scale_time_px));
+    qreal step_x = (qreal)(sizeInterval / GRAD_NUM);
+
+    //we calculate the location of the next gradation in the future part
+    qlonglong first = _timePresent - _timePresent % ((qlonglong) timeInterval);
+    qlonglong cur_t = first;
+
+    //gradations in the past
+    while (cur_t > _timePresent - _timeBefore)
+    {
+        if (cur_t >= (qlonglong) 0)
+        {
+            qreal cur_x =
+                    ((qreal)((_timeBefore - (_timePresent - cur_t)) / scale)
+                     + ourStartx);
+            QString buffer;
+            buffer.append(QString("%1").arg(cur_t));
+            QStaticText gradTxt = QStaticText(buffer);
+            gradTxt.setPerformanceHint(QStaticText::AggressiveCaching);
+            //calculate the fading
+            int fading = 3 * (cur_x - ourStartx);
+            if (fading < 0)
+            {
+                fading = 0;
+            }
+            if (fading > 255)
+            {
+                fading = 255;
+            }
+            _textPen.setColor(QColor(255, 255, 255, fading));
+            painter->setPen(_textPen);
+            painter->drawLine(
+                    QLineF(cur_x, 0, cur_x, HEIGHT_TIME_AXIS - MARGIN));
+            if (widthAvailable > 500)
+            {
+                painter->drawStaticText(
+                        QPointF(cur_x,
+                                HEIGHT_TIME_AXIS - MARGIN - f.pixelSize()),
+                        gradTxt);
+            }
+            for (int k = 1; k < GRAD_NUM; k++)
+            { // k=1 ,because of spans
+                painter->drawLine(
+                        QLineF(cur_x + step_x * k, 0, cur_x + step_x * k,
+                               HEIGHT_TIME_AXIS - MARGIN * 3));
+            }
+        }
+        cur_t -= timeInterval;
+    }
+
+    //in the future
+    cur_t = first + timeInterval;
+    while (cur_t < _timePresent + _timeAfter)
+    {
+        qreal cur_x = ((qreal)((_timeBefore - (_timePresent - cur_t)) / scale)
+                       + ourStartx);
+        QString buffer;
+        buffer.append(QString("%1").arg(cur_t));
+        QStaticText gradTxt = QStaticText(buffer);
+        gradTxt.setPerformanceHint(QStaticText::AggressiveCaching);
+        //calculate the fading
+        int fading = 3 * (size().width() - cur_x);
+        if (fading > 255)
+        {
+            fading = 255;
+        }
+        _textPen.setColor(QColor(255, 255, 255, fading));
+        painter->setPen(_textPen);
+        painter->drawLine(QLineF(cur_x, 0, cur_x, HEIGHT_TIME_AXIS - MARGIN));
+        if (widthAvailable > 500)
+        {
+            painter->drawStaticText(
+                    QPointF(cur_x, HEIGHT_TIME_AXIS - MARGIN - f.pixelSize()),
+                    gradTxt);
+        }
+        for (int k = 1; k < GRAD_NUM; k++)
+        {
+            painter->drawLine(
+                    QLineF(cur_x + step_x * k, 0, cur_x + step_x * k,
+                           HEIGHT_TIME_AXIS - MARGIN * 3));
+        }
+        cur_t += timeInterval;
+    }
+    _textPen.setColor(QColor(255, 255, 255));
+    painter->setPen(_textPen);
+}
+
+//calculate un lapse of time to get at least 20 gradations if 1000 <= timeTotal
+//and <=24 * 10^X
+int GanttWidget::computeTimeInterval(int timeTotal)
+{
+    int coef = 1;
+    while (timeTotal >= SIGNIF_NUM)
+    {
+        timeTotal = timeTotal / 10;
+        coef *= 10;
+    }
+    //we have a number between 1 and 99
+    if (timeTotal < FIRST_THRESHOLD)
+    {
+        return coef;
+    }
+    else if (timeTotal < SECOND_THRESHOLD)
+    {
+        return coef * 5;
+    }
+    else
+    {
+        return coef * 10;
+    }
+}
+
+void GanttWidget::drawProgram(QPainter *painter)
+{
+    QFont f;
+    QPen penRect;
+    QPen penText;
+    penRect.setColor(GANTT_PU_COLOR);
+    penText.setColor(GANTT_TEXT_COLOR);
+    f.setFamily("utf8");
+    f.setWeight(QFont::Black);
+    f.setPixelSize(10);
+    painter->setFont(f);
+    painter->setPen(penRect);
+
+    _rectProg = QRectF(0, HEIGHT_TIME_AXIS + MARGIN, WIDTH_PROGRAM,
+                       size().height() - HEIGHT_TIME_AXIS - MARGIN * 2);
+    painter->drawRect(_rectProg);
+    painter->fillRect(_rectProg, Qt::blue);
+    QPointF coordTxt = QPointF(
+            _rectProg.center().rx() - (WIDTH_PROGRAM / 2) + 3,
+            _rectProg.center().ry() - f.pixelSize());
+    QString txt = QString("Program");
+    QStaticText name = QStaticText(txt);
+    name.setPerformanceHint(QStaticText::AggressiveCaching);
+    painter->setPen(penText);
+    painter->drawStaticText(coordTxt, name);
+}
+
+void GanttWidget::drawPresentLine(QPainter *painter)
+{
+    QPen pen;
+    pen.setColor(GANTT_PRESENTLINE_COLOR);
+    painter->setPen(pen);
+    qreal widthAllowed = (qreal)(
+            size().width() - WIDTH_PROGRAM - MARGIN - WIDTH_GLOBAL_PU - MARGIN
+            - WIDTH_PU - MARGIN);
+    int timeTotal = _timeBefore + _timeAfter;
+    int x, y, w, h;
+    x = WIDTH_PROGRAM + MARGIN + WIDTH_GLOBAL_PU + MARGIN + WIDTH_PU + MARGIN;
+    y = (HEIGHT_TIME_AXIS + MARGIN);
+    w = WIDTH_PRESENT_LINE;
+    h = size().height() - (HEIGHT_TIME_AXIS + MARGIN);
+    qreal scale = (qreal)(widthAllowed / timeTotal);
+    qreal gap_x = (qreal)(scale * _timeBefore);
+
+    _linePresent = QRectF(x + gap_x, y, w, h);
+    _coordxPresentLine = (qreal)(x + gap_x);
+    painter->drawRect(_linePresent);
+    painter->fillRect(_linePresent, Qt::black);
+}
+
+/* Draw whole gantt diagram depending on time showing line present location.
+ Useful to draw the diagram after the complete execution. */
+void GanttWidget::drawFromTime(QPainter *painter, qlonglong timestamp)
+{
+    Q_ASSERT_X(timestamp >= 0, "GanttWidget::drawFromTime",
+               "Negative timestamp !");
+
+    /* program rect */
+    drawProgram(painter);
+
+    _timePresent = timestamp;
+
+    /* time line */
+    drawTime(painter);
+
+    drawPUs(painter);
+
+    /* Tasks */
+    drawIdlePU(painter);
+
+    qlonglong borneBefore = _timePresent - _timeBefore;
+    if (borneBefore < 0)
+    {
+        borneBefore = 0;
+    }
+    _tasks = _taskManager->tasks(borneBefore, _timePresent);
+    foreach(StarputopTask t, _tasks)
+    {
+	drawWorkPU(painter,t);
+    }
+}
+
+/* draw idle time for each processor */
+void GanttWidget::drawIdlePU(QPainter *painter)
+{
+    int starty = HEIGHT_TIME_AXIS + MARGIN;
+    int widthAllowed = size().width() - WIDTH_PROGRAM - MARGIN
+                       - WIDTH_GLOBAL_PU - MARGIN - WIDTH_PU - MARGIN;
+    int timeTotal = _timeBefore + _timeAfter;
+    qreal posBlockx = 0;
+    qreal placeTime = 0;
+    bool isStartx = false;
+    qreal scale = (qreal) widthAllowed / timeTotal;
+
+    QRectF rectIdle;
+
+    qlonglong timestampS = 0;
+    if (_timePresent >= _timeBefore)
+    {
+        timestampS = _timePresent - _timeBefore;
+    }
+
+    /* drawIdlePu */
+    for (qlonglong j = timestampS; j < _timePresent; j++)
+    {
+        if (!isStartx)
+        {
+            isStartx = true;
+            posBlockx = coordxForTime(j);
+        }
+        placeTime++;
+    }
+
+    QFont f;
+    QPen pen;
+
+    f.setFamily("utf8");
+    f.setWeight(QFont::DemiBold);
+    f.setPixelSize(10);
+    painter->setFont(f);
+    pen.setColor(GANTT_IDLE_COLOR.lighter(110));
+    painter->setPen(pen);
+
+    for (int i = 0; i < _numPUs; i++)
+    {
+        rectIdle = QRectF(posBlockx, starty + (_heightPU) * i,
+                          placeTime * scale, (_heightPU - MARGIN));
+        painter->drawRect(rectIdle);
+        painter->fillRect(rectIdle, GANTT_IDLE_COLOR);
+    }
+}
+
+/* draw forecasted working time for each processor */
+void GanttWidget::drawPrevWorkPU(QPainter *painter, StarputopTask t)
+{
+    int starty = HEIGHT_TIME_AXIS + MARGIN;
+    int widthAllowed = size().width() - WIDTH_PROGRAM - MARGIN
+                       - WIDTH_GLOBAL_PU - MARGIN - WIDTH_PU - MARGIN;
+    qreal posBlockx = 0;
+    qreal placeTime = 0;
+    bool isStartx = false;
+    qreal scale = (qreal) widthAllowed / _timeTotal;
+    QRectF rectForecast;
+
+    //either the beginning is in the Future Part
+    //( timeAfter ) or either in the Past Part (timeBefore)
+    qlonglong timestampS = (t.timestampStart - _timePresent);
+    if (timestampS > 0)
+    {
+        // the beginning is in the Future part (displayable here)
+        timestampS = t.timestampStart;
+    }
+    else
+    {
+        // the beginning is in the Past part (not displayable here)
+        timestampS = _timePresent;
+        // +1 just to be sure we don't draw over the line of Present
+        posBlockx = _coordxPresentLine + WIDTH_PRESENT_LINE + 1;
+        isStartx = true;
+        placeTime -= WIDTH_PRESENT_LINE + 1;
+    }
+
+    qlonglong timestampE = (t.timestampEnd - _timePresent);
+    if (timestampE > 0)
+    {
+        if (timestampE <= _timeAfter)
+        {
+            timestampE = t.timestampEnd; // the end is displayable
+        }
+        else
+        {
+            // the end is not displayable because it's in the future
+            // more than timePresent + timeAfter
+            timestampE = _timePresent + _timeAfter;
+        }
+    }
+    else
+    {
+        // the end is not displayable because it's in the past
+        timestampE = _timePresent;
+        posBlockx = _coordxPresentLine + WIDTH_PRESENT_LINE + 1;
+        isStartx = true;
+        placeTime -= WIDTH_PRESENT_LINE + 1;
+    }
+
+    /* Future */
+    for (qlonglong i = timestampS; i <= timestampE; i++)
+    {
+        if (!isStartx)
+        {
+            isStartx = true;
+            posBlockx = coordxForTime(i);
+        }
+        placeTime++;
+    }
+
+    int pos = _PUsByDevice[t.deviceId].id;
+    QFont f;
+    QPen pen;
+    pen.setColor(GANTT_TEXT_COLOR);
+    painter->setPen(pen);
+    f.setFamily("utf8");
+    f.setWeight(QFont::DemiBold);
+    f.setPixelSize(10);
+    painter->setFont(f);
+
+    QLinearGradient gradient(posBlockx,
+                             starty + (_heightPU) * pos + (_heightPU - MARGIN) / 2,
+                             posBlockx + placeTime * scale,
+                             starty + (_heightPU) * pos + (_heightPU - MARGIN) / 2);
+    QColor prevColor = GANTT_PREV_COLOR;
+    gradient.setColorAt(0.2, prevColor.lighter(110));
+    gradient.setColorAt(0.3, Qt::yellow);
+    gradient.setColorAt(0.80, prevColor.darker(270));
+
+    QBrush brush(gradient);
+    pen.setBrush(brush);
+    painter->setPen(pen);
+    rectForecast = QRectF(posBlockx, starty + (_heightPU) * pos,
+                          placeTime * scale, (_heightPU - MARGIN));
+    painter->drawRect(rectForecast);
+    painter->fillRect(rectForecast, brush);
+}
+
+/* Draw working time for each processor. Working PUs.
+ We don't mind about task values because the taskmanager gives us only the tasks
+ between timeBefore and timePresent so
+ we haven't to test if they are displayable or not. We just have to calculate
+ which part of time is displayable.
+ The task t has its begin or its end between time Before and timePresent */
+void GanttWidget::drawWorkPU(QPainter *painter, StarputopTask t)
+{
+    int starty = HEIGHT_TIME_AXIS + MARGIN;
+    int widthAllowed = size().width() - WIDTH_PROGRAM - MARGIN
+                       - WIDTH_GLOBAL_PU - MARGIN - WIDTH_PU - MARGIN;
+    qreal posBlockx = 0;
+    qreal placeTime = 0;
+    bool isStartx = false;
+    qreal scale = (qreal) widthAllowed / _timeTotal;
+    QRectF rectWorking;
+
+    qlonglong timestampS = (_timePresent - t.timestampStart);
+    qlonglong timestampE = -1;
+    if (timestampS > _timeBefore)
+    {
+        // Begin time of task t is not displayable
+        timestampS = _timePresent - _timeBefore;
+    }
+    else
+    {
+        timestampS = t.timestampStart; // Begin time of task t is displayable
+    }
+    if (t.timestampEnd == -1)
+    {
+        for (qlonglong i = timestampS; i <= _timePresent; i++)
+        {
+            if (!isStartx)
+            {
+                isStartx = true;
+                posBlockx = coordxForTime(i);
+            }
+            placeTime++;
+        }
+    }
+    else
+    {
+        timestampE = t.timestampEnd;
+        if (timestampE > _timePresent)
+        {
+            timestampE = _timePresent;
+        }
+        for (qlonglong i = timestampS; i <= timestampE; i++)
+        {
+            if (!isStartx)
+            {
+                isStartx = true;
+                posBlockx = coordxForTime(i);
+            }
+            placeTime++;
+        }
+    }
+
+    int pos = _PUsByDevice[t.deviceId].id;
+
+    QFont f;
+    QPen pen;
+
+    f.setFamily("utf8");
+    f.setWeight(QFont::DemiBold);
+    f.setPixelSize(10);
+    painter->setFont(f);
+
+    rectWorking = QRectF(posBlockx, starty + (_heightPU) * pos,
+                         placeTime * scale, (_heightPU - MARGIN));
+    painter->drawRect(rectWorking);
+
+    QLinearGradient gradient(posBlockx,
+                             starty + (_heightPU) * pos + (_heightPU - MARGIN) / 2,
+                             posBlockx + placeTime * scale,
+                             starty + (_heightPU) * pos + (_heightPU - MARGIN) / 2);
+    QColor workingColor = GANTT_WORKING_COLOR;
+    gradient.setColorAt(0.2, workingColor.lighter(110));
+    gradient.setColorAt(0.3, Qt::green);
+    gradient.setColorAt(0.8, workingColor.darker(270));
+    gradient.setSpread(QGradient::PadSpread);
+
+    QBrush brush(gradient);
+    pen.setBrush(brush);
+    painter->setPen(pen);
+    painter->fillRect(rectWorking, brush);
+}
+
+void GanttWidget::updateZoom(double value)
+{
+    qDebug() << "VALEUR === " << value;
+    //   if(!(value == 0.0))
+    // {
+    _timeTotal = value;
+    updatePrevLine( _lastValPrevLine);
+    //}
+}
+
+void GanttWidget::updatePrevLine(double value)
+{
+    _timeBefore = _timeTotal * (value / 100);
+    _timeAfter = _timeTotal * ((100 - value) / 100);
+    _lastValPrevLine = value;
+    if (!(_timer->isActive()))
+    {
+        update();
+    }
+}
+
+void GanttWidget::updateTimeView(int time)
+{
+    qlonglong newTimeToShow = time;
+    if (!(_timer->isActive()))
+    {
+        _timeToShow = newTimeToShow;
+        update();
+    }
+}
+
+void GanttWidget::connected()
+{
+    _wasRunning = false;
+    _initCompleted = false;
+    _timePresent = 0;
+    if (!(_timer->isActive()))
+    {
+        _timer->start(35);
+    }
+}
+
+void GanttWidget::disconnected()
+{
+    _wasRunning = true;
+    if (_timer->isActive())
+    {
+        _timer->stop();
+    }
+}
+
+void GanttWidget::ganttLocked()
+{
+    update(); // a last drawing update before to freeze the drawing
+    if (_timer->isActive())
+    {
+        _timer->stop(); // freeze the drawing
+    }
+}
+
+void GanttWidget::ganttUnlocked()
+{
+    if (!(_timer->isActive()))
+    {
+        _timer->start(35); // start the timer again
+    }
+}
+
+void GanttWidget::countPUs()
+{
+    int length;
+    _numCPUs = 0;
+    _numGPUs = 0;
+
+    length = _mainWindow->serverDevices()->length();
+    _numPUs = length;
+    delete _PUsByDevice;
+    delete _PUsByPos;
+    _PUsByDevice = new StarputopDevice[length];
+    _PUsByPos = new StarputopDevice[length];
+    int pos = 0;
+
+    /* CPUs */
+    foreach(StarputopDevice sD,*_mainWindow->serverDevices())
+    {
+	if(sD.type == 0)
+	{
+            _PUsByDevice[sD.id].name = sD.name;
+            _PUsByDevice[sD.id].type = sD.type;
+            _PUsByDevice[sD.id].id = pos; // actual location
+
+            _PUsByPos[pos].id = sD.id; // the reak id
+            _PUsByPos[pos].name = sD.name;
+            _PUsByPos[pos].type = sD.type;
+
+            _numCPUs++;
+            pos++;
+	}
+    }
+
+    /* GPUs */
+    foreach (StarputopDevice sD , *_mainWindow->serverDevices())
+    {
+	if(sD.type == 1 || sD.type == 2)
+	{
+            _PUsByDevice[sD.id].name = sD.name;
+            _PUsByDevice[sD.id].type = sD.type;
+            _PUsByDevice[sD.id].id = pos; // actually location
+
+            _PUsByPos[pos].id = sD.id; // the real id
+            _PUsByPos[pos].name = sD.name;
+            _PUsByPos[pos].type = sD.type;
+
+            pos++;
+            _numGPUs++;
+	}
+    }
+}
+
+void GanttWidget::paint(QPainter *painter, QPaintEvent *event)
+{
+    painter->fillRect(event->rect(), _background);
+    painter->setPen(_textPen);
+
+    if (_mainWindow->isReady())
+    {
+        if (!_initCompleted)
+        { // do not call countPUs more than once per execution
+            countPUs();
+            _initCompleted = true;
+        }
+        drawProgram(painter);
+        drawPUs(painter);
+
+        if (_mainWindow->isRunning())
+        {
+            _timePresent = _mainWindow->effectiveRunningTime();
+            _timeToShow = _timePresent; // saved the time of end
+            drawTime(painter);
+            drawPresentLine(painter);
+            drawIdlePU(painter);
+
+            /* Past part */
+            qlonglong borneBefore = _timePresent - _timeBefore;
+            if (borneBefore < 0)
+            {
+                borneBefore = 0;
+            }
+
+            _tasks = _taskManager->tasks(borneBefore, _timePresent);
+            foreach (StarputopTask t, _tasks)
+            {
+                drawWorkPU(painter,t);
+            }
+
+            /* Future past */
+            qlonglong borneAfter = _timePresent + _timeAfter;
+            _tasks = _taskManager->prevTasks(_timePresent, borneAfter);
+            foreach		(StarputopTask t, _tasks)
+            {
+                drawPrevWorkPU(painter,t);
+            }
+	}
+	else if (!_wasRunning)
+	{
+            defaultScreen(painter);
+	}
+    }
+    else
+    {
+	if (_wasRunning)
+	{
+            // display wanted part of execution (only if it's finished)
+            drawFromTime(painter,_timeToShow);
+	}
+    }
+}

+ 103 - 0
starpu-top/ganttwidget.h

@@ -0,0 +1,103 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef GANTTWIDGET_H
+#define GANTTWIDGET_H
+
+class MainWindow;
+class TaskManager;
+
+#include <QGLWidget>
+#include <QPainter>
+#include "starputoptypes.h"
+
+class GanttWidget : public QGLWidget
+{
+    Q_OBJECT
+public:
+    explicit GanttWidget(
+            MainWindow *mainWindow,
+            TaskManager *taskManager);
+    ~GanttWidget();
+
+public slots:
+    void updateZoom(double value);
+    void updatePrevLine(double value);
+    void updateTimeView(int time);
+    void connected();
+    void disconnected();
+    void ganttLocked();
+    void ganttUnlocked();
+
+protected:
+    void paintEvent(QPaintEvent *event);
+    void paint(QPainter *painter, QPaintEvent *event);
+    void drawPUs(QPainter *painter);
+    void drawTime(QPainter *painter);
+    void drawProgram(QPainter *painter);
+    void resizeGL (int width,int height);
+    void drawWorkPU(QPainter *painter, StarputopTask t);
+    void drawIdlePU(QPainter *painter);
+    void drawPrevWorkPU(QPainter *painter, StarputopTask t);
+    void defaultScreen(QPainter *painter);
+    void drawPresentLine(QPainter *painter);
+    int computeTimeInterval(int timeTotal);
+    qreal coordxForTime(qlonglong timestamp_ms);
+    void drawFromTime(QPainter *painter, qlonglong timestamp);
+    void countPUs();
+
+private:
+    MainWindow *_mainWindow;
+    TaskManager *_taskManager;
+
+    QBrush _background;
+    QFont _textFont;
+    QPen _textPen;
+    QRectF _rectTime;
+    QRectF _rectProg;
+    QRectF _rectCPUblock;
+    QRectF _rectGPUblock;
+    QRectF *_rectPUs;
+    QRectF _linePresent;
+    qreal _coordxPresentLine;
+    int _numPUs;
+    bool _wasRunning;
+    QList<StarputopTask> _tasks;
+    int _timeTotal;
+    int _timeAfter;
+    int _timeBefore;
+    double _lastValPrevLine;
+    QTimer *_timer;
+    qlonglong _timePresent;
+    qlonglong _timeToShow;
+    StarputopDevice *_PUsByDevice;
+    StarputopDevice *_PUsByPos;
+    int _numCPUs;
+    int _numGPUs;
+    bool _initCompleted;
+    int _heightPU; // Height of each CPU or GPU rectangles
+};
+
+#endif // GANTTWIDGET_H

BIN
starpu-top/images/about.png


BIN
starpu-top/images/add.png


BIN
starpu-top/images/connect.png


BIN
starpu-top/images/debugoff.png


BIN
starpu-top/images/debugon.png


BIN
starpu-top/images/help.png


BIN
starpu-top/images/inside.png


BIN
starpu-top/images/lock.png


BIN
starpu-top/images/outside.png


BIN
starpu-top/images/play.png


BIN
starpu-top/images/preferences.png


BIN
starpu-top/images/quit.png


BIN
starpu-top/images/remove.png


BIN
starpu-top/images/starputop.png


BIN
starpu-top/images/widget.png


BIN
starpu-top/images/windows.png


+ 625 - 0
starpu-top/interactivewidget.cpp

@@ -0,0 +1,625 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "interactivewidget.h"
+#include "mainwindow.h"
+#include <QCloseEvent>
+#include <QAction>
+#include <QCheckBox>
+#include <QSpinBox>
+#include <QDial>
+#include <qwt_knob.h>
+#include <qwt_wheel.h>
+#include <qwt_slider.h>
+
+InteractiveWidget::InteractiveWidget(ParamDescription *paramDescription,
+                                     MainWindow *mainWindow) :
+QWidget(mainWindow)
+{
+    _mainWindow = mainWindow;
+    _paramDescription = paramDescription;
+    _internalWidget = 0;
+
+    _interactiveWidgetNames = _mainWindow->interactiveWidgetNames();
+    _interactiveWidgetPossibilities
+            = _mainWindow->interactiveWidgetPossibilities() ->value(
+                    _paramDescription->type).values();
+
+    // Init context menu actions
+    QActionGroup *actionGroup = new QActionGroup(this);
+    for (int i = 0; i < _interactiveWidgetPossibilities.count(); i++)
+    {
+        QAction *action = new QAction(
+                _interactiveWidgetNames ->value(
+                        _interactiveWidgetPossibilities.at(i)), actionGroup);
+        action->setCheckable(true);
+        if (_interactiveWidgetPossibilities.at(i) == _paramDescription->widget)
+        {
+            action->setChecked(true);
+        }
+        QObject::connect(action, SIGNAL(triggered()), this,
+                         SLOT(widgetTypeChanged()));
+        actionGroup->addAction(action);
+    }
+    addActions(actionGroup->actions());
+
+    // Set attributes
+    setAttribute(Qt::WA_DeleteOnClose);
+    setContextMenuPolicy(Qt::ActionsContextMenu);
+
+    // Init GUI
+    QString labelText = _paramDescription->descriptionString;
+    if (_paramDescription->descriptionString.size() > 14)
+    {
+        labelText.truncate(12);
+        labelText.append("...");
+    }
+    _label = new QLabel(labelText);
+    _label->setToolTip(_paramDescription->descriptionString);
+    // Set layout
+    _layout = new QHBoxLayout(this);
+    setLayout( _layout);
+    _layout->addWidget(_label);
+
+    // Create internal widget
+    createInternalWidget();
+
+    // Bind notifications
+    QObject::connect(this, SIGNAL(paramValueChanged(int,bool)),
+                     _mainWindow, SLOT(interactiveWidgetUpdated(int,bool)));
+    QObject::connect(this, SIGNAL(paramValueChanged(int,int)),
+                     _mainWindow, SLOT(interactiveWidgetUpdated(int,int)));
+    QObject::connect(this, SIGNAL(paramValueChanged(int,double)),
+                     _mainWindow, SLOT(interactiveWidgetUpdated(int,double)));
+    // Setup automatic cleanup
+    QObject::connect(this, SIGNAL(destroyed()), _mainWindow,
+                     SLOT(removeDestroyedInteractiveWidgets()));
+
+    qDebug() << "InteractiveWidget : initializing [desc"
+            << _paramDescription->descriptionString << "; id"
+            << _paramDescription->id << "; type" << _paramDescription->type
+            << "; min" << _paramDescription->valMin << "; max"
+            << _paramDescription->valMax << "; init bool"
+            << _paramDescription->valInitBool << "; init double"
+            << _paramDescription->valInitDouble << "; init enum"
+            << _paramDescription->valInitEnum << "; init int"
+            << _paramDescription->valInitInt << "; widget"
+            << _paramDescription->widget << "]";
+}
+
+InteractiveWidget::~InteractiveWidget()
+{
+    qDebug() << "InteractiveWidget" << _paramDescription->id << ": terminating";
+}
+
+void InteractiveWidget::closeEvent(QCloseEvent *ce)
+{
+    ce->accept();
+}
+
+void InteractiveWidget::recreateInternalWidget()
+{
+    if (_internalWidget != 0)
+    {
+        _internalWidget->close();
+        _internalWidget = 0;
+    }
+
+    createInternalWidget();
+    adjustSize();
+    updateAction(_paramDescription->widget);
+}
+
+void InteractiveWidget::updateAction(InteractiveWidgetType newWidget)
+{
+    for (int i = 0; i < actions().count(); i++)
+    {
+        if (actions().at(i)->text().compare(
+                _interactiveWidgetNames->value(newWidget)) == 0)
+        {
+            actions().at(i)->setChecked(true);
+            return;
+        }
+    }
+}
+
+void InteractiveWidget::createInternalWidget()
+{
+    qDebug() << "Creating the interactive widget for param id"
+            << _paramDescription->id;
+
+    switch (_paramDescription->widget)
+    {
+    case INTERACTIVE_WIDGET_SLIDER:
+	{
+            _internalWidget = new QwtSlider(this);
+            _internalWidget->setMinimumWidth(100);
+
+            QwtSlider *widget = (QwtSlider*) _internalWidget;
+            widget->setRange(_paramDescription->valMin, _paramDescription->valMax);
+            widget->setScalePosition(QwtSlider::BottomScale);
+            widget->setValue(_paramDescription->valInitInt);
+            QObject::connect(widget, SIGNAL(sliderReleased()), this,
+                             SLOT(sliderValueChanged()));
+            break;
+	}
+
+    case INTERACTIVE_WIDGET_KNOB:
+	{
+            _internalWidget = new QwtKnob(this);
+            _internalWidget->setMinimumSize(50, 50);
+
+            QwtKnob *widget = (QwtKnob*) _internalWidget;
+            widget->setRange(_paramDescription->valMin, _paramDescription->valMax);
+            widget->setValue(_paramDescription->valInitDouble);
+            QObject::connect(widget, SIGNAL(sliderReleased()), this,
+                             SLOT(knobValueChanged()));
+            break;
+	}
+
+    case INTERACTIVE_WIDGET_WHEEL:
+	{
+            _internalWidget = new QwtWheel(this);
+            _internalWidget->setMinimumSize(50, 30);
+
+            QwtWheel *widget = (QwtWheel*) _internalWidget;
+            widget->setRange(_paramDescription->valMin, _paramDescription->valMax);
+            widget->setValue(_paramDescription->valInitDouble);
+            QObject::connect(widget, SIGNAL(sliderReleased()), this,
+                             SLOT(wheelValueChanged()));
+            break;
+	}
+
+    case INTERACTIVE_WIDGET_CHECKBOX:
+	{
+            _internalWidget = new QCheckBox(this);
+            _internalWidget->setMinimumSize(25, 25);
+
+            QCheckBox *widget = (QCheckBox*) _internalWidget;
+            widget->setChecked(_paramDescription->valInitBool);
+            QObject::connect(widget, SIGNAL(clicked(bool)),
+                             this, SLOT(notifyValueChanged(bool)));
+            break;
+	}
+
+    case INTERACTIVE_WIDGET_SPINBOX:
+	{
+            _internalWidget = new QSpinBox(this);
+            _internalWidget->setMinimumSize(75, 30);
+
+            QSpinBox *widget = (QSpinBox*) _internalWidget;
+            widget->setRange(_paramDescription->valMin, _paramDescription->valMax);
+            widget->setValue(_paramDescription->valInitInt);
+            QObject::connect(widget, SIGNAL(valueChanged(int)),
+                             this, SLOT(notifyValueChanged(int)));
+            break;
+	}
+
+    case INTERACTIVE_WIDGET_DOUBLESPINBOX:
+	{
+            _internalWidget = new QDoubleSpinBox(this);
+            _internalWidget->setMinimumSize(75, 30);
+
+            QDoubleSpinBox *widget = (QDoubleSpinBox*) _internalWidget;
+            widget->setRange(_paramDescription->valMin, _paramDescription->valMax);
+            widget->setValue(_paramDescription->valInitDouble);
+            QObject::connect(widget, SIGNAL(valueChanged(double)),
+                             this, SLOT(notifyValueChanged(double)));
+            break;
+	}
+
+    case INTERACTIVE_WIDGET_DIAL:
+	{
+            _internalWidget = new QDial(this);
+            _internalWidget->setMinimumSize(80, 40);
+
+            QDial *widget = (QDial*) _internalWidget;
+            widget->setRange(_paramDescription->valMin, _paramDescription->valMax);
+            widget->setValue(_paramDescription->valInitInt);
+            QObject::connect(widget, SIGNAL(sliderReleased()), this,
+                             SLOT(dialValueChanged()));
+            break;
+	}
+
+    case INTERACTIVE_WIDGET_COMBOBOX:
+	{
+            _internalWidget = new QComboBox(this);
+            _internalWidget->setMinimumSize(75, 25);
+
+            QComboBox *widget = (QComboBox*) _internalWidget;
+            widget->addItems(_paramDescription->enumValues);
+            widget->setCurrentIndex(_paramDescription->valInitEnum);
+            QObject::connect(widget, SIGNAL(currentIndexChanged(int)),
+                             this, SLOT(notifyValueChanged(int)));
+            break;
+	}
+
+    default:
+        ;
+    }
+
+    _internalWidget->setAttribute(Qt::WA_DeleteOnClose);
+    layout()->addWidget(_internalWidget);
+}
+
+/* -------------------------------------------------------------------------- */
+/* Getters                                                                    */
+/* -------------------------------------------------------------------------- */
+
+ParamDescription *InteractiveWidget::description() const
+{
+    return _paramDescription;
+}
+
+QSize InteractiveWidget::minimumInternalWidgetSize() const
+{
+    return _internalWidget->minimumSize();
+}
+
+/* -------------------------------------------------------------------------- */
+/* Setters                                                                    */
+/* -------------------------------------------------------------------------- */
+
+void InteractiveWidget::setValue(bool value)
+{
+    switch (_paramDescription->widget)
+    {
+    case INTERACTIVE_WIDGET_CHECKBOX:
+	{
+            QCheckBox *widget = qobject_cast<QCheckBox*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->setChecked(value);
+            }
+            else
+            {
+                qDebug()
+                        << "Bad interactive widget cast "
+                        "(InteractiveWidget::setValue()) !";
+            }
+            break;
+	}
+
+    default:
+        ;
+    }
+}
+
+void InteractiveWidget::setValue(int value)
+{
+    switch (_paramDescription->widget)
+    {
+    case INTERACTIVE_WIDGET_SLIDER:
+	{
+            QwtSlider *widget = qobject_cast<QwtSlider*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->setValue(value);
+            }
+            else
+            {
+                qDebug()
+                        << "Bad interactive widget cast "
+                        "(InteractiveWidget::setValue()) !";
+            }
+            break;
+	}
+
+    case INTERACTIVE_WIDGET_KNOB:
+	{
+            QwtKnob *widget = qobject_cast<QwtKnob*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->setValue(value);
+            }
+            else
+            {
+                qDebug()
+                        << "Bad interactive widget cast "
+                        "(InteractiveWidget::setValue()) !";
+            }
+            break;
+	}
+
+    case INTERACTIVE_WIDGET_WHEEL:
+	{
+            QwtWheel *widget = qobject_cast<QwtWheel*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->setValue(value);
+            }
+            else
+            {
+                qDebug()
+                        << "Bad interactive widget cast "
+                        "(InteractiveWidget::setValue()) !";
+            }
+            break;
+	}
+
+    case INTERACTIVE_WIDGET_SPINBOX:
+	{
+            QSpinBox *widget = qobject_cast<QSpinBox*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->setValue(value);
+            }
+            else
+            {
+                qDebug()
+                        << "Bad interactive widget cast "
+                        "(InteractiveWidget::setValue()) !";
+            }
+            break;
+	}
+
+    case INTERACTIVE_WIDGET_DOUBLESPINBOX:
+	{
+            QDoubleSpinBox *widget =
+                    qobject_cast<QDoubleSpinBox*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->setValue(value);
+            }
+            else
+            {
+                qDebug()
+                        << "Bad interactive widget cast "
+                        "(InteractiveWidget::setValue()) !";
+            }
+            break;
+	}
+
+    case INTERACTIVE_WIDGET_DIAL:
+	{
+            QDial *widget = qobject_cast<QDial*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->setValue(value);
+            }
+            else
+            {
+                qDebug()
+                        << "Bad interactive widget cast "
+                        "(InteractiveWidget::setValue()) !";
+            }
+            break;
+	}
+
+    case INTERACTIVE_WIDGET_COMBOBOX:
+	{
+            QComboBox *widget = qobject_cast<QComboBox*> (_internalWidget);
+            if (widget != 0)
+            {
+                if (value >= _paramDescription->valMin && value
+                    <= _paramDescription->valMax)
+                {
+                    widget->setCurrentIndex(value);
+                }
+                else
+                {
+                    qDebug()
+                            << "Trying to set out of range enum value for enum widget "
+                            << _paramDescription->id << "value" << value;
+                }
+            }
+            else
+            {
+                qDebug()
+                        << "Bad interactive widget cast "
+                        "(InteractiveWidget::setValue()) !";
+            }
+            break;
+	}
+
+    default:
+        ;
+    }
+}
+
+void InteractiveWidget::setValue(double value)
+{
+    switch (_paramDescription->widget)
+    {
+    case INTERACTIVE_WIDGET_SLIDER:
+	{
+            QwtSlider *widget = qobject_cast<QwtSlider*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->setValue(value);
+            }
+            else
+            {
+                qDebug()
+                        << "Bad interactive widget cast "
+                        "(InteractiveWidget::setValue()) !";
+            }
+            break;
+	}
+
+    case INTERACTIVE_WIDGET_KNOB:
+	{
+            QwtKnob *widget = qobject_cast<QwtKnob*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->setValue(value);
+            }
+            else
+            {
+                qDebug()
+                        << "Bad interactive widget cast "
+                        "(InteractiveWidget::setValue()) !";
+            }
+            break;
+	}
+
+    case INTERACTIVE_WIDGET_WHEEL:
+	{
+            QwtWheel *widget = qobject_cast<QwtWheel*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->setValue(value);
+            }
+            else
+            {
+                qDebug()
+                        << "Bad interactive widget cast "
+                        "(InteractiveWidget::setValue()) !";
+            }
+            break;
+	}
+
+    case INTERACTIVE_WIDGET_DOUBLESPINBOX:
+	{
+            QDoubleSpinBox *widget =
+                    qobject_cast<QDoubleSpinBox*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->setValue(value);
+            }
+            else
+            {
+                qDebug()
+                        << "Bad interactive widget cast "
+                        "(InteractiveWidget::setValue()) !";
+            }
+            break;
+	}
+
+    case INTERACTIVE_WIDGET_DIAL:
+	{
+            QDial *widget = qobject_cast<QDial*> (_internalWidget);
+            if (widget != 0)
+            {
+                widget->setValue(value);
+            }
+            else
+            {
+                qDebug()
+                        << "Bad interactive widget cast "
+                        "(InteractiveWidget::setValue()) !";
+            }
+            break;
+	}
+
+    default:
+        ;
+    }
+}
+
+/* -------------------------------------------------------------------------- */
+/* Other methods                                                              */
+/* -------------------------------------------------------------------------- */
+
+void InteractiveWidget::sliderValueChanged()
+{
+    QwtSlider *widget = (QwtSlider*) QObject::sender();
+
+    if (_paramDescription->type == PARAM_TYPE_INT)
+    {
+        int valueInt = (int) widget->value();
+        notifyValueChanged(valueInt);
+    }
+    else
+    { // Param type is double
+        double valueDouble = (double) widget->value();
+        notifyValueChanged(valueDouble);
+    }
+}
+
+void InteractiveWidget::wheelValueChanged()
+{
+    QwtWheel *widget = (QwtWheel*) QObject::sender();
+
+    if (_paramDescription->type == PARAM_TYPE_INT)
+    {
+        int valueInt = (int) widget->value();
+        notifyValueChanged(valueInt);
+    }
+    else
+    { // Param type is double
+        double valueDouble = (double) widget->value();
+        notifyValueChanged(valueDouble);
+    }
+}
+
+void InteractiveWidget::knobValueChanged()
+{
+    QwtKnob *widget = (QwtKnob*) QObject::sender();
+
+    if (_paramDescription->type == PARAM_TYPE_INT)
+    {
+        int valueInt = (int) widget->value();
+        notifyValueChanged(valueInt);
+    }
+    else
+    { // Param type is double
+        double valueDouble = (double) widget->value();
+        notifyValueChanged(valueDouble);
+    }
+}
+
+void InteractiveWidget::dialValueChanged()
+{
+    QDial *widget = (QDial*) QObject::sender();
+
+    if (_paramDescription->type == PARAM_TYPE_INT)
+    {
+        int valueInt = (int) widget->value();
+        notifyValueChanged(valueInt);
+    }
+    else
+    { // Param type is double
+        double valueDouble = (double) widget->value();
+        notifyValueChanged(valueDouble);
+    }
+}
+
+void InteractiveWidget::notifyValueChanged(bool value)
+{
+    emit paramValueChanged(_paramDescription->id, value);
+}
+
+void InteractiveWidget::notifyValueChanged(int value)
+{
+    emit paramValueChanged(_paramDescription->id, value);
+}
+
+void InteractiveWidget::notifyValueChanged(double value)
+{
+    emit paramValueChanged(_paramDescription->id, value);
+}
+
+void InteractiveWidget::widgetTypeChanged()
+{
+    QAction *action = (QAction*) QObject::sender();
+
+    if(_paramDescription->widget != _interactiveWidgetNames->key(action->text()))
+    {
+        _mainWindow->updateInteractiveWidgetType
+                (_paramDescription->id,
+                 _interactiveWidgetNames->key(action->text()));
+    }
+}

+ 97 - 0
starpu-top/interactivewidget.h

@@ -0,0 +1,97 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef INTERACTIVEWIDGET_H
+#define INTERACTIVEWIDGET_H
+
+#include <QWidget>
+#include <QCloseEvent>
+#include <QLabel>
+#include <QHBoxLayout>
+#include "starputoptypes.h"
+
+class MainWindow;
+
+class InteractiveWidget: public QWidget
+{ /* Widget which represents a single parameter on the server
+ and which takes place in the parameters dock of
+ the main window. Can display the parameter under
+ different forms defined in the interactive widget
+ specifications. The internal widget can be changed at any time. */
+    Q_OBJECT
+
+public:
+    explicit InteractiveWidget(ParamDescription *paramDescription,
+                               MainWindow *mainWindow);
+    ~InteractiveWidget();
+
+    // Getters
+    ParamDescription *description() const;
+    QSize minimumInternalWidgetSize() const;
+
+private:
+    // Events
+    void closeEvent(QCloseEvent *ce);
+    // UI components
+    MainWindow *_mainWindow;
+    QLabel *_label;
+    QWidget *_internalWidget;
+    QHBoxLayout *_layout;
+    // Data
+    ParamDescription *_paramDescription;
+    const QHash<InteractiveWidgetType, QString> *_interactiveWidgetNames;
+    QList<InteractiveWidgetType> _interactiveWidgetPossibilities;
+    // Create the internal widget
+    void createInternalWidget();
+
+    /** SLOTS **/
+
+public slots:
+    // Setters
+    void setValue(bool value);
+    void setValue(int value);
+    void setValue(double value);
+    // Other methods
+    void recreateInternalWidget();
+
+private slots:
+    // Other methods
+    void sliderValueChanged();
+    void wheelValueChanged();
+    void knobValueChanged();
+    void dialValueChanged();
+    void notifyValueChanged(bool value);
+    void notifyValueChanged(int value);
+    void notifyValueChanged(double value);
+    void widgetTypeChanged();
+    void updateAction(InteractiveWidgetType newWidget);
+
+signals:
+    void paramValueChanged(int id, bool value);
+    void paramValueChanged(int id, int value);
+    void paramValueChanged(int id, double value);
+};
+
+#endif // INTERACTIVEWIDGET_H

+ 43 - 0
starpu-top/main.cpp

@@ -0,0 +1,43 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include <QtGui/QApplication>
+#include "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+    QApplication a(argc, argv);
+
+    // Application description
+    QCoreApplication::setOrganizationName("INRIA-Bordeaux");
+    QCoreApplication::setOrganizationDomain("runtime.bordeaux.inria.fr");
+    QCoreApplication::setApplicationName("StarPU-Top");
+    QCoreApplication::setApplicationVersion("0.1");
+
+    MainWindow w;
+    w.show();
+
+    return a.exec();
+}

File diff suppressed because it is too large
+ 1527 - 0
starpu-top/mainwindow.cpp


+ 290 - 0
starpu-top/mainwindow.h

@@ -0,0 +1,290 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+class GanttWidget;
+class PreferencesDialog;
+class DebugConsole;
+class AbstractWidgetWindow;
+class DataWidget;
+class DataAggregatorWidget;
+class InteractiveWidget;
+class CommunicationThread;
+class ConfigurationManager;
+class WidgetWindowsManager;
+class SessionSetupManager;
+class TaskManager;
+
+#include <QMainWindow>
+#include <QMdiArea>
+#include <QSplitter>
+#include <QLabel>
+#include <QComboBox>
+#include <QPointer>
+#include <QScrollArea>
+#include <QAbstractSocket>
+#include <QTime>
+#include <QSpinBox>
+#include "starputoptypes.h"
+
+namespace Ui
+{
+    class MainWindow;
+}
+
+class MainWindow: public QMainWindow
+{
+    Q_OBJECT
+
+public:
+    explicit MainWindow(QWidget *parent = 0);
+    ~MainWindow();
+
+    // Getters
+    // Get GUI components
+    const QSplitter *splitter() const;
+    const QDockWidget *parametersDock() const;
+    // Get managers
+    const WidgetWindowsManager* widgetWindowsManager() const;
+    const ConfigurationManager* configurationManager() const;
+    const SessionSetupManager* sessionSetupManager() const;
+    const TaskManager* taskManager() const;
+    // Get different descriptions for the current session
+    QString serverID() const;
+    const QList<DataDescription*> *dataDescriptions() const;
+    const QList<ParamDescription*> *paramDescriptions() const;
+    DataDescription *dataDescriptionFromId(int dataId);
+    ParamDescription *paramDescriptionFromId(int interactiveId);
+    const QList<StarputopDevice> *serverDevices() const;
+    // Get different widgets metadata
+    const QHash<DataWidgetType, QString> *dataWidgetNames() const;
+    const QHash<DataType, QSet<DataWidgetType> >
+            *dataWidgetPossibilities() const;
+    const QHash<InteractiveWidgetType, QString> *interactiveWidgetNames() const;
+    const QHash<ParamType, QSet<InteractiveWidgetType> >
+            *interactiveWidgetPossibilities() const;
+    // Get the actual widgets
+    const QList<QPointer<DataWidget> > *dataWidgets() const;
+    const QList<QPointer<DataAggregatorWidget> > *dataAggregatorWidgets() const;
+    const QList<QPointer<InteractiveWidget> > *interactiveWidgets() const;
+    DataWidget *dataWidgetFromDataId(int id);
+    InteractiveWidget *interactiveWidgetFromParamId(int id);
+    // Get widgets counts
+    int nbDataWidgets() const;
+    int nbDataAggregatorWidgets() const;
+    int nbInteractiveWidgets() const;
+    // Get GUI states
+    bool isConnected() const;
+    bool isReady() const;
+    bool isRunning() const;
+    bool isDebugEnabled() const;
+    DisplayMode displayMode() const;
+    // Get effective session time
+    int effectiveRunningTime() const;
+    // Add new widgets to the session
+    DataWidget *addDataWidget(DataDescription *dataDescription);
+    DataAggregatorWidget *addDataAggregatorWidget(
+            QList<int> dataIds = QList<int> ());
+    InteractiveWidget *addInteractiveWidget(ParamDescription *paramDescription);
+
+protected:
+    // Events
+    void changeEvent(QEvent *e);
+    void closeEvent(QCloseEvent *e);
+
+private:
+    // GUI components
+    Ui::MainWindow *ui;
+    QComboBox *_widgetsDisplayModesList;
+    QSplitter *_splitter;
+    QMdiArea *_mdiArea;
+    GanttWidget *_ganttWidget;
+    QSpinBox *_ganttTimeView;
+    QScrollArea *_parametersDockScrollArea;
+    DebugConsole *_debugConsole;
+    QLabel *_statusBarIcon;
+    QLabel *_statusBarLabel;
+    PreferencesDialog *_preferencesDialog;
+    QList<QPointer<DataWidget> > *_dataWidgets;
+    QList<QPointer<DataAggregatorWidget> > *_dataAggregatorWidgets;
+    QList<QPointer<InteractiveWidget> > *_interactiveWidgets;
+    // Managers
+    ConfigurationManager *_configurationManager;
+    CommunicationThread *_communicationThread; // Will instantiate the communication manager
+    WidgetWindowsManager *_widgetWindowsManager;
+    SessionSetupManager *_sessionSetupManager;
+    TaskManager *_taskManager;
+    // GUI states
+    DisplayMode _displayMode;
+    bool _connected;
+    bool _ready;
+    bool _running;
+    bool _debug;
+    // GUI actions
+    QAction *_actionConnect;
+    QAction *_actionLaunch;
+    QAction *_actionDebug;
+    QAction *_actionSaveSessionSetup;
+    QAction *_actionAddDataWidget;
+    QAction *_actionAddDataAggregatorWidget;
+    // Widgets metadata
+    QHash<DataWidgetType, QString> _dataWidgetNames;
+    QSet<DataWidgetType> _dataBoolWidgets, _dataIntWidgets, _dataFloatWidgets;
+    QHash<DataType, QSet<DataWidgetType> > _dataWidgetPossibilities;
+    QHash<InteractiveWidgetType, QString> _interactiveWidgetNames;
+    QSet<InteractiveWidgetType> _paramBoolWidgets, _paramIntWidgets,
+    _paramFloatWidgets, _paramEnumWidgets;
+    QHash<ParamType, QSet<InteractiveWidgetType> >
+            _interactiveWidgetPossibilities;
+    // Session metadata
+    QString _serverID;
+    qlonglong _referenceTimestamp;
+    // Different descriptions
+    QList<DataDescription*> *_dataDescriptions;
+    QList<ParamDescription*> *_paramDescriptions;
+    QList<StarputopDevice> *_serverDevices;
+    int _nbDataWidgets;
+    int _nbDataAggregatorWidgets;
+    int _nbInteractiveWidgets;
+    // Time references
+    QTime _preGoTimer;
+    int _preGoTime;
+    QTime _runningTime;
+    QTime _currentLockTime;
+    int _lockedTime;
+    // Get the current status bar message
+    QString statusBarMessage() const;
+    // Get the current session running time
+    int runningTime() const;
+    int currentLockTime() const;
+    int lockedTime() const;
+
+    /** SLOTS **/
+
+private slots:
+    // Actions on GUI
+    void on_actionConnect_triggered();
+    void on_actionLaunch_StarPU_triggered();
+    void on_actionSaveSessionSetup_triggered();
+    void on_actionDebug_triggered(bool enabled);
+    void on_actionQuit_triggered();
+    void on_actionPreferences_triggered();
+    void on_actionAbout_triggered();
+    void on_actionAddDataAggregatorWidget_triggered();
+    // Setters
+    // Set GUI states
+    void setConnected(bool connected);
+    void setReady(bool ready);
+    void setRunning(bool running);
+    void setDebug(bool enabled);
+    void setDisplayMode(DisplayMode displayMode);
+    // Other methods
+    void initDataWidgetLists();
+    void initInteractiveWidgetLists();
+    void displayInteractiveWidget(InteractiveWidget *interactiveWidget);
+    void removeDestroyedDataWidgets();
+    void removeDestroyedInteractiveWidgets();
+    void removeDestroyedDataAggregatorWidgets();
+    void clearDescriptions();
+    void clearDataDescriptions();
+    void clearParamDescriptions();
+    void clearWidgets();
+    void clearDataWidgets();
+    void clearInteractiveWidgets();
+    void openSession();
+    void closeSession();
+    void setStatusBarIcon(QString iconFile);
+    void setStatusBarMessage(QString message);
+    void debugLock();
+    void debugStep();
+    void sessionMainWindowSetupLoaded(MainWindowSetup mainWindowSetup);
+    void sessionParametersDockSetupLoaded(
+            ParametersDockSetup parametersDockSetup);
+    void sessionWidgetWindowsSetupLoaded(
+            QList<DataWidgetSetup> dataWidgetsSetup,
+            QList<DataAggregatorWidgetSetup> dataAggregatorWidgetsSetup);
+
+public slots:
+    void synchronizeSessionTime(qlonglong serverTimestamp);
+    void initClient(QString serverID,
+                    QList<DataDescription*> *dataDescriptions,
+                    QList<ParamDescription*> *paramDescriptions,
+                    QList<StarputopDevice> *serverDevices);
+    // Connection events handlers
+    void connectionSucceeded();
+    void connectionAborted(QString message);
+    void disconnected();
+    // GUI updates
+    void updateDataWidgetsDisplayMode(int index);
+    void updateDisplayModeIndex(int index);
+    void updateDataWidgetType(int dataId, DataWidgetType newWidget);
+    void updateInteractiveWidgetType(int paramId,
+                                     InteractiveWidgetType newWidget);
+    void updateStatusBarMessage(QString message);
+    // Responses to protocol messages
+    void protocolErrorCaught(QString errorMessage);
+    // Debug
+    void setDebugMessage(QString debugMessage);
+    void setDebugLock(QString debugLockMessage);
+    // Incoming widget update messages
+    void updateDataWidget(int dataWidgetId, bool value, qlonglong timestamp);
+    void updateDataWidget(int dataWidgetId, int value, qlonglong timestamp);
+    void updateDataWidget(int dataWidgetId, double value, qlonglong timestamp);
+    void updateInteractiveWidget(int interactiveWidgetId, bool value,
+                                 qlonglong timestamp);
+    void updateInteractiveWidget(int interactiveWidgetId, int value,
+                                 qlonglong timestamp);
+    void updateInteractiveWidget(int interactiveWidgetId, double value,
+                                 qlonglong timestamp);
+    // Incoming task update messages
+    void updateTaskPrev(int taskId, int deviceId, qlonglong timestamp,
+			qlonglong timestampStart, qlonglong timestampEnd);
+    void updateTaskStart(int taskId, int deviceId, qlonglong timestamp);
+    void updateTaskEnd(int taskId, qlonglong timestamp);
+    // Outgoing widget update messages
+    void interactiveWidgetUpdated(int interactiveWidgetId, bool value);
+    void interactiveWidgetUpdated(int interactiveWidgetId, int value);
+    void interactiveWidgetUpdated(int interactiveWidgetId, double value);
+
+    /** SIGNALS **/
+
+signals:
+    void preferencesDialogCreated(int);
+    void sessionOpened();
+    void sessionClosed();
+    void clientLaunched();
+    void dataEnabled(int dataId);
+    void dataDisabled(int dataId);
+    void paramValueUpdated(int paramId, bool paramValue);
+    void paramValueUpdated(int paramId, int paramValue);
+    void paramValueUpdated(int paramId, double paramValue);
+    void debugEnabled(bool enabled);
+    void debugStepped();
+    void debugLocked();
+};
+
+#endif // MAINWINDOW_H

+ 198 - 0
starpu-top/mainwindow.ui

@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>987</width>
+    <height>700</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>StarPU-Top</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="resources.qrc">
+    <normaloff>:/images/starputop.png</normaloff>:/images/starputop.png</iconset>
+  </property>
+  <widget class="QWidget" name="centralWidget">
+   <layout class="QGridLayout" name="gridLayout_2">
+    <property name="bottomMargin">
+     <number>1</number>
+    </property>
+    <property name="spacing">
+     <number>6</number>
+    </property>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menuBar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>987</width>
+     <height>21</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menuStarputop">
+    <property name="title">
+     <string>StarPU-Top</string>
+    </property>
+   </widget>
+   <widget class="QMenu" name="menuHelp">
+    <property name="title">
+     <string>?</string>
+    </property>
+    <addaction name="actionAbout"/>
+   </widget>
+   <widget class="QMenu" name="menuDisplay">
+    <property name="title">
+     <string>Settings</string>
+    </property>
+    <addaction name="actionPreferences"/>
+   </widget>
+   <addaction name="menuStarputop"/>
+   <addaction name="menuDisplay"/>
+   <addaction name="menuHelp"/>
+  </widget>
+  <widget class="QToolBar" name="mainToolBar">
+   <property name="windowTitle">
+    <string>Toolbar</string>
+   </property>
+   <property name="movable">
+    <bool>false</bool>
+   </property>
+   <property name="allowedAreas">
+    <set>Qt::TopToolBarArea</set>
+   </property>
+   <property name="floatable">
+    <bool>false</bool>
+   </property>
+   <attribute name="toolBarArea">
+    <enum>TopToolBarArea</enum>
+   </attribute>
+   <attribute name="toolBarBreak">
+    <bool>false</bool>
+   </attribute>
+  </widget>
+  <widget class="QStatusBar" name="statusBar"/>
+  <widget class="QDockWidget" name="parametersDock">
+   <property name="minimumSize">
+    <size>
+     <width>60</width>
+     <height>38</height>
+    </size>
+   </property>
+   <property name="contextMenuPolicy">
+    <enum>Qt::DefaultContextMenu</enum>
+   </property>
+   <property name="features">
+    <set>QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable</set>
+   </property>
+   <property name="windowTitle">
+    <string>Parameters</string>
+   </property>
+   <attribute name="dockWidgetArea">
+    <number>2</number>
+   </attribute>
+   <widget class="QWidget" name="dockWidgetContents"/>
+  </widget>
+  <action name="actionConnect">
+   <property name="icon">
+    <iconset resource="resources.qrc">
+     <normaloff>:/images/connect.png</normaloff>:/images/connect.png</iconset>
+   </property>
+   <property name="text">
+    <string>Connect to StarPU</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+C</string>
+   </property>
+  </action>
+  <action name="actionLaunch_StarPU">
+   <property name="enabled">
+    <bool>false</bool>
+   </property>
+   <property name="icon">
+    <iconset resource="resources.qrc">
+     <normaloff>:/images/play.png</normaloff>:/images/play.png</iconset>
+   </property>
+   <property name="text">
+    <string>Launch StarPU</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+L</string>
+   </property>
+  </action>
+  <action name="actionQuit">
+   <property name="icon">
+    <iconset resource="resources.qrc">
+     <normaloff>:/images/quit.png</normaloff>:/images/quit.png</iconset>
+   </property>
+   <property name="text">
+    <string>Quit</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Q</string>
+   </property>
+  </action>
+  <action name="actionHelp">
+   <property name="icon">
+    <iconset resource="resources.qrc">
+     <normaloff>:/images/help.png</normaloff>:/images/help.png</iconset>
+   </property>
+   <property name="text">
+    <string>Help</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+H</string>
+   </property>
+  </action>
+  <action name="actionAbout">
+   <property name="icon">
+    <iconset resource="resources.qrc">
+     <normaloff>:/images/about.png</normaloff>:/images/about.png</iconset>
+   </property>
+   <property name="text">
+    <string>About StarPU-Top...</string>
+   </property>
+  </action>
+  <action name="actionPreferences">
+   <property name="icon">
+    <iconset resource="resources.qrc">
+     <normaloff>:/images/preferences.png</normaloff>:/images/preferences.png</iconset>
+   </property>
+   <property name="text">
+    <string>Preferences</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+P</string>
+   </property>
+  </action>
+  <action name="actionEnable_Debug">
+   <property name="enabled">
+    <bool>false</bool>
+   </property>
+   <property name="icon">
+    <iconset resource="resources.qrc">
+     <normaloff>:/images/debugon.png</normaloff>:/images/debugon.png</iconset>
+   </property>
+   <property name="text">
+    <string>Enable Debug</string>
+   </property>
+  </action>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources>
+  <include location="resources.qrc"/>
+ </resources>
+ <connections/>
+</ui>

+ 486 - 0
starpu-top/preferencesdialog.cpp

@@ -0,0 +1,486 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "preferencesdialog.h"
+#include "ui_preferencesdialog.h"
+#include "mainwindow.h"
+#include "configurationmanager.h"
+#include "sessionsetupmanager.h"
+#include <QCloseEvent>
+#include <QMessageBox>
+#include <QDir>
+
+const QString DEFAULT_SESSION_SETUP_NAME = "<default>";
+
+PreferencesDialog::PreferencesDialog(MainWindow *mainWindow,
+                                     ConfigurationManager *configurationManager,
+                                     SessionSetupManager *sessionSetupManger,
+                                     int activeTab) :
+QDialog(mainWindow), ui(new Ui::PreferencesDialog)
+{
+    ui->setupUi(this);
+
+    _mainWindow = mainWindow;
+    _configurationManager = configurationManager;
+    _sessionSetupManager = sessionSetupManger;
+    _dataWidgetNames = _mainWindow->dataWidgetNames();
+    _dataWidgetPossibilities = _mainWindow->dataWidgetPossibilities();
+    _interactiveWidgetNames = _mainWindow->interactiveWidgetNames();
+    _interactiveWidgetPossibilities
+            = _mainWindow->interactiveWidgetPossibilities();
+
+    ui->ipEdit->setText(_configurationManager->serverHost());
+    ui->portEdit->setValue(_configurationManager->serverPort());
+    ui->commandEdit->setText(_configurationManager->commandLine());
+    ui->connectionSSHGroupBox->setChecked(_configurationManager);
+    ui->antialiasingCheckBox->setChecked(_configurationManager->antialiasing());
+
+    ui->displayModeComboBox->addItem(tr("Flying windows"),
+                                     DISPLAY_FLYING_WINDOWS);
+    ui->displayModeComboBox->addItem(tr("MDI, normal"), DISPLAY_MDI_NORMAL);
+
+    ui->preferencesTab->setCurrentIndex(activeTab);
+
+    // Synchronize display mode indexes with the main window's toolbar
+    QObject::connect(_mainWindow, SIGNAL(preferencesDialogCreated(int)),
+                     this, SLOT(updateDisplayModeIndex(int)));
+    QObject::connect(ui->displayModeComboBox, SIGNAL(currentIndexChanged(int)),
+                     _mainWindow, SLOT(updateDisplayModeIndex(int)));
+    // Synchronize descriptions setup when session setup is loaded
+    QObject::connect(
+            _mainWindow->sessionSetupManager(),
+            SIGNAL(
+                    descriptionsSetupLoaded(QList<DataDescriptionSetup> ,
+                                            QList<ParamDescriptionSetup> )),
+            this,
+            SLOT(
+                    sessionDescriptionsSetupLoaded(
+                            QList<DataDescriptionSetup> ,
+                            QList<ParamDescriptionSetup> )));
+    // Synchronize main window setup when session setup is loaded
+    QObject::connect(_mainWindow->sessionSetupManager(),
+                     SIGNAL(mainWindowSetupLoaded(MainWindowSetup)), this,
+                     SLOT(sessionMainWindowSetupLoaded(MainWindowSetup)));
+
+    if (_mainWindow->isConnected())
+    {
+        ui->connectionServerGroupBox->setEnabled(false);
+    }
+    if (_mainWindow->isReady() == false)
+    {
+        ui->displayWidgetsGroupBox->setEnabled(false);
+    }
+
+    displayWidgetPreferences();
+    displaySessionSetupsList();
+}
+
+PreferencesDialog::~PreferencesDialog()
+{
+    delete ui;
+}
+
+void PreferencesDialog::changeEvent(QEvent *e)
+{
+    QDialog::changeEvent(e);
+    switch (e->type())
+    {
+    case QEvent::LanguageChange:
+        ui->retranslateUi(this);
+        break;
+    default:
+        break;
+    }
+}
+
+void PreferencesDialog::closeEvent(QCloseEvent *ce)
+{
+    _configurationManager->setServerHost(ui->ipEdit->text());
+    _configurationManager->setServerPort(ui->portEdit->value());
+    _configurationManager->setCommandLine(ui->commandEdit->text());
+    _configurationManager->setAntialiasing(
+            ui->antialiasingCheckBox->isChecked());
+    _configurationManager->setSSH(ui->connectionSSHGroupBox->isChecked());
+
+    ce->accept();
+}
+
+void PreferencesDialog::displayWidgetPreferences()
+{
+    // Read data descriptions
+    for (int i = 0; i < _mainWindow->dataDescriptions()->count(); i++)
+    {
+        DataDescription *dataDescription = _mainWindow->dataDescriptions()->at(
+                i);
+
+        // Init UI
+        QGridLayout *layout = (QGridLayout*) ui->dataWidgetsGroupBox->layout();
+        layout->addWidget(new QLabel(dataDescription->descriptionString), i, 0,
+                          Qt::AlignHCenter);
+        QComboBox *dataWidgetList = new QComboBox();
+        dataWidgetList->setMinimumWidth(100);
+
+        // Init list
+        int dataId = dataDescription->id;
+        DataType dataType = dataDescription->type;
+        DataWidgetListItemData dataStruct;
+        dataStruct.id = dataId;
+        QVariant data;
+        QList < DataWidgetType > dataWidgetPossibilities
+                = _dataWidgetPossibilities->value(dataType).values();
+
+        int currentDataWidgetIndex;
+        for (int j = 0; j < dataWidgetPossibilities.count(); j++)
+        {
+            DataWidgetType widget = dataWidgetPossibilities.at(j);
+            if (widget == dataDescription->widget)
+            {
+                currentDataWidgetIndex = j;
+            }
+            dataStruct.widget = widget;
+            data.setValue(dataStruct);
+            dataWidgetList->addItem(_dataWidgetNames->value(widget), data);
+        }
+        // Last item : MUST be DATA_WIDGET_NONE
+        dataStruct.widget = DATA_WIDGET_NONE;
+        data.setValue(dataStruct);
+        dataWidgetList->addItem(
+                _dataWidgetNames->value(DATA_WIDGET_NONE), data);
+
+        // Init index
+        if (dataDescription->widget == DATA_WIDGET_NONE)
+        { // NONE is the last item
+            dataWidgetList->setCurrentIndex(dataWidgetList->count() - 1);
+        }
+        else
+        {
+            dataWidgetList->setCurrentIndex(currentDataWidgetIndex);
+        }
+
+        QObject::connect(dataWidgetList, SIGNAL(currentIndexChanged(int)),
+                         this, SLOT(updateDataWidgetType(int)));
+        _dataWidgetListComboBoxes.append(dataWidgetList);
+        layout->addWidget(dataWidgetList, i, 1, Qt::AlignHCenter);
+    }
+
+    // Param descriptions
+    for (int i = 0; i < _mainWindow->paramDescriptions()->count(); i++)
+    {
+        ParamDescription *paramDescription =
+                _mainWindow->paramDescriptions()->at(i);
+
+        QGridLayout *layout =
+                (QGridLayout*) ui->interactiveWidgetsGroupBox->layout();
+        layout->addWidget(new QLabel(paramDescription->descriptionString), i,
+                          0, Qt::AlignHCenter);
+        QComboBox *interactiveWidgetList = new QComboBox();
+        interactiveWidgetList->setMinimumWidth(100);
+
+        // Init list
+        int paramId = paramDescription->id;
+        ParamType paramType = paramDescription->type;
+        InteractiveWidgetListItemData dataStruct;
+        dataStruct.id = paramId;
+        QVariant data;
+        QList < InteractiveWidgetType > interactiveWidgetPossibilities
+                = _interactiveWidgetPossibilities->value(paramType).values();
+
+        int currentInteractiveWidgetIndex;
+        for (int j = 0; j < interactiveWidgetPossibilities.count(); j++)
+        {
+            InteractiveWidgetType widget = interactiveWidgetPossibilities.at(j);
+            if (widget == paramDescription->widget)
+            {
+                currentInteractiveWidgetIndex = j;
+            }
+            dataStruct.widget = widget;
+            data.setValue(dataStruct);
+            interactiveWidgetList->addItem(
+                    _interactiveWidgetNames->value(widget), data);
+        }
+
+        // Init index
+        interactiveWidgetList->setCurrentIndex(currentInteractiveWidgetIndex);
+
+        QObject::connect(interactiveWidgetList,
+                         SIGNAL(currentIndexChanged(int)),
+                         this, SLOT(updateInteractiveWidgetType(int)));
+        _interactiveWidgetListComboBoxes.append(interactiveWidgetList);
+        layout->addWidget(interactiveWidgetList, i, 1, Qt::AlignHCenter);
+    }
+}
+
+void PreferencesDialog::displaySessionSetupsList()
+{
+    // Default session setup must be the first index
+    ui->loadSessionSetupComboBox->addItem(DEFAULT_SESSION_SETUP_NAME);
+
+    QDir sessionSetupsDir = QDir(SESSION_SETUPS_DIR);
+    QStringList filter;
+    filter << "*" + SESSION_SETUPS_FILEEXT;
+    sessionSetupsDir.setNameFilters(filter);
+    sessionSetupsDir.setSorting(QDir::Time);
+    QStringList sessionSetupFiles = sessionSetupsDir.entryList();
+
+    QStringList sessionSetupNames;
+    for (int i = 0; i < sessionSetupFiles.count(); i++)
+    {
+        QString sessionSetupFile = sessionSetupFiles.at(i);
+        QString sessionSetupName = sessionSetupFile;
+        sessionSetupName.chop(SESSION_SETUPS_FILEEXT.size());
+        sessionSetupNames.append(sessionSetupName);
+    }
+    ui->loadSessionSetupComboBox->addItems(sessionSetupNames);
+
+    ui->loadSessionSetupComboBox->setCurrentIndex(0);
+    QObject::connect(ui->loadSessionSetupComboBox,
+                     SIGNAL(currentIndexChanged(QString)), this,
+                     SLOT(loadSessionSetup(QString)));
+}
+
+void PreferencesDialog::updateDisplayModeIndex(int index)
+{
+    ui->displayModeComboBox->setCurrentIndex(index);
+}
+
+void PreferencesDialog::updateDataWidgetType(int index)
+{
+    QComboBox *dataWidgetList = (QComboBox*) QObject::sender();
+    QVariant data = dataWidgetList->itemData(index, Qt::UserRole);
+    DataWidgetListItemData dataStruct;
+
+    Q_ASSERT_X(data.canConvert<DataWidgetListItemData> () == true,
+               "PreferencesDialog::updateDataWidgetType()",
+               "Data extraction from QVariant failed !");
+
+    dataStruct = data.value<DataWidgetListItemData> ();
+    int dataId = dataStruct.id;
+    DataWidgetType newWidget = dataStruct.widget;
+
+    _mainWindow->updateDataWidgetType(dataId, newWidget);
+}
+
+void PreferencesDialog::updateInteractiveWidgetType(int index)
+{
+    QComboBox *interactiveWidgetList = (QComboBox*) QObject::sender();
+    QVariant data = interactiveWidgetList->itemData(index, Qt::UserRole);
+    InteractiveWidgetListItemData dataStruct;
+
+    Q_ASSERT_X(data.canConvert<InteractiveWidgetListItemData> () == true,
+               "PreferencesDialog::updateInteractiveWidgetType()",
+               "Data extraction from QVariant failed !");
+
+    dataStruct = data.value<InteractiveWidgetListItemData> ();
+    int paramId = dataStruct.id;
+
+    InteractiveWidgetType newWidget = dataStruct.widget;
+    _mainWindow->updateInteractiveWidgetType(paramId, newWidget);
+}
+
+void PreferencesDialog::loadSessionSetup(QString sessionSetupName)
+{
+    if (sessionSetupName.compare(DEFAULT_SESSION_SETUP_NAME) == 0)
+    {
+        qDebug() << "PreferencesDialog : loading default session setup";
+
+        // Load default data widgets
+        loadDefaultDataWidgets();
+
+        // Load default interactive widgets
+        loadDefaultInteractiveWidgets();
+    }
+    else
+    {
+        qDebug() << "PreferencesDialog : loading session setup"
+                << sessionSetupName;
+
+        if (_sessionSetupManager->loadSessionSetup(sessionSetupName) == true)
+        {
+            qDebug() << "PreferencesDialog : loaded session setup successfully";
+        }
+        else
+        {
+            QMessageBox::warning(this, tr("StarPU-Top"),
+                                 tr("Couldn't load the session setup !"),
+                                 QMessageBox::Ok);
+
+            QComboBox *comboBox = (QComboBox*) QObject::sender();
+            int indexToRemove = comboBox->currentIndex();
+            comboBox->setCurrentIndex(0);
+            comboBox->removeItem(indexToRemove);
+        }
+    }
+}
+
+void PreferencesDialog::loadDefaultDataWidgets()
+{
+    for (int i = 0; i < _dataWidgetListComboBoxes.count(); i++)
+    {
+        for (int j = 0; _dataWidgetListComboBoxes.at(i)->count(); j++)
+        {
+            Q_ASSERT_X(
+                    _dataWidgetListComboBoxes.at(i)->itemData(j). canConvert<
+                    DataWidgetListItemData> () == true,
+                    "PreferencesDialog::loadSessionSetup()",
+                    "Data extraction from QVariant failed !");
+
+            DataWidgetListItemData dataStruct =
+                    _dataWidgetListComboBoxes.at(i)->itemData(j).value<
+                    DataWidgetListItemData> ();
+            if (dataStruct.widget == DEFAULT_DATA_WIDGET_BOOL
+                || dataStruct.widget == DEFAULT_DATA_WIDGET_INT
+                || dataStruct.widget == DEFAULT_DATA_WIDGET_FLOAT)
+            {
+                _dataWidgetListComboBoxes.at(i)->setCurrentIndex(j);
+                break;
+            }
+        }
+    }
+}
+
+void PreferencesDialog::loadDefaultInteractiveWidgets()
+{
+    for (int i = 0; i < _interactiveWidgetListComboBoxes.count(); i++)
+    {
+        for (int j = 0; _interactiveWidgetListComboBoxes.at(i)->count(); j++)
+        {
+            Q_ASSERT_X(
+                    _interactiveWidgetListComboBoxes.
+                    at(i)->itemData(j). canConvert<
+                    InteractiveWidgetListItemData> () == true,
+                    "PreferencesDialog::loadSessionSetup()",
+                    "Data extraction from QVariant failed !");
+
+            InteractiveWidgetListItemData dataStruct =
+                    _interactiveWidgetListComboBoxes.at(i) ->itemData(j).value<
+                    InteractiveWidgetListItemData> ();
+            if (dataStruct.widget == DEFAULT_INTERACTIVE_WIDGET_BOOL
+                || dataStruct.widget == DEFAULT_INTERACTIVE_WIDGET_INT
+                || dataStruct.widget == DEFAULT_INTERACTIVE_WIDGET_FLOAT
+                || dataStruct.widget == DEFAULT_INTERACTIVE_WIDGET_ENUM)
+            {
+                _interactiveWidgetListComboBoxes.at(i)->setCurrentIndex(j);
+                break;
+            }
+        }
+    }
+}
+
+void PreferencesDialog::sessionDescriptionsSetupLoaded(
+        QList<DataDescriptionSetup> dataDescriptionsSetup,
+        QList<ParamDescriptionSetup> paramDescriptionsSetup)
+{
+    qDebug()
+            << "PreferencesDialog : "
+            "restoring descriptions setup from another session";
+
+    // Load data descriptions setup
+    for (int i = 0; i < dataDescriptionsSetup.count(); i++)
+    {
+        // The comboboxes are created following the order of the descriptions
+        int newIndex = indexOfDataWidget(_dataWidgetListComboBoxes.at(i),
+                                         dataDescriptionsSetup.at(i).widget);
+        Q_ASSERT_X(newIndex != -1, "PreferencesDialog::sessionSetupLoaded()",
+                   "Couldn't find loaded data widget index in the list !");
+
+        _dataWidgetListComboBoxes.at(i)->setCurrentIndex(newIndex);
+    }
+    // Load param descriptions setup
+    for (int i = 0; i < paramDescriptionsSetup.count(); i++)
+    {
+        // The comboboxes are created following the order of the descriptions
+        int newIndex = indexOfInteractiveWidget(
+                _interactiveWidgetListComboBoxes.at(i),
+                paramDescriptionsSetup.at(i).widget);
+        Q_ASSERT_X(newIndex != -1, "PreferencesDialog::sessionSetupLoaded()",
+                   "Couldn't find loaded interactive widget index in the list !");
+
+        _interactiveWidgetListComboBoxes.at(i)->setCurrentIndex(newIndex);
+    }
+}
+
+void PreferencesDialog::sessionMainWindowSetupLoaded(
+        MainWindowSetup mainWindowSetup)
+{
+    if (_mainWindow->displayMode() != mainWindowSetup.displayMode)
+    {
+        for (int i = 0; i < ui->displayModeComboBox->count(); i++)
+        {
+            DisplayMode displayMode =
+                    (DisplayMode) ui->displayModeComboBox ->itemData(i).toInt();
+            if (displayMode == mainWindowSetup.displayMode)
+            {
+                ui->displayModeComboBox->setCurrentIndex(i);
+                return;
+            }
+        }
+    }
+}
+
+// Util methods
+int PreferencesDialog::indexOfDataWidget(QComboBox* dataWidgetList,
+                                         DataWidgetType widget)
+{
+    for (int i = 0; dataWidgetList->count(); i++)
+    {
+        Q_ASSERT_X(
+                dataWidgetList->itemData(i)
+                . canConvert<DataWidgetListItemData> ()
+                == true, "PreferencesDialog::indexOfDataWidget()",
+                "Data extraction from QVariant failed !");
+
+        DataWidgetListItemData dataStruct = dataWidgetList->itemData(i).value<
+                                            DataWidgetListItemData> ();
+        if (dataStruct.widget == widget)
+        {
+            return i;
+        }
+    }
+
+    return -1;
+}
+
+int PreferencesDialog::indexOfInteractiveWidget(
+        QComboBox* interactiveWidgetList, InteractiveWidgetType widget)
+{
+    for (int i = 0; interactiveWidgetList->count(); i++)
+    {
+        Q_ASSERT_X(
+                interactiveWidgetList->itemData(i). canConvert<
+                InteractiveWidgetListItemData> () == true,
+                "PreferencesDialog::indexOfInteractiveWidget()",
+                "Data extraction from QVariant failed !");
+
+        InteractiveWidgetListItemData dataStruct =
+                interactiveWidgetList->itemData(i).value<
+                InteractiveWidgetListItemData> ();
+        if (dataStruct.widget == widget)
+        {
+            return i;
+        }
+    }
+
+    return -1;
+}

+ 100 - 0
starpu-top/preferencesdialog.h

@@ -0,0 +1,100 @@
+/*
+= StarPU-Top for StarPU =
+
+Copyright (C) 2011 
+William Braik
+Yann Courtois
+Jean-Marie Couteyen
+Anthony Roy
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef PREFERENCESDIALOG_H
+#define PREFERENCESDIALOG_H
+
+class MainWindow;
+class ConfigurationManager;
+class SessionSetupManager;
+
+#include <QMetaType>
+#include <QDialog>
+#include <QComboBox>
+#include "starputoptypes.h"
+
+namespace Ui
+{
+    class PreferencesDialog;
+}
+
+class PreferencesDialog: public QDialog
+{ /* The preferences panel of the application.
+ Each type of preferences is in a different tab. */
+    Q_OBJECT
+
+public:
+    explicit PreferencesDialog(MainWindow *mainWindow,
+                               ConfigurationManager *configurationManager,
+                               SessionSetupManager *sessionSetupManger, int activeTab = 0);
+    ~PreferencesDialog();
+
+protected:
+    // Events
+    void changeEvent(QEvent *e);
+    void closeEvent(QCloseEvent *ce);
+
+private:
+    // GUI components
+    Ui::PreferencesDialog *ui;
+    QList<QComboBox*> _dataWidgetListComboBoxes;
+    QList<QComboBox*> _interactiveWidgetListComboBoxes;
+    // Components
+    MainWindow *_mainWindow;
+    ConfigurationManager *_configurationManager;
+    SessionSetupManager *_sessionSetupManager;
+    // Metadata
+    const QHash<DataWidgetType, QString> *_dataWidgetNames;
+    const QHash<DataType, QSet<DataWidgetType> > *_dataWidgetPossibilities;
+    const QHash<InteractiveWidgetType, QString> *_interactiveWidgetNames;
+    const QHash<ParamType, QSet<InteractiveWidgetType> >
+            *_interactiveWidgetPossibilities;
+
+    // Util methods
+    int indexOfDataWidget(QComboBox* dataWidgetList, DataWidgetType widget);
+    int indexOfInteractiveWidget(QComboBox* interactiveWidgetList,
+                                 InteractiveWidgetType widget);
+
+private slots:
+    // Other methods
+    void displayWidgetPreferences();
+    void displaySessionSetupsList();
+    void updateDisplayModeIndex(int index);
+    void updateDataWidgetType(int index);
+    void updateInteractiveWidgetType(int index);
+    void loadSessionSetup(QString fileName);
+    void loadDefaultDataWidgets();
+    void loadDefaultInteractiveWidgets();
+    void sessionDescriptionsSetupLoaded(
+            QList<DataDescriptionSetup> dataDescriptionsSetup,
+            QList<ParamDescriptionSetup> paramDescriptionsSetup);
+    void sessionMainWindowSetupLoaded(MainWindowSetup mainWindowSetup);
+};
+
+// Model structs for the widget choice comboboxes
+Q_DECLARE_METATYPE( DataWidgetListItemData)
+Q_DECLARE_METATYPE(InteractiveWidgetListItemData)
+
+#endif // PREFERENCESDIALOG_H

+ 268 - 0
starpu-top/preferencesdialog.ui

@@ -0,0 +1,268 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PreferencesDialog</class>
+ <widget class="QDialog" name="PreferencesDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>387</width>
+    <height>490</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>Preferences</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="resources.qrc">
+    <normaloff>:/images/preferences.png</normaloff>:/images/preferences.png</iconset>
+  </property>
+  <property name="modal">
+   <bool>true</bool>
+  </property>
+  <layout class="QGridLayout" name="gridLayout_6">
+   <item row="0" column="0">
+    <widget class="QTabWidget" name="preferencesTab">
+     <property name="minimumSize">
+      <size>
+       <width>250</width>
+       <height>0</height>
+      </size>
+     </property>
+     <property name="currentIndex">
+      <number>0</number>
+     </property>
+     <widget class="QWidget" name="connectionTab">
+      <attribute name="title">
+       <string>Connection</string>
+      </attribute>
+      <layout class="QGridLayout" name="gridLayout_2">
+       <item row="0" column="0">
+        <widget class="QGroupBox" name="connectionServerGroupBox">
+         <property name="title">
+          <string>Server settings</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_4">
+          <item row="2" column="1">
+           <widget class="QLabel" name="portLabel">
+            <property name="text">
+             <string>Port</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="QLabel" name="ipLabel">
+            <property name="text">
+             <string>IP Address</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="2">
+           <widget class="QLineEdit" name="ipEdit">
+            <property name="text">
+             <string>127.0.0.1</string>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="2">
+           <widget class="QSpinBox" name="portEdit">
+            <property name="accelerated">
+             <bool>true</bool>
+            </property>
+            <property name="minimum">
+             <number>1024</number>
+            </property>
+            <property name="maximum">
+             <number>65535</number>
+            </property>
+            <property name="value">
+             <number>2011</number>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="1" column="0">
+        <widget class="QGroupBox" name="connectionSSHGroupBox">
+         <property name="title">
+          <string>SSH</string>
+         </property>
+         <property name="checkable">
+          <bool>true</bool>
+         </property>
+         <property name="checked">
+          <bool>false</bool>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_11">
+          <item row="0" column="0">
+           <widget class="QLabel" name="commandLabel">
+            <property name="text">
+             <string>Command Line</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QLineEdit" name="commandEdit">
+            <property name="text">
+             <string>ssh -L</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="displayTab">
+      <attribute name="title">
+       <string>Display</string>
+      </attribute>
+      <layout class="QGridLayout" name="gridLayout_5">
+       <item row="2" column="0" colspan="2">
+        <widget class="QGroupBox" name="displayWidgetsGroupBox">
+         <property name="title">
+          <string>Widgets</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_9">
+          <item row="4" column="0" colspan="2">
+           <widget class="QScrollArea" name="dataWidgetsScroll">
+            <property name="widgetResizable">
+             <bool>true</bool>
+            </property>
+            <widget class="QWidget" name="scrollAreaWidgetContents">
+             <property name="geometry">
+              <rect>
+               <x>0</x>
+               <y>0</y>
+               <width>100</width>
+               <height>51</height>
+              </rect>
+             </property>
+             <layout class="QGridLayout" name="gridLayout_7">
+              <item row="1" column="0">
+               <widget class="QGroupBox" name="dataWidgetsGroupBox">
+                <property name="enabled">
+                 <bool>true</bool>
+                </property>
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
+                <property name="maximumSize">
+                 <size>
+                  <width>16777215</width>
+                  <height>16777215</height>
+                 </size>
+                </property>
+                <property name="title">
+                 <string>Data widgets</string>
+                </property>
+                <property name="flat">
+                 <bool>false</bool>
+                </property>
+                <property name="checkable">
+                 <bool>false</bool>
+                </property>
+                <layout class="QGridLayout" name="gridLayout"/>
+               </widget>
+              </item>
+             </layout>
+            </widget>
+           </widget>
+          </item>
+          <item row="5" column="0" colspan="2">
+           <widget class="QScrollArea" name="interactiveWidgetsScroll">
+            <property name="widgetResizable">
+             <bool>true</bool>
+            </property>
+            <widget class="QWidget" name="scrollAreaWidgetContents_2">
+             <property name="geometry">
+              <rect>
+               <x>0</x>
+               <y>0</y>
+               <width>130</width>
+               <height>51</height>
+              </rect>
+             </property>
+             <layout class="QGridLayout" name="gridLayout_8">
+              <item row="0" column="0">
+               <widget class="QGroupBox" name="interactiveWidgetsGroupBox">
+                <property name="title">
+                 <string>Interactive widgets</string>
+                </property>
+                <layout class="QGridLayout" name="gridLayout_3"/>
+               </widget>
+              </item>
+             </layout>
+            </widget>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="QComboBox" name="loadSessionSetupComboBox"/>
+          </item>
+          <item row="1" column="0">
+           <widget class="QLabel" name="loadSessionSetupLabel">
+            <property name="text">
+             <string>Load a session setup</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="0" column="0" colspan="2">
+        <widget class="QGroupBox" name="displayGeneralGroupBox">
+         <property name="title">
+          <string>General</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_10">
+          <item row="0" column="0">
+           <widget class="QLabel" name="displayModeLabel">
+            <property name="text">
+             <string>Display mode</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QComboBox" name="displayModeComboBox"/>
+          </item>
+          <item row="1" column="0">
+           <widget class="QLabel" name="antialiasingLabel">
+            <property name="text">
+             <string>Enable antialiasing</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="QCheckBox" name="antialiasingCheckBox">
+            <property name="text">
+             <string/>
+            </property>
+            <property name="checked">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources>
+  <include location="resources.qrc"/>
+ </resources>
+ <connections/>
+</ui>

+ 91 - 0
starpu-top/qledindicator/qledindicator.cpp

@@ -0,0 +1,91 @@
+/***************************************************************************
+ *   Copyright (C) 2010 by Tn                                              *
+ *   thenobody@poczta.fm                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library General Public     *
+ *   License along with this program; if not, write to the                 *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include <QPainter>
+
+#include "qledindicator.h"
+
+const qreal QLedIndicator::scaledSize = 1000;
+
+QLedIndicator::QLedIndicator(QWidget *parent) :
+	QWidget(parent)
+{
+	this->checked = false;
+	onColor1 = QColor(0, 255, 0);
+	onColor2 = QColor(0, 192, 0);
+	offColor1 = QColor(255, 0, 0);
+	offColor2 = QColor(192, 0, 0);
+}
+
+void QLedIndicator::paintEvent(QPaintEvent *event)
+{
+	qreal realSize = qMin(width() / 1.3, height() / 1.3);
+
+	QRadialGradient gradient;
+	QPainter painter(this);
+	QPen pen(Qt::black);
+	pen.setWidth(1);
+
+	painter.setRenderHint(QPainter::Antialiasing);
+	painter.translate(width() / 2, height() / 2);
+	painter.scale(realSize / scaledSize, realSize / scaledSize);
+
+	gradient = QRadialGradient(QPointF(-500, -500), 1500, QPointF(-500, -500));
+	gradient.setColorAt(0, QColor(224, 224, 224));
+	gradient.setColorAt(1, QColor(28, 28, 28));
+	painter.setPen(pen);
+	painter.setBrush(QBrush(gradient));
+	painter.drawEllipse(QPointF(0, 0), 500, 500);
+
+	gradient = QRadialGradient(QPointF(500, 500), 1500, QPointF(500, 500));
+	gradient.setColorAt(0, QColor(224, 224, 224));
+	gradient.setColorAt(1, QColor(28, 28, 28));
+	painter.setPen(pen);
+	painter.setBrush(QBrush(gradient));
+	painter.drawEllipse(QPointF(0, 0), 450, 450);
+
+	painter.setPen(pen);
+	if (isChecked())
+	{
+		gradient = QRadialGradient(QPointF(-500, -500), 1500,
+				QPointF(-500, -500));
+		gradient.setColorAt(0, onColor1);
+		gradient.setColorAt(1, onColor2);
+	}
+	else
+	{
+		gradient = QRadialGradient(QPointF(500, 500), 1500, QPointF(500, 500));
+		gradient.setColorAt(0, offColor1);
+		gradient.setColorAt(1, offColor2);
+	}
+	painter.setBrush(gradient);
+	painter.drawEllipse(QPointF(0, 0), 400, 400);
+}
+
+void QLedIndicator::setChecked(bool checked)
+{
+	this->checked = checked;
+	update();
+}
+
+bool QLedIndicator::isChecked() const
+{
+	return this->checked;
+}

+ 83 - 0
starpu-top/qledindicator/qledindicator.h

@@ -0,0 +1,83 @@
+/***************************************************************************
+ *   Copyright (C) 2010 by Tn                                              *
+ *   thenobody@poczta.fm                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Library General Public License as       *
+ *   published by the Free Software Foundation; either version 3 of the    *
+ *   License, or (at your option) any later version.                       *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU Library General Public     *
+ *   License along with this program; if not, write to the                 *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef QLEDINDICATOR_H
+#define QLEDINDICATOR_H
+
+#include <QWidget>
+#include <QResizeEvent>
+#include <QColor>
+#include <QDebug>
+
+class QLedIndicator: public QWidget
+{
+	Q_PROPERTY(QColor onColor1 WRITE setOnColor1 READ getOnColor1 );Q_PROPERTY(QColor onColor2 WRITE setOnColor2 READ getOnColor2 );Q_PROPERTY(QColor offColor1 WRITE setOffColor1 READ getOffColor1 );Q_PROPERTY(QColor offColor2 WRITE setOffColor2 READ getOffColor2 );Q_OBJECT
+public:
+	QLedIndicator(QWidget *parent);
+
+	void setOnColor1(QColor c)
+	{
+		onColor1 = c;
+	}
+	void setOffColor1(QColor c)
+	{
+		offColor1 = c;
+	}
+	void setOnColor2(QColor c)
+	{
+		onColor2 = c;
+	}
+	void setOffColor2(QColor c)
+	{
+		offColor2 = c;
+	}
+
+	QColor getOnColor1(void)
+	{
+		return onColor1;
+	}
+	QColor getOffColor1(void)
+	{
+		return offColor1;
+	}
+	QColor getOnColor2(void)
+	{
+		return onColor2;
+	}
+	QColor getOffColor2(void)
+	{
+		return offColor2;
+	}
+
+	void setChecked(bool checked);
+	bool isChecked() const;
+
+protected:
+	virtual void paintEvent(QPaintEvent *event);
+
+private:
+	bool checked;
+	static const qreal scaledSize;
+	QColor onColor1, offColor1;
+	QColor onColor2, offColor2;
+	QPixmap ledBuffer;
+};
+
+#endif // QLEDINDICATOR_H

+ 310 - 0
starpu-top/qwt/qwt_abstract_scale.cpp

@@ -0,0 +1,310 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#include "qwt_abstract_scale.h"
+#include "qwt_scale_engine.h"
+#include "qwt_scale_draw.h"
+#include "qwt_scale_div.h"
+#include "qwt_scale_map.h"
+#include "qwt_interval.h"
+
+class QwtAbstractScale::PrivateData
+{
+public:
+    PrivateData():
+        maxMajor( 5 ),
+        maxMinor( 3 ),
+        stepSize( 0.0 ),
+        autoScale( true )
+    {
+        scaleEngine = new QwtLinearScaleEngine;
+        scaleDraw = new QwtScaleDraw();
+    }
+
+    ~PrivateData()
+    {
+        delete scaleEngine;
+        delete scaleDraw;
+    }
+
+    QwtScaleEngine *scaleEngine;
+    QwtAbstractScaleDraw *scaleDraw;
+
+    int maxMajor;
+    int maxMinor;
+    double stepSize;
+
+    bool autoScale;
+};
+
+/*!
+  Constructor
+
+  Creates a default QwtScaleDraw and a QwtLinearScaleEngine.
+  Autoscaling is enabled, and the stepSize is initialized by 0.0.
+*/
+
+QwtAbstractScale::QwtAbstractScale()
+{
+    d_data = new PrivateData;
+    rescale( 0.0, 100.0 );
+}
+
+//! Destructor
+QwtAbstractScale::~QwtAbstractScale()
+{
+    delete d_data;
+}
+
+/*!
+  \brief Specify a scale.
+
+  Disable autoscaling and define a scale by an interval and a step size
+
+  \param vmin lower limit of the scale interval
+  \param vmax upper limit of the scale interval
+  \param stepSize major step size
+  \sa setAutoScale()
+*/
+void QwtAbstractScale::setScale( double vmin, double vmax, double stepSize )
+{
+    d_data->autoScale = false;
+    d_data->stepSize = stepSize;
+
+    rescale( vmin, vmax, stepSize );
+}
+
+/*!
+  \brief Specify a scale.
+
+  Disable autoscaling and define a scale by an interval and a step size
+
+  \param interval Interval
+  \param stepSize major step size
+  \sa setAutoScale()
+*/
+void QwtAbstractScale::setScale( const QwtInterval &interval, double stepSize )
+{
+    setScale( interval.minValue(), interval.maxValue(), stepSize );
+}
+
+
+/*!
+  \brief Specify a scale.
+
+  Disable autoscaling and define a scale by a scale division
+
+  \param scaleDiv Scale division
+  \sa setAutoScale()
+*/
+void QwtAbstractScale::setScale( const QwtScaleDiv &scaleDiv )
+{
+    d_data->autoScale = false;
+
+    if ( scaleDiv != d_data->scaleDraw->scaleDiv() )
+    {
+        d_data->scaleDraw->setScaleDiv( scaleDiv );
+        scaleChange();
+    }
+}
+
+/*!
+  Recalculate the scale division and update the scale draw.
+
+  \param vmin Lower limit of the scale interval
+  \param vmax Upper limit of the scale interval
+  \param stepSize Major step size
+
+  \sa scaleChange()
+*/
+void QwtAbstractScale::rescale( double vmin, double vmax, double stepSize )
+{
+    const QwtScaleDiv scaleDiv = d_data->scaleEngine->divideScale(
+        vmin, vmax, d_data->maxMajor, d_data->maxMinor, stepSize );
+
+    if ( scaleDiv != d_data->scaleDraw->scaleDiv() )
+    {
+        d_data->scaleDraw->setTransformation(
+            d_data->scaleEngine->transformation() );
+        d_data->scaleDraw->setScaleDiv( scaleDiv );
+        scaleChange();
+    }
+}
+
+/*!
+  \brief Advise the widget to control the scale range internally.
+
+  Autoscaling is on by default.
+  \sa setScale(), autoScale()
+*/
+void QwtAbstractScale::setAutoScale()
+{
+    if ( !d_data->autoScale )
+    {
+        d_data->autoScale = true;
+        scaleChange();
+    }
+}
+
+/*!
+  \return \c true if autoscaling is enabled
+*/
+bool QwtAbstractScale::autoScale() const
+{
+    return d_data->autoScale;
+}
+
+/*!
+  \brief Set the maximum number of major tick intervals.
+
+  The scale's major ticks are calculated automatically such that
+  the number of major intervals does not exceed ticks.
+  The default value is 5.
+  \param ticks maximal number of major ticks.
+  \sa QwtAbstractScaleDraw
+*/
+void QwtAbstractScale::setScaleMaxMajor( int ticks )
+{
+    if ( ticks != d_data->maxMajor )
+    {
+        d_data->maxMajor = ticks;
+        updateScaleDraw();
+    }
+}
+
+/*!
+  \brief Set the maximum number of minor tick intervals
+
+  The scale's minor ticks are calculated automatically such that
+  the number of minor intervals does not exceed ticks.
+  The default value is 3.
+  \param ticks
+  \sa QwtAbstractScaleDraw
+*/
+void QwtAbstractScale::setScaleMaxMinor( int ticks )
+{
+    if ( ticks != d_data->maxMinor )
+    {
+        d_data->maxMinor = ticks;
+        updateScaleDraw();
+    }
+}
+
+/*!
+  \return Max. number of minor tick intervals
+  The default value is 3.
+*/
+int QwtAbstractScale::scaleMaxMinor() const
+{
+    return d_data->maxMinor;
+}
+
+/*!
+  \return Max. number of major tick intervals
+  The default value is 5.
+*/
+int QwtAbstractScale::scaleMaxMajor() const
+{
+    return d_data->maxMajor;
+}
+
+/*!
+  \brief Set a scale draw
+
+  scaleDraw has to be created with new and will be deleted in
+  ~QwtAbstractScale or the next call of setAbstractScaleDraw.
+*/
+void QwtAbstractScale::setAbstractScaleDraw( QwtAbstractScaleDraw *scaleDraw )
+{
+    if ( scaleDraw == NULL || scaleDraw == d_data->scaleDraw )
+        return;
+
+    if ( d_data->scaleDraw != NULL )
+        scaleDraw->setScaleDiv( d_data->scaleDraw->scaleDiv() );
+
+    delete d_data->scaleDraw;
+    d_data->scaleDraw = scaleDraw;
+}
+
+/*!
+    \return Scale draw
+    \sa setAbstractScaleDraw()
+*/
+QwtAbstractScaleDraw *QwtAbstractScale::abstractScaleDraw()
+{
+    return d_data->scaleDraw;
+}
+
+/*!
+    \return Scale draw
+    \sa setAbstractScaleDraw()
+*/
+const QwtAbstractScaleDraw *QwtAbstractScale::abstractScaleDraw() const
+{
+    return d_data->scaleDraw;
+}
+
+void QwtAbstractScale::updateScaleDraw()
+{
+    rescale( d_data->scaleDraw->scaleDiv().lowerBound(),
+        d_data->scaleDraw->scaleDiv().upperBound(), d_data->stepSize );
+}
+
+/*!
+  \brief Set a scale engine
+
+  The scale engine is responsible for calculating the scale division,
+  and in case of auto scaling how to align the scale.
+
+  scaleEngine has to be created with new and will be deleted in
+  ~QwtAbstractScale or the next call of setScaleEngine.
+*/
+void QwtAbstractScale::setScaleEngine( QwtScaleEngine *scaleEngine )
+{
+    if ( scaleEngine != NULL && scaleEngine != d_data->scaleEngine )
+    {
+        delete d_data->scaleEngine;
+        d_data->scaleEngine = scaleEngine;
+    }
+}
+
+/*!
+    \return Scale engine
+    \sa setScaleEngine()
+*/
+const QwtScaleEngine *QwtAbstractScale::scaleEngine() const
+{
+    return d_data->scaleEngine;
+}
+
+/*!
+    \return Scale engine
+    \sa setScaleEngine()
+*/
+QwtScaleEngine *QwtAbstractScale::scaleEngine()
+{
+    return d_data->scaleEngine;
+}
+
+/*!
+  \brief Notify changed scale
+
+  Dummy empty implementation, intended to be overloaded by derived classes
+*/
+void QwtAbstractScale::scaleChange()
+{
+}
+
+/*!
+   \return abstractScaleDraw()->scaleMap()
+*/
+const QwtScaleMap &QwtAbstractScale::scaleMap() const
+{
+    return d_data->scaleDraw->scaleMap();
+}

+ 70 - 0
starpu-top/qwt/qwt_abstract_scale.h

@@ -0,0 +1,70 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#ifndef QWT_ABSTRACT_SCALE_H
+#define QWT_ABSTRACT_SCALE_H
+
+#include "qwt_global.h"
+
+class QwtScaleEngine;
+class QwtAbstractScaleDraw;
+class QwtScaleDiv;
+class QwtScaleMap;
+class QwtInterval;
+
+/*!
+  \brief An abstract base class for classes containing a scale
+
+  QwtAbstractScale is used to provide classes with a QwtScaleDraw,
+  and a QwtScaleDiv. The QwtScaleDiv might be set explicitely
+  or calculated by a QwtScaleEngine.
+*/
+
+class QWT_EXPORT QwtAbstractScale
+{
+public:
+    QwtAbstractScale();
+    virtual ~QwtAbstractScale();
+
+    void setScale( double vmin, double vmax, double step = 0.0 );
+    void setScale( const QwtInterval &, double step = 0.0 );
+    void setScale( const QwtScaleDiv & );
+
+    void setAutoScale();
+    bool autoScale() const;
+
+    void setScaleMaxMajor( int ticks );
+    int scaleMaxMinor() const;
+
+    void setScaleMaxMinor( int ticks );
+    int scaleMaxMajor() const;
+
+    void setScaleEngine( QwtScaleEngine * );
+    const QwtScaleEngine *scaleEngine() const;
+    QwtScaleEngine *scaleEngine();
+
+    const QwtScaleMap &scaleMap() const;
+
+protected:
+    void rescale( double vmin, double vmax, double step = 0.0 );
+
+    void setAbstractScaleDraw( QwtAbstractScaleDraw * );
+    const QwtAbstractScaleDraw *abstractScaleDraw() const;
+    QwtAbstractScaleDraw *abstractScaleDraw();
+
+    virtual void scaleChange();
+
+private:
+    void updateScaleDraw();
+
+    class PrivateData;
+    PrivateData *d_data;
+};
+
+#endif

+ 402 - 0
starpu-top/qwt/qwt_abstract_scale_draw.cpp

@@ -0,0 +1,402 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#include "qwt_abstract_scale_draw.h"
+#include "qwt_math.h"
+#include "qwt_text.h"
+#include "qwt_painter.h"
+#include "qwt_scale_map.h"
+#include <qpainter.h>
+#include <qpalette.h>
+#include <qmap.h>
+#include <qlocale.h>
+
+class QwtAbstractScaleDraw::PrivateData
+{
+public:
+    PrivateData():
+        components( Backbone | Ticks | Labels ),
+        spacing( 4.0 ),
+        penWidth( 0 ),
+        minExtent( 0.0 )
+    {
+        tickLength[QwtScaleDiv::MinorTick] = 4.0;
+        tickLength[QwtScaleDiv::MediumTick] = 6.0;
+        tickLength[QwtScaleDiv::MajorTick] = 8.0;
+    }
+
+    int components;
+
+    QwtScaleMap map;
+    QwtScaleDiv scldiv;
+
+    double spacing;
+    double tickLength[QwtScaleDiv::NTickTypes];
+    int penWidth;
+
+    double minExtent;
+
+    QMap<double, QwtText> labelCache;
+};
+
+/*!
+  \brief Constructor
+
+  The range of the scale is initialized to [0, 100],
+  The spacing (distance between ticks and labels) is
+  set to 4, the tick lengths are set to 4,6 and 8 pixels
+*/
+QwtAbstractScaleDraw::QwtAbstractScaleDraw()
+{
+    d_data = new QwtAbstractScaleDraw::PrivateData;
+}
+
+//! Destructor
+QwtAbstractScaleDraw::~QwtAbstractScaleDraw()
+{
+    delete d_data;
+}
+
+/*!
+  En/Disable a component of the scale
+
+  \param component Scale component
+  \param enable On/Off
+
+  \sa hasComponent()
+*/
+void QwtAbstractScaleDraw::enableComponent(
+    ScaleComponent component, bool enable )
+{
+    if ( enable )
+        d_data->components |= component;
+    else
+        d_data->components &= ~component;
+}
+
+/*!
+  Check if a component is enabled
+  \sa enableComponent()
+*/
+bool QwtAbstractScaleDraw::hasComponent( ScaleComponent component ) const
+{
+    return ( d_data->components & component );
+}
+
+/*!
+  Change the scale division
+  \param sd New scale division
+*/
+void QwtAbstractScaleDraw::setScaleDiv( const QwtScaleDiv &sd )
+{
+    d_data->scldiv = sd;
+    d_data->map.setScaleInterval( sd.lowerBound(), sd.upperBound() );
+    d_data->labelCache.clear();
+}
+
+/*!
+  Change the transformation of the scale
+  \param transformation New scale transformation
+*/
+void QwtAbstractScaleDraw::setTransformation(
+    QwtScaleTransformation *transformation )
+{
+    d_data->map.setTransformation( transformation );
+}
+
+//! \return Map how to translate between scale and pixel values
+const QwtScaleMap &QwtAbstractScaleDraw::map() const
+{
+    return d_data->map;
+}
+
+//! \return Map how to translate between scale and pixel values
+QwtScaleMap &QwtAbstractScaleDraw::scaleMap()
+{
+    return d_data->map;
+}
+
+//! \return scale division
+const QwtScaleDiv& QwtAbstractScaleDraw::scaleDiv() const
+{
+    return d_data->scldiv;
+}
+
+/*!
+  \brief Specify the width of the scale pen
+  \param width Pen width
+  \sa penWidth()
+*/
+void QwtAbstractScaleDraw::setPenWidth( int width )
+{
+    if ( width < 0 )
+        width = 0;
+
+    if ( width != d_data->penWidth )
+        d_data->penWidth = width;
+}
+
+/*!
+    \return Scale pen width
+    \sa setPenWidth()
+*/
+int QwtAbstractScaleDraw::penWidth() const
+{
+    return d_data->penWidth;
+}
+
+/*!
+  \brief Draw the scale
+
+  \param painter    The painter
+
+  \param palette    Palette, text color is used for the labels,
+                    foreground color for ticks and backbone
+*/
+void QwtAbstractScaleDraw::draw( QPainter *painter,
+    const QPalette& palette ) const
+{
+    painter->save();
+
+    QPen pen = painter->pen();
+    pen.setWidth( d_data->penWidth );
+    pen.setCosmetic( false );
+    painter->setPen( pen );
+
+    if ( hasComponent( QwtAbstractScaleDraw::Labels ) )
+    {
+        painter->save();
+        painter->setPen( palette.color( QPalette::Text ) ); // ignore pen style
+
+        const QList<double> &majorTicks =
+            d_data->scldiv.ticks( QwtScaleDiv::MajorTick );
+
+        for ( int i = 0; i < ( int )majorTicks.count(); i++ )
+        {
+            const double v = majorTicks[i];
+            if ( d_data->scldiv.contains( v ) )
+                drawLabel( painter, majorTicks[i] );
+        }
+
+        painter->restore();
+    }
+
+    if ( hasComponent( QwtAbstractScaleDraw::Ticks ) )
+    {
+        painter->save();
+
+        QPen pen = painter->pen();
+        pen.setColor( palette.color( QPalette::WindowText ) );
+        pen.setCapStyle( Qt::FlatCap );
+
+        painter->setPen( pen );
+
+        for ( int tickType = QwtScaleDiv::MinorTick;
+            tickType < QwtScaleDiv::NTickTypes; tickType++ )
+        {
+            const QList<double> &ticks = d_data->scldiv.ticks( tickType );
+            for ( int i = 0; i < ( int )ticks.count(); i++ )
+            {
+                const double v = ticks[i];
+                if ( d_data->scldiv.contains( v ) )
+                    drawTick( painter, v, d_data->tickLength[tickType] );
+            }
+        }
+
+        painter->restore();
+    }
+
+    if ( hasComponent( QwtAbstractScaleDraw::Backbone ) )
+    {
+        painter->save();
+
+        QPen pen = painter->pen();
+        pen.setColor( palette.color( QPalette::WindowText ) );
+        pen.setCapStyle( Qt::FlatCap );
+
+        painter->setPen( pen );
+
+        drawBackbone( painter );
+
+        painter->restore();
+    }
+
+    painter->restore();
+}
+
+/*!
+  \brief Set the spacing between tick and labels
+
+  The spacing is the distance between ticks and labels.
+  The default spacing is 4 pixels.
+
+  \param spacing Spacing
+
+  \sa spacing()
+*/
+void QwtAbstractScaleDraw::setSpacing( double spacing )
+{
+    if ( spacing < 0 )
+        spacing = 0;
+
+    d_data->spacing = spacing;
+}
+
+/*!
+  \brief Get the spacing
+
+  The spacing is the distance between ticks and labels.
+  The default spacing is 4 pixels.
+
+  \sa setSpacing()
+*/
+double QwtAbstractScaleDraw::spacing() const
+{
+    return d_data->spacing;
+}
+
+/*!
+  \brief Set a minimum for the extent
+
+  The extent is calculated from the coomponents of the
+  scale draw. In situations, where the labels are
+  changing and the layout depends on the extent (f.e scrolling
+  a scale), setting an upper limit as minimum extent will
+  avoid jumps of the layout.
+
+  \param minExtent Minimum extent
+
+  \sa extent(), minimumExtent()
+*/
+void QwtAbstractScaleDraw::setMinimumExtent( double minExtent )
+{
+    if ( minExtent < 0.0 )
+        minExtent = 0.0;
+
+    d_data->minExtent = minExtent;
+}
+
+/*!
+  Get the minimum extent
+  \sa extent(), setMinimumExtent()
+*/
+double QwtAbstractScaleDraw::minimumExtent() const
+{
+    return d_data->minExtent;
+}
+
+/*!
+  Set the length of the ticks
+
+  \param tickType Tick type
+  \param length New length
+
+  \warning the length is limited to [0..1000]
+*/
+void QwtAbstractScaleDraw::setTickLength(
+    QwtScaleDiv::TickType tickType, double length )
+{
+    if ( tickType < QwtScaleDiv::MinorTick ||
+        tickType > QwtScaleDiv::MajorTick )
+    {
+        return;
+    }
+
+    if ( length < 0.0 )
+        length = 0.0;
+
+    const double maxTickLen = 1000.0;
+    if ( length > maxTickLen )
+        length = maxTickLen;
+
+    d_data->tickLength[tickType] = length;
+}
+
+/*!
+    Return the length of the ticks
+
+    \sa setTickLength(), majTickLength()
+*/
+double QwtAbstractScaleDraw::tickLength( QwtScaleDiv::TickType tickType ) const
+{
+    if ( tickType < QwtScaleDiv::MinorTick ||
+        tickType > QwtScaleDiv::MajorTick )
+    {
+        return 0;
+    }
+
+    return d_data->tickLength[tickType];
+}
+
+/*!
+   The same as QwtAbstractScaleDraw::tickLength(QwtScaleDiv::MajorTick).
+*/
+double QwtAbstractScaleDraw::majTickLength() const
+{
+    return d_data->tickLength[QwtScaleDiv::MajorTick];
+}
+
+/*!
+  \brief Convert a value into its representing label
+
+  The value is converted to a plain text using
+  QLocale::system().toString(value).
+  This method is often overloaded by applications to have individual
+  labels.
+
+  \param value Value
+  \return Label string.
+*/
+QwtText QwtAbstractScaleDraw::label( double value ) const
+{
+    return QLocale::system().toString( value );
+}
+
+/*!
+   \brief Convert a value into its representing label and cache it.
+
+   The conversion between value and label is called very often
+   in the layout and painting code. Unfortunately the
+   calculation of the label sizes might be slow (really slow
+   for rich text in Qt4), so it's necessary to cache the labels.
+
+   \param font Font
+   \param value Value
+
+   \return Tick label
+*/
+const QwtText &QwtAbstractScaleDraw::tickLabel(
+    const QFont &font, double value ) const
+{
+    QMap<double, QwtText>::const_iterator it = d_data->labelCache.find( value );
+    if ( it == d_data->labelCache.end() )
+    {
+        QwtText lbl = label( value );
+        lbl.setRenderFlags( 0 );
+        lbl.setLayoutAttribute( QwtText::MinimumLayout );
+
+        ( void )lbl.textSize( font ); // initialize the internal cache
+
+        it = d_data->labelCache.insert( value, lbl );
+    }
+
+    return ( *it );
+}
+
+/*!
+   Invalidate the cache used by QwtAbstractScaleDraw::tickLabel
+
+   The cache is invalidated, when a new QwtScaleDiv is set. If
+   the labels need to be changed. while the same QwtScaleDiv is set,
+   QwtAbstractScaleDraw::invalidateCache needs to be called manually.
+*/
+void QwtAbstractScaleDraw::invalidateCache()
+{
+    d_data->labelCache.clear();
+}

+ 136 - 0
starpu-top/qwt/qwt_abstract_scale_draw.h

@@ -0,0 +1,136 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#ifndef QWT_ABSTRACT_SCALE_DRAW_H
+#define QWT_ABSTRACT_SCALE_DRAW_H
+
+#include "qwt_global.h"
+#include "qwt_scale_div.h"
+#include "qwt_text.h"
+
+class QPalette;
+class QPainter;
+class QFont;
+class QwtScaleTransformation;
+class QwtScaleMap;
+
+/*!
+  \brief A abstract base class for drawing scales
+
+  QwtAbstractScaleDraw can be used to draw linear or logarithmic scales.
+
+  After a scale division has been specified as a QwtScaleDiv object
+  using QwtAbstractScaleDraw::setScaleDiv(const QwtScaleDiv &s),
+  the scale can be drawn with the QwtAbstractScaleDraw::draw() member.
+*/
+class QWT_EXPORT QwtAbstractScaleDraw
+{
+public:
+
+    /*!
+       Components of a scale
+
+       - Backbone
+       - Ticks
+       - Labels
+
+       \sa enableComponent(), hasComponent
+    */
+
+    enum ScaleComponent
+    {
+        Backbone = 1,
+        Ticks = 2,
+        Labels = 4
+    };
+
+    QwtAbstractScaleDraw();
+    virtual ~QwtAbstractScaleDraw();
+
+    void setScaleDiv( const QwtScaleDiv &s );
+    const QwtScaleDiv& scaleDiv() const;
+
+    void setTransformation( QwtScaleTransformation * );
+    const QwtScaleMap &map() const;
+
+    void enableComponent( ScaleComponent, bool enable = true );
+    bool hasComponent( ScaleComponent ) const;
+
+    void setTickLength( QwtScaleDiv::TickType, double length );
+    double tickLength( QwtScaleDiv::TickType ) const;
+    double majTickLength() const;
+
+    void setSpacing( double margin );
+    double spacing() const;
+
+    void setPenWidth( int width );
+    int penWidth() const;
+
+    virtual void draw( QPainter *, const QPalette & ) const;
+
+    virtual QwtText label( double ) const;
+
+    /*!
+      Calculate the extent
+
+      The extent is the distcance from the baseline to the outermost
+      pixel of the scale draw in opposite to its orientation.
+      It is at least minimumExtent() pixels.
+
+      \sa setMinimumExtent(), minimumExtent()
+    */
+    virtual double extent( const QFont & ) const = 0;
+
+    void setMinimumExtent( double );
+    double minimumExtent() const;
+
+    QwtScaleMap &scaleMap();
+
+protected:
+    /*!
+       Draw a tick
+
+       \param painter Painter
+       \param value Value of the tick
+       \param len Lenght of the tick
+
+       \sa drawBackbone(), drawLabel()
+    */
+    virtual void drawTick( QPainter *painter, double value, double len ) const = 0;
+
+    /*!
+      Draws the baseline of the scale
+      \param painter Painter
+
+      \sa drawTick(), drawLabel()
+    */
+    virtual void drawBackbone( QPainter *painter ) const = 0;
+
+    /*!
+        Draws the label for a major scale tick
+
+        \param painter Painter
+        \param value Value
+
+        \sa drawTick, drawBackbone
+    */
+    virtual void drawLabel( QPainter *painter, double value ) const = 0;
+
+    void invalidateCache();
+    const QwtText &tickLabel( const QFont &, double value ) const;
+
+private:
+    QwtAbstractScaleDraw( const QwtAbstractScaleDraw & );
+    QwtAbstractScaleDraw &operator=( const QwtAbstractScaleDraw & );
+
+    class PrivateData;
+    PrivateData *d_data;
+};
+
+#endif

+ 596 - 0
starpu-top/qwt/qwt_abstract_slider.cpp

@@ -0,0 +1,596 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#include "qwt_abstract_slider.h"
+#include "qwt_math.h"
+#include <qevent.h>
+#include <qdatetime.h>
+
+#if QT_VERSION < 0x040601
+#define qFabs(x) ::fabs(x)
+#define qExp(x) ::exp(x)
+#endif
+
+class QwtAbstractSlider::PrivateData
+{
+public:
+    PrivateData():
+        scrollMode( ScrNone ),
+        mouseOffset( 0.0 ),
+        tracking( true ),
+        tmrID( 0 ),
+        updTime( 150 ),
+        mass( 0.0 ),
+        readOnly( false )
+    {
+    }
+
+    int scrollMode;
+    double mouseOffset;
+    int direction;
+    int tracking;
+
+    int tmrID;
+    int updTime;
+    int timerTick;
+    QTime time;
+    double speed;
+    double mass;
+    Qt::Orientation orientation;
+    bool readOnly;
+};
+
+/*!
+   \brief Constructor
+
+   \param orientation Orientation
+   \param parent Parent widget
+*/
+QwtAbstractSlider::QwtAbstractSlider(
+        Qt::Orientation orientation, QWidget *parent ):
+    QWidget( parent, NULL )
+{
+    d_data = new QwtAbstractSlider::PrivateData;
+    d_data->orientation = orientation;
+
+    setFocusPolicy( Qt::TabFocus );
+}
+
+//! Destructor
+QwtAbstractSlider::~QwtAbstractSlider()
+{
+    if ( d_data->tmrID )
+        killTimer( d_data->tmrID );
+
+    delete d_data;
+}
+
+/*!
+  En/Disable read only mode
+
+  In read only mode the slider can't be controlled by mouse
+  or keyboard.
+
+  \param readOnly Enables in case of true
+  \sa isReadOnly()
+*/
+void QwtAbstractSlider::setReadOnly( bool readOnly )
+{
+    d_data->readOnly = readOnly;
+    update();
+}
+
+/*!
+  In read only mode the slider can't be controlled by mouse
+  or keyboard.
+
+  \return true if read only
+  \sa setReadOnly()
+*/
+bool QwtAbstractSlider::isReadOnly() const
+{
+    return d_data->readOnly;
+}
+
+/*!
+  \brief Set the orientation.
+  \param o Orientation. Allowed values are
+           Qt::Horizontal and Qt::Vertical.
+*/
+void QwtAbstractSlider::setOrientation( Qt::Orientation o )
+{
+    d_data->orientation = o;
+}
+
+/*!
+  \return Orientation
+  \sa setOrientation()
+*/
+Qt::Orientation QwtAbstractSlider::orientation() const
+{
+    return d_data->orientation;
+}
+
+//! Stop updating if automatic scrolling is active
+
+void QwtAbstractSlider::stopMoving()
+{
+    if ( d_data->tmrID )
+    {
+        killTimer( d_data->tmrID );
+        d_data->tmrID = 0;
+    }
+}
+
+/*!
+  \brief Specify the update interval for automatic scrolling
+  \param t update interval in milliseconds
+  \sa getScrollMode()
+*/
+void QwtAbstractSlider::setUpdateTime( int t )
+{
+    if ( t < 50 )
+        t = 50;
+    d_data->updTime = t;
+}
+
+
+/*!
+   Mouse press event handler
+   \param e Mouse event
+*/
+void QwtAbstractSlider::mousePressEvent( QMouseEvent *e )
+{
+    if ( isReadOnly() )
+    {
+        e->ignore();
+        return;
+    }
+    if ( !isValid() )
+        return;
+
+    const QPoint &p = e->pos();
+
+    d_data->timerTick = 0;
+
+    getScrollMode( p, d_data->scrollMode, d_data->direction );
+    stopMoving();
+
+    switch ( d_data->scrollMode )
+    {
+        case ScrPage:
+        case ScrTimer:
+            d_data->mouseOffset = 0;
+            d_data->tmrID = startTimer( qMax( 250, 2 * d_data->updTime ) );
+            break;
+
+        case ScrMouse:
+            d_data->time.start();
+            d_data->speed = 0;
+            d_data->mouseOffset = getValue( p ) - value();
+            Q_EMIT sliderPressed();
+            break;
+
+        default:
+            d_data->mouseOffset = 0;
+            d_data->direction = 0;
+            break;
+    }
+}
+
+
+//! Emits a valueChanged() signal if necessary
+void QwtAbstractSlider::buttonReleased()
+{
+    if ( ( !d_data->tracking ) || ( value() != prevValue() ) )
+        Q_EMIT valueChanged( value() );
+}
+
+
+/*!
+   Mouse Release Event handler
+   \param e Mouse event
+*/
+void QwtAbstractSlider::mouseReleaseEvent( QMouseEvent *e )
+{
+    if ( isReadOnly() )
+    {
+        e->ignore();
+        return;
+    }
+    if ( !isValid() )
+        return;
+
+    const double inc = step();
+
+    switch ( d_data->scrollMode )
+    {
+        case ScrMouse:
+        {
+            setPosition( e->pos() );
+            d_data->direction = 0;
+            d_data->mouseOffset = 0;
+            if ( d_data->mass > 0.0 )
+            {
+                const int ms = d_data->time.elapsed();
+                if ( ( qFabs( d_data->speed ) >  0.0 ) && ( ms < 50 ) )
+                    d_data->tmrID = startTimer( d_data->updTime );
+            }
+            else
+            {
+                d_data->scrollMode = ScrNone;
+                buttonReleased();
+            }
+            Q_EMIT sliderReleased();
+
+            break;
+        }
+
+        case ScrDirect:
+        {
+            setPosition( e->pos() );
+            d_data->direction = 0;
+            d_data->mouseOffset = 0;
+            d_data->scrollMode = ScrNone;
+            buttonReleased();
+            break;
+        }
+
+        case ScrPage:
+        {
+            stopMoving();
+            if ( !d_data->timerTick )
+                QwtDoubleRange::incPages( d_data->direction );
+            d_data->timerTick = 0;
+            buttonReleased();
+            d_data->scrollMode = ScrNone;
+            break;
+        }
+
+        case ScrTimer:
+        {
+            stopMoving();
+            if ( !d_data->timerTick )
+                QwtDoubleRange::fitValue( value() + double( d_data->direction ) * inc );
+            d_data->timerTick = 0;
+            buttonReleased();
+            d_data->scrollMode = ScrNone;
+            break;
+        }
+
+        default:
+        {
+            d_data->scrollMode = ScrNone;
+            buttonReleased();
+        }
+    }
+}
+
+
+/*!
+  Move the slider to a specified point, adjust the value
+  and emit signals if necessary.
+*/
+void QwtAbstractSlider::setPosition( const QPoint &p )
+{
+    QwtDoubleRange::fitValue( getValue( p ) - d_data->mouseOffset );
+}
+
+
+/*!
+  \brief Enables or disables tracking.
+
+  If tracking is enabled, the slider emits a
+  valueChanged() signal whenever its value
+  changes (the default behaviour). If tracking
+  is disabled, the value changed() signal will only
+  be emitted if:<ul>
+  <li>the user releases the mouse
+      button and the value has changed or
+  <li>at the end of automatic scrolling.</ul>
+  Tracking is enabled by default.
+  \param enable \c true (enable) or \c false (disable) tracking.
+*/
+void QwtAbstractSlider::setTracking( bool enable )
+{
+    d_data->tracking = enable;
+}
+
+/*!
+   Mouse Move Event handler
+   \param e Mouse event
+*/
+void QwtAbstractSlider::mouseMoveEvent( QMouseEvent *e )
+{
+    if ( isReadOnly() )
+    {
+        e->ignore();
+        return;
+    }
+
+    if ( !isValid() )
+        return;
+
+    if ( d_data->scrollMode == ScrMouse )
+    {
+        setPosition( e->pos() );
+        if ( d_data->mass > 0.0 )
+        {
+            double ms = double( d_data->time.elapsed() );
+            if ( ms < 1.0 )
+                ms = 1.0;
+            d_data->speed = ( exactValue() - exactPrevValue() ) / ms;
+            d_data->time.start();
+        }
+        if ( value() != prevValue() )
+            Q_EMIT sliderMoved( value() );
+    }
+}
+
+/*!
+   Wheel Event handler
+   \param e Whell event
+*/
+void QwtAbstractSlider::wheelEvent( QWheelEvent *e )
+{
+    if ( isReadOnly() )
+    {
+        e->ignore();
+        return;
+    }
+
+    if ( !isValid() )
+        return;
+
+    int mode = ScrNone, direction = 0;
+
+    // Give derived classes a chance to say ScrNone
+    getScrollMode( e->pos(), mode, direction );
+    if ( mode != ScrNone )
+    {
+        // Most mouse types work in steps of 15 degrees, in which case
+        // the delta value is a multiple of 120
+
+        const int inc = e->delta() / 120;
+        QwtDoubleRange::incPages( inc );
+        if ( value() != prevValue() )
+            Q_EMIT sliderMoved( value() );
+    }
+}
+
+/*!
+  Handles key events
+
+  - Key_Down, KeyLeft\n
+    Decrement by 1
+  - Key_Up, Key_Right\n
+    Increment by 1
+
+  \param e Key event
+  \sa isReadOnly()
+*/
+void QwtAbstractSlider::keyPressEvent( QKeyEvent *e )
+{
+    if ( isReadOnly() )
+    {
+        e->ignore();
+        return;
+    }
+
+    if ( !isValid() )
+        return;
+
+    int increment = 0;
+    switch ( e->key() )
+    {
+        case Qt::Key_Down:
+            if ( orientation() == Qt::Vertical )
+                increment = -1;
+            break;
+        case Qt::Key_Up:
+            if ( orientation() == Qt::Vertical )
+                increment = 1;
+            break;
+        case Qt::Key_Left:
+            if ( orientation() == Qt::Horizontal )
+                increment = -1;
+            break;
+        case Qt::Key_Right:
+            if ( orientation() == Qt::Horizontal )
+                increment = 1;
+            break;
+        default:;
+            e->ignore();
+    }
+
+    if ( increment != 0 )
+    {
+        QwtDoubleRange::incValue( increment );
+        if ( value() != prevValue() )
+            Q_EMIT sliderMoved( value() );
+    }
+}
+
+/*!
+   Qt timer event
+   \param e Timer event
+*/
+void QwtAbstractSlider::timerEvent( QTimerEvent * )
+{
+    const double inc = step();
+
+    switch ( d_data->scrollMode )
+    {
+        case ScrMouse:
+        {
+            if ( d_data->mass > 0.0 )
+            {
+                d_data->speed *= qExp( - double( d_data->updTime ) * 0.001 / d_data->mass );
+                const double newval =
+                    exactValue() + d_data->speed * double( d_data->updTime );
+                QwtDoubleRange::fitValue( newval );
+                // stop if d_data->speed < one step per second
+                if ( qFabs( d_data->speed ) < 0.001 * qFabs( step() ) )
+                {
+                    d_data->speed = 0;
+                    stopMoving();
+                    buttonReleased();
+                }
+
+            }
+            else
+                stopMoving();
+            break;
+        }
+
+        case ScrPage:
+        {
+            QwtDoubleRange::incPages( d_data->direction );
+            if ( !d_data->timerTick )
+            {
+                killTimer( d_data->tmrID );
+                d_data->tmrID = startTimer( d_data->updTime );
+            }
+            break;
+        }
+        case ScrTimer:
+        {
+            QwtDoubleRange::fitValue( value() +  double( d_data->direction ) * inc );
+            if ( !d_data->timerTick )
+            {
+                killTimer( d_data->tmrID );
+                d_data->tmrID = startTimer( d_data->updTime );
+            }
+            break;
+        }
+        default:
+        {
+            stopMoving();
+            break;
+        }
+    }
+
+    d_data->timerTick = 1;
+}
+
+
+/*!
+  Notify change of value
+
+  This function can be reimplemented by derived classes
+  in order to keep track of changes, i.e. repaint the widget.
+  The default implementation emits a valueChanged() signal
+  if tracking is enabled.
+*/
+void QwtAbstractSlider::valueChange()
+{
+    if ( d_data->tracking )
+        Q_EMIT valueChanged( value() );
+}
+
+/*!
+  \brief Set the slider's mass for flywheel effect.
+
+  If the slider's mass is greater then 0, it will continue
+  to move after the mouse button has been released. Its speed
+  decreases with time at a rate depending on the slider's mass.
+  A large mass means that it will continue to move for a
+  long time.
+
+  Derived widgets may overload this function to make it public.
+
+  \param val New mass in kg
+
+  \bug If the mass is smaller than 1g, it is set to zero.
+       The maximal mass is limited to 100kg.
+  \sa mass()
+*/
+void QwtAbstractSlider::setMass( double val )
+{
+    if ( val < 0.001 )
+        d_data->mass = 0.0;
+    else if ( val > 100.0 )
+        d_data->mass = 100.0;
+    else
+        d_data->mass = val;
+}
+
+/*!
+    \return mass
+    \sa setMass()
+*/
+double QwtAbstractSlider::mass() const
+{
+    return d_data->mass;
+}
+
+
+/*!
+  \brief Move the slider to a specified value
+
+  This function can be used to move the slider to a value
+  which is not an integer multiple of the step size.
+  \param val new value
+  \sa fitValue()
+*/
+void QwtAbstractSlider::setValue( double val )
+{
+    if ( d_data->scrollMode == ScrMouse )
+        stopMoving();
+    QwtDoubleRange::setValue( val );
+}
+
+
+/*!
+  \brief Set the slider's value to the nearest integer multiple
+         of the step size.
+
+   \param value Value
+   \sa setValue(), incValue()
+*/
+void QwtAbstractSlider::fitValue( double value )
+{
+    if ( d_data->scrollMode == ScrMouse )
+        stopMoving();
+    QwtDoubleRange::fitValue( value );
+}
+
+/*!
+  \brief Increment the value by a specified number of steps
+  \param steps number of steps
+  \sa setValue()
+*/
+void QwtAbstractSlider::incValue( int steps )
+{
+    if ( d_data->scrollMode == ScrMouse )
+        stopMoving();
+    QwtDoubleRange::incValue( steps );
+}
+
+/*!
+  \sa mouseOffset()
+*/
+void QwtAbstractSlider::setMouseOffset( double offset )
+{
+    d_data->mouseOffset = offset;
+}
+
+/*!
+  \sa setMouseOffset()
+*/
+double QwtAbstractSlider::mouseOffset() const
+{
+    return d_data->mouseOffset;
+}
+
+//! sa ScrollMode
+int QwtAbstractSlider::scrollMode() const
+{
+    return d_data->scrollMode;
+}

+ 189 - 0
starpu-top/qwt/qwt_abstract_slider.h

@@ -0,0 +1,189 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#ifndef QWT_ABSTRACT_SLIDER_H
+#define QWT_ABSTRACT_SLIDER_H
+
+#include "qwt_global.h"
+#include "qwt_double_range.h"
+#include <qwidget.h>
+
+/*!
+  \brief An abstract base class for slider widgets
+
+  QwtAbstractSlider is a base class for
+  slider widgets. It handles mouse events
+  and updates the slider's value accordingly. Derived classes
+  only have to implement the getValue() and
+  getScrollMode() members, and should react to a
+  valueChange(), which normally requires repainting.
+*/
+
+class QWT_EXPORT QwtAbstractSlider : public QWidget, public QwtDoubleRange
+{
+    Q_OBJECT
+    Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly )
+    Q_PROPERTY( bool valid READ isValid WRITE setValid )
+    Q_PROPERTY( double mass READ mass WRITE setMass )
+    Q_PROPERTY( Qt::Orientation orientation
+                READ orientation WRITE setOrientation )
+
+public:
+    /*!
+      Scroll mode
+      \sa getScrollMode()
+     */
+    enum ScrollMode
+    {
+        ScrNone,
+        ScrMouse,
+        ScrTimer,
+        ScrDirect,
+        ScrPage
+    };
+
+    explicit QwtAbstractSlider( Qt::Orientation, QWidget *parent = NULL );
+    virtual ~QwtAbstractSlider();
+
+    void setUpdateTime( int t );
+    void stopMoving();
+    void setTracking( bool enable );
+
+    virtual void setMass( double val );
+    virtual double mass() const;
+
+    virtual void setOrientation( Qt::Orientation o );
+    Qt::Orientation orientation() const;
+
+    bool isReadOnly() const;
+
+    /*
+        Wrappers for QwtDblRange::isValid/QwtDblRange::setValid made
+        to be available as Q_PROPERTY in the designer.
+    */
+
+    /*!
+      \sa QwtDblRange::isValid()
+    */
+    bool isValid() const
+    {
+        return QwtDoubleRange::isValid();
+    }
+
+    /*!
+      \param valid true/false
+      \sa QwtDblRange::isValid()
+    */
+    void setValid( bool valid )
+    {
+        QwtDoubleRange::setValid( valid );
+    }
+
+public Q_SLOTS:
+    virtual void setValue( double val );
+    virtual void fitValue( double val );
+    virtual void incValue( int steps );
+
+    virtual void setReadOnly( bool );
+
+Q_SIGNALS:
+
+    /*!
+      \brief Notify a change of value.
+
+      In the default setting
+      (tracking enabled), this signal will be emitted every
+      time the value changes ( see setTracking() ).
+      \param value new value
+    */
+    void valueChanged( double value );
+
+    /*!
+      This signal is emitted when the user presses the
+      movable part of the slider (start ScrMouse Mode).
+    */
+    void sliderPressed();
+
+    /*!
+      This signal is emitted when the user releases the
+      movable part of the slider.
+    */
+
+    void sliderReleased();
+    /*!
+      This signal is emitted when the user moves the
+      slider with the mouse.
+      \param value new value
+    */
+    void sliderMoved( double value );
+
+protected:
+    virtual void setPosition( const QPoint & );
+    virtual void valueChange();
+
+    virtual void timerEvent( QTimerEvent *e );
+    virtual void mousePressEvent( QMouseEvent *e );
+    virtual void mouseReleaseEvent( QMouseEvent *e );
+    virtual void mouseMoveEvent( QMouseEvent *e );
+    virtual void keyPressEvent( QKeyEvent *e );
+    virtual void wheelEvent( QWheelEvent *e );
+
+    /*!
+      \brief Determine the value corresponding to a specified poind
+
+      This is an abstract virtual function which is called when
+      the user presses or releases a mouse button or moves the
+      mouse. It has to be implemented by the derived class.
+      \param p point
+    */
+    virtual double getValue( const QPoint & p ) = 0;
+
+    /*!
+      \brief Determine what to do when the user presses a mouse button.
+
+      This function is abstract and has to be implemented by derived classes.
+      It is called on a mousePress event. The derived class can determine
+      what should happen next in dependence of the position where the mouse
+      was pressed by returning scrolling mode and direction. QwtAbstractSlider
+      knows the following modes:
+
+      - ScrNone\n
+        Scrolling switched off. Don't change the value.
+
+      - ScrMouse
+        Change the value while the user keeps the
+        button pressed and moves the mouse.
+
+      - ScrTimer
+        Automatic scrolling. Increment the value in the specified direction 
+        as long as the user keeps the button pressed.
+
+      - ScrPage
+        Automatic scrolling. Same as ScrTimer, but increment by page size.
+
+      \param p point where the mouse was pressed
+      \retval scrollMode The scrolling mode
+      \retval direction  direction: 1, 0, or -1.
+    */
+    virtual void getScrollMode( const QPoint &p,
+        int &scrollMode, int &direction ) = 0;
+
+    void setMouseOffset( double );
+    double mouseOffset() const;
+
+    int scrollMode() const;
+
+private:
+    void buttonReleased();
+
+    class PrivateData;
+    PrivateData *d_data;
+};
+
+#endif

+ 486 - 0
starpu-top/qwt/qwt_clipper.cpp

@@ -0,0 +1,486 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#include "qwt_clipper.h"
+#include "qwt_math.h"
+#include <qrect.h>
+
+#if QT_VERSION < 0x040601
+#define qAtan(x) ::atan(x)
+#endif
+
+static inline QRectF boundingRect( const QPolygonF &polygon )
+{
+    return polygon.boundingRect();
+}
+
+enum Edge
+{
+    Left,
+    Top,
+    Right,
+    Bottom,
+    NEdges
+};
+
+class QwtPolygonClipper: public QRect
+{
+public:
+    QwtPolygonClipper( const QRect &r );
+
+    QPolygon clipPolygon( const QPolygon & ) const;
+
+private:
+    void clipEdge( Edge, const QPolygon &, QPolygon & ) const;
+    bool insideEdge( const QPoint &, Edge edge ) const;
+    QPoint intersectEdge( const QPoint &p1,
+        const QPoint &p2, Edge edge ) const;
+
+    void addPoint( QPolygon &, uint pos, const QPoint &point ) const;
+};
+
+class QwtPolygonClipperF: public QRectF
+{
+public:
+    QwtPolygonClipperF( const QRectF &r );
+    QPolygonF clipPolygon( const QPolygonF & ) const;
+
+private:
+    void clipEdge( Edge, const QPolygonF &, QPolygonF & ) const;
+    bool insideEdge( const QPointF &, Edge edge ) const;
+    QPointF intersectEdge( const QPointF &p1,
+        const QPointF &p2, Edge edge ) const;
+
+    void addPoint( QPolygonF &, uint pos, const QPointF &point ) const;
+};
+
+class QwtCircleClipper: public QRectF
+{
+public:
+    QwtCircleClipper( const QRectF &r );
+    QVector<QwtInterval> clipCircle( const QPointF &, double radius ) const;
+
+private:
+    QList<QPointF> cuttingPoints(
+        Edge, const QPointF &pos, double radius ) const;
+    double toAngle( const QPointF &, const QPointF & ) const;
+};
+
+QwtPolygonClipper::QwtPolygonClipper( const QRect &r ):
+    QRect( r )
+{
+}
+
+inline void QwtPolygonClipper::addPoint(
+    QPolygon &pa, uint pos, const QPoint &point ) const
+{
+    if ( uint( pa.size() ) <= pos )
+        pa.resize( pos + 5 );
+
+    pa.setPoint( pos, point );
+}
+
+//! Sutherland-Hodgman polygon clipping
+QPolygon QwtPolygonClipper::clipPolygon( const QPolygon &pa ) const
+{
+    if ( contains( pa.boundingRect() ) )
+        return pa;
+
+    QPolygon cpa( pa.size() );
+
+    clipEdge( ( Edge )0, pa, cpa );
+
+    for ( uint edge = 1; edge < NEdges; edge++ )
+    {
+        const QPolygon rpa = cpa;
+        clipEdge( ( Edge )edge, rpa, cpa );
+    }
+
+    return cpa;
+}
+
+bool QwtPolygonClipper::insideEdge( const QPoint &p, Edge edge ) const
+{
+    switch ( edge )
+    {
+        case Left:
+            return p.x() > left();
+        case Top:
+            return p.y() > top();
+        case Right:
+            return p.x() < right();
+        case Bottom:
+            return p.y() < bottom();
+        default:
+            break;
+    }
+
+    return false;
+}
+
+QPoint QwtPolygonClipper::intersectEdge( const QPoint &p1,
+        const QPoint &p2, Edge edge ) const
+{
+    int x = 0, y = 0;
+    double m = 0;
+
+    const double dy = p2.y() - p1.y();
+    const double dx = p2.x() - p1.x();
+
+    switch ( edge )
+    {
+        case Left:
+            x = left();
+            m = double( qAbs( p1.x() - x ) ) / qAbs( dx );
+            y = p1.y() + int( dy * m );
+            break;
+        case Top:
+            y = top();
+            m = double( qAbs( p1.y() - y ) ) / qAbs( dy );
+            x = p1.x() + int( dx * m );
+            break;
+        case Right:
+            x = right();
+            m = double( qAbs( p1.x() - x ) ) / qAbs( dx );
+            y = p1.y() + int( dy * m );
+            break;
+        case Bottom:
+            y = bottom();
+            m = double( qAbs( p1.y() - y ) ) / qAbs( dy );
+            x = p1.x() + int( dx * m );
+            break;
+        default:
+            break;
+    }
+
+    return QPoint( x, y );
+}
+
+void QwtPolygonClipper::clipEdge( Edge edge,
+    const QPolygon &pa, QPolygon &cpa ) const
+{
+    if ( pa.count() == 0 )
+    {
+        cpa.resize( 0 );
+        return;
+    }
+
+    unsigned int count = 0;
+
+    QPoint p1 = pa.point( 0 );
+    if ( insideEdge( p1, edge ) )
+        addPoint( cpa, count++, p1 );
+
+    const uint nPoints = pa.size();
+    for ( uint i = 1; i < nPoints; i++ )
+    {
+        const QPoint p2 = pa.point( i );
+        if ( insideEdge( p2, edge ) )
+        {
+            if ( insideEdge( p1, edge ) )
+                addPoint( cpa, count++, p2 );
+            else
+            {
+                addPoint( cpa, count++, intersectEdge( p1, p2, edge ) );
+                addPoint( cpa, count++, p2 );
+            }
+        }
+        else
+        {
+            if ( insideEdge( p1, edge ) )
+                addPoint( cpa, count++, intersectEdge( p1, p2, edge ) );
+        }
+        p1 = p2;
+    }
+    cpa.resize( count );
+}
+
+QwtPolygonClipperF::QwtPolygonClipperF( const QRectF &r ):
+    QRectF( r )
+{
+}
+
+inline void QwtPolygonClipperF::addPoint( QPolygonF &pa, uint pos, const QPointF &point ) const
+{
+    if ( uint( pa.size() ) <= pos )
+        pa.resize( pos + 5 );
+
+    pa[( int )pos] = point;
+}
+
+//! Sutherland-Hodgman polygon clipping
+QPolygonF QwtPolygonClipperF::clipPolygon( const QPolygonF &pa ) const
+{
+    if ( contains( ::boundingRect( pa ) ) )
+        return pa;
+
+    QPolygonF cpa( pa.size() );
+
+    clipEdge( ( Edge )0, pa, cpa );
+
+    for ( uint edge = 1; edge < NEdges; edge++ )
+    {
+        const QPolygonF rpa = cpa;
+        clipEdge( ( Edge )edge, rpa, cpa );
+    }
+
+    return cpa;
+}
+
+bool QwtPolygonClipperF::insideEdge( const QPointF &p, Edge edge ) const
+{
+    switch ( edge )
+    {
+        case Left:
+            return p.x() > left();
+        case Top:
+            return p.y() > top();
+        case Right:
+            return p.x() < right();
+        case Bottom:
+            return p.y() < bottom();
+        default:
+            break;
+    }
+
+    return false;
+}
+
+QPointF QwtPolygonClipperF::intersectEdge( const QPointF &p1,
+    const QPointF &p2, Edge edge ) const
+{
+    double x = 0.0, y = 0.0;
+    double m = 0;
+
+    const double dy = p2.y() - p1.y();
+    const double dx = p2.x() - p1.x();
+
+    switch ( edge )
+    {
+        case Left:
+            x = left();
+            m = double( qAbs( p1.x() - x ) ) / qAbs( dx );
+            y = p1.y() + int( dy * m );
+            break;
+        case Top:
+            y = top();
+            m = double( qAbs( p1.y() - y ) ) / qAbs( dy );
+            x = p1.x() + int( dx * m );
+            break;
+        case Right:
+            x = right();
+            m = double( qAbs( p1.x() - x ) ) / qAbs( dx );
+            y = p1.y() + int( dy * m );
+            break;
+        case Bottom:
+            y = bottom();
+            m = double( qAbs( p1.y() - y ) ) / qAbs( dy );
+            x = p1.x() + int( dx * m );
+            break;
+        default:
+            break;
+    }
+
+    return QPointF( x, y );
+}
+
+void QwtPolygonClipperF::clipEdge( Edge edge,
+    const QPolygonF &pa, QPolygonF &cpa ) const
+{
+    if ( pa.count() == 0 )
+    {
+        cpa.resize( 0 );
+        return;
+    }
+
+    unsigned int count = 0;
+
+    QPointF p1 = pa[0];
+    if ( insideEdge( p1, edge ) )
+        addPoint( cpa, count++, p1 );
+
+    const uint nPoints = pa.size();
+    for ( uint i = 1; i < nPoints; i++ )
+    {
+        const QPointF p2 = pa[( int )i];
+        if ( insideEdge( p2, edge ) )
+        {
+            if ( insideEdge( p1, edge ) )
+                addPoint( cpa, count++, p2 );
+            else
+            {
+                addPoint( cpa, count++, intersectEdge( p1, p2, edge ) );
+                addPoint( cpa, count++, p2 );
+            }
+        }
+        else
+        {
+            if ( insideEdge( p1, edge ) )
+                addPoint( cpa, count++, intersectEdge( p1, p2, edge ) );
+        }
+        p1 = p2;
+    }
+    cpa.resize( count );
+}
+
+QwtCircleClipper::QwtCircleClipper( const QRectF &r ):
+    QRectF( r )
+{
+}
+
+QVector<QwtInterval> QwtCircleClipper::clipCircle(
+    const QPointF &pos, double radius ) const
+{
+    QList<QPointF> points;
+    for ( int edge = 0; edge < NEdges; edge++ )
+        points += cuttingPoints( ( Edge )edge, pos, radius );
+
+    QVector<QwtInterval> intv;
+    if ( points.size() <= 0 )
+    {
+        QRectF cRect( 0, 0, 2 * radius, 2* radius );
+        cRect.moveCenter( pos );
+        if ( contains( cRect ) )
+            intv += QwtInterval( 0.0, 2 * M_PI );
+    }
+    else
+    {
+        QList<double> angles;
+        for ( int i = 0; i < points.size(); i++ )
+            angles += toAngle( pos, points[i] );
+        qSort( angles );
+
+        const int in = contains( qwtPolar2Pos( pos, radius,
+                                               angles[0] + ( angles[1] - angles[0] ) / 2 ) );
+        if ( in )
+        {
+            for ( int i = 0; i < angles.size() - 1; i += 2 )
+                intv += QwtInterval( angles[i], angles[i+1] );
+        }
+        else
+        {
+            for ( int i = 1; i < angles.size() - 1; i += 2 )
+                intv += QwtInterval( angles[i], angles[i+1] );
+            intv += QwtInterval( angles.last(), angles.first() );
+        }
+    }
+
+    return intv;
+}
+
+double QwtCircleClipper::toAngle(
+    const QPointF &from, const QPointF &to ) const
+{
+    if ( from.x() == to.x() )
+        return from.y() <= to.y() ? M_PI / 2.0 : 3 * M_PI / 2.0;
+
+    const double m = qAbs( ( to.y() - from.y() ) / ( to.x() - from.x() ) );
+
+    double angle = qAtan( m );
+    if ( to.x() > from.x() )
+    {
+        if ( to.y() > from.y() )
+            angle = 2 * M_PI - angle;
+    }
+    else
+    {
+        if ( to.y() > from.y() )
+            angle = M_PI + angle;
+        else
+            angle = M_PI - angle;
+    }
+
+    return angle;
+}
+
+QList<QPointF> QwtCircleClipper::cuttingPoints(
+    Edge edge, const QPointF &pos, double radius ) const
+{
+    QList<QPointF> points;
+
+    if ( edge == Left || edge == Right )
+    {
+        const double x = ( edge == Left ) ? left() : right();
+        if ( qAbs( pos.x() - x ) < radius )
+        {
+            const double off = qSqrt( qwtSqr( radius ) - qwtSqr( pos.x() - x ) );
+            const double y1 = pos.y() + off;
+            if ( y1 >= top() && y1 <= bottom() )
+                points += QPointF( x, y1 );
+            const double y2 = pos.y() - off;
+            if ( y2 >= top() && y2 <= bottom() )
+                points += QPointF( x, y2 );
+        }
+    }
+    else
+    {
+        const double y = ( edge == Top ) ? top() : bottom();
+        if ( qAbs( pos.y() - y ) < radius )
+        {
+            const double off = qSqrt( qwtSqr( radius ) - qwtSqr( pos.y() - y ) );
+            const double x1 = pos.x() + off;
+            if ( x1 >= left() && x1 <= right() )
+                points += QPointF( x1, y );
+            const double x2 = pos.x() - off;
+            if ( x2 >= left() && x2 <= right() )
+                points += QPointF( x2, y );
+        }
+    }
+    return points;
+}
+
+/*!
+   Sutherland-Hodgman polygon clipping
+
+   \param clipRect Clip rectangle
+   \param polygon Polygon
+
+   \return Clipped polygon
+*/
+QPolygon QwtClipper::clipPolygon(
+    const QRect &clipRect, const QPolygon &polygon )
+{
+    QwtPolygonClipper clipper( clipRect );
+    return clipper.clipPolygon( polygon );
+}
+
+/*!
+   Sutherland-Hodgman polygon clipping
+
+   \param clipRect Clip rectangle
+   \param polygon Polygon
+
+   \return Clipped polygon
+*/
+QPolygonF QwtClipper::clipPolygonF(
+    const QRectF &clipRect, const QPolygonF &polygon )
+{
+    QwtPolygonClipperF clipper( clipRect );
+    return clipper.clipPolygon( polygon );
+}
+
+/*!
+   Circle clipping
+
+   clipCircle() devides a circle into intervals of angles representing arcs
+   of the circle. When the circle is completely inside the clip rectangle
+   an interval [0.0, 2 * M_PI] is returned.
+
+   \param clipRect Clip rectangle
+   \param center Center of the circle
+   \param radius Radius of the circle
+
+   \return Arcs of the circle
+*/
+QVector<QwtInterval> QwtClipper::clipCircle( const QRectF &clipRect,
+    const QPointF &center, double radius )
+{
+    QwtCircleClipper clipper( clipRect );
+    return clipper.clipCircle( center, radius );
+}

+ 35 - 0
starpu-top/qwt/qwt_clipper.h

@@ -0,0 +1,35 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#ifndef QWT_CLIPPER_H
+#define QWT_CLIPPER_H
+
+#include "qwt_global.h"
+#include "qwt_interval.h"
+#include <qpolygon.h>
+#include <qvector.h>
+
+class QRect;
+class QRectF;
+
+/*!
+  \brief Some clipping algos
+*/
+
+class QWT_EXPORT QwtClipper
+{
+public:
+    static QPolygon clipPolygon( const QRect &, const QPolygon & );
+    static QPolygonF clipPolygonF( const QRectF &, const QPolygonF & );
+
+    static QVector<QwtInterval> clipCircle(
+        const QRectF &, const QPointF &, double radius );
+};
+
+#endif

+ 442 - 0
starpu-top/qwt/qwt_color_map.cpp

@@ -0,0 +1,442 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#include "qwt_color_map.h"
+#include "qwt_math.h"
+#include "qwt_interval.h"
+#include <qnumeric.h>
+
+typedef QVector<QRgb> QwtColorTable;
+
+class QwtLinearColorMap::ColorStops
+{
+public:
+    ColorStops()
+    {
+        _stops.reserve( 256 );
+    }
+
+    void insert( double pos, const QColor &color );
+    QRgb rgb( QwtLinearColorMap::Mode, double pos ) const;
+
+    QVector<double> stops() const;
+
+private:
+
+    class ColorStop
+    {
+    public:
+        ColorStop():
+            pos( 0.0 ),
+            rgb( 0 )
+        {
+        };
+
+        ColorStop( double p, const QColor &c ):
+            pos( p ),
+            rgb( c.rgb() )
+        {
+            r = qRed( rgb );
+            g = qGreen( rgb );
+            b = qBlue( rgb );
+        }
+
+        double pos;
+        QRgb rgb;
+        int r, g, b;
+    };
+
+    inline int findUpper( double pos ) const;
+    QVector<ColorStop> _stops;
+};
+
+void QwtLinearColorMap::ColorStops::insert( double pos, const QColor &color )
+{
+    // Lookups need to be very fast, insertions are not so important.
+    // Anyway, a balanced tree is what we need here. TODO ...
+
+    if ( pos < 0.0 || pos > 1.0 )
+        return;
+
+    int index;
+    if ( _stops.size() == 0 )
+    {
+        index = 0;
+        _stops.resize( 1 );
+    }
+    else
+    {
+        index = findUpper( pos );
+        if ( index == ( int )_stops.size() ||
+                qAbs( _stops[index].pos - pos ) >= 0.001 )
+        {
+            _stops.resize( _stops.size() + 1 );
+            for ( int i = _stops.size() - 1; i > index; i-- )
+                _stops[i] = _stops[i-1];
+        }
+    }
+
+    _stops[index] = ColorStop( pos, color );
+}
+
+inline QVector<double> QwtLinearColorMap::ColorStops::stops() const
+{
+    QVector<double> positions( _stops.size() );
+    for ( int i = 0; i < ( int )_stops.size(); i++ )
+        positions[i] = _stops[i].pos;
+    return positions;
+}
+
+inline int QwtLinearColorMap::ColorStops::findUpper( double pos ) const
+{
+    int index = 0;
+    int n = _stops.size();
+
+    const ColorStop *stops = _stops.data();
+
+    while ( n > 0 )
+    {
+        const int half = n >> 1;
+        const int middle = index + half;
+
+        if ( stops[middle].pos <= pos )
+        {
+            index = middle + 1;
+            n -= half + 1;
+        }
+        else
+            n = half;
+    }
+
+    return index;
+}
+
+inline QRgb QwtLinearColorMap::ColorStops::rgb(
+    QwtLinearColorMap::Mode mode, double pos ) const
+{
+    if ( pos <= 0.0 )
+        return _stops[0].rgb;
+    if ( pos >= 1.0 )
+        return _stops[( int )( _stops.size() - 1 )].rgb;
+
+    const int index = findUpper( pos );
+    if ( mode == FixedColors )
+    {
+        return _stops[index-1].rgb;
+    }
+    else
+    {
+        const ColorStop &s1 = _stops[index-1];
+        const ColorStop &s2 = _stops[index];
+
+        const double ratio = ( pos - s1.pos ) / ( s2.pos - s1.pos );
+
+        const int r = s1.r + qRound( ratio * ( s2.r - s1.r ) );
+        const int g = s1.g + qRound( ratio * ( s2.g - s1.g ) );
+        const int b = s1.b + qRound( ratio * ( s2.b - s1.b ) );
+
+        return qRgb( r, g, b );
+    }
+}
+
+//! Constructor
+QwtColorMap::QwtColorMap( Format format ):
+    d_format( format )
+{
+}
+
+//! Destructor
+QwtColorMap::~QwtColorMap()
+{
+}
+
+/*!
+   Build and return a color map of 256 colors
+
+   The color table is needed for rendering indexed images in combination
+   with using colorIndex().
+
+   \param interval Range for the values
+   \return A color table, that can be used for a QImage
+*/
+QwtColorTable QwtColorMap::colorTable( const QwtInterval &interval ) const
+{
+    QwtColorTable table( 256 );
+
+    if ( interval.isValid() )
+    {
+        const double step = interval.width() / ( table.size() - 1 );
+        for ( int i = 0; i < ( int ) table.size(); i++ )
+            table[i] = rgb( interval, interval.minValue() + step * i );
+    }
+
+    return table;
+}
+
+class QwtLinearColorMap::PrivateData
+{
+public:
+    ColorStops colorStops;
+    QwtLinearColorMap::Mode mode;
+};
+
+/*!
+   Build a color map with two stops at 0.0 and 1.0. The color
+   at 0.0 is Qt::blue, at 1.0 it is Qt::yellow.
+
+   \param format Preferred format of the color map
+*/
+QwtLinearColorMap::QwtLinearColorMap( QwtColorMap::Format format ):
+    QwtColorMap( format )
+{
+    d_data = new PrivateData;
+    d_data->mode = ScaledColors;
+
+    setColorInterval( Qt::blue, Qt::yellow );
+}
+
+/*!
+   Build a color map with two stops at 0.0 and 1.0.
+
+   \param color1 Color used for the minimum value of the value interval
+   \param color2 Color used for the maximum value of the value interval
+   \param format Preferred format of the coor map
+*/
+QwtLinearColorMap::QwtLinearColorMap( const QColor &color1,
+        const QColor &color2, QwtColorMap::Format format ):
+    QwtColorMap( format )
+{
+    d_data = new PrivateData;
+    d_data->mode = ScaledColors;
+    setColorInterval( color1, color2 );
+}
+
+//! Destructor
+QwtLinearColorMap::~QwtLinearColorMap()
+{
+    delete d_data;
+}
+
+/*!
+   \brief Set the mode of the color map
+
+   FixedColors means the color is calculated from the next lower
+   color stop. ScaledColors means the color is calculated
+   by interpolating the colors of the adjacent stops.
+
+   \sa mode()
+*/
+void QwtLinearColorMap::setMode( Mode mode )
+{
+    d_data->mode = mode;
+}
+
+/*!
+   \return Mode of the color map
+   \sa setMode()
+*/
+QwtLinearColorMap::Mode QwtLinearColorMap::mode() const
+{
+    return d_data->mode;
+}
+
+/*!
+   Set the color range
+
+   Add stops at 0.0 and 1.0.
+
+   \param color1 Color used for the minimum value of the value interval
+   \param color2 Color used for the maximum value of the value interval
+
+   \sa color1(), color2()
+*/
+void QwtLinearColorMap::setColorInterval(
+    const QColor &color1, const QColor &color2 )
+{
+    d_data->colorStops = ColorStops();
+    d_data->colorStops.insert( 0.0, color1 );
+    d_data->colorStops.insert( 1.0, color2 );
+}
+
+/*!
+   Add a color stop
+
+   The value has to be in the range [0.0, 1.0].
+   F.e. a stop at position 17.0 for a range [10.0,20.0] must be
+   passed as: (17.0 - 10.0) / (20.0 - 10.0)
+
+   \param value Value between [0.0, 1.0]
+   \param color Color stop
+*/
+void QwtLinearColorMap::addColorStop( double value, const QColor& color )
+{
+    if ( value >= 0.0 && value <= 1.0 )
+        d_data->colorStops.insert( value, color );
+}
+
+/*!
+   Return all positions of color stops in increasing order
+*/
+QVector<double> QwtLinearColorMap::colorStops() const
+{
+    return d_data->colorStops.stops();
+}
+
+/*!
+  \return the first color of the color range
+  \sa setColorInterval()
+*/
+QColor QwtLinearColorMap::color1() const
+{
+    return QColor( d_data->colorStops.rgb( d_data->mode, 0.0 ) );
+}
+
+/*!
+  \return the second color of the color range
+  \sa setColorInterval()
+*/
+QColor QwtLinearColorMap::color2() const
+{
+    return QColor( d_data->colorStops.rgb( d_data->mode, 1.0 ) );
+}
+
+/*!
+  Map a value of a given interval into a rgb value
+
+  \param interval Range for all values
+  \param value Value to map into a rgb value
+*/
+QRgb QwtLinearColorMap::rgb(
+    const QwtInterval &interval, double value ) const
+{
+    if ( qIsNaN(value) )
+        return qRgba(0, 0, 0, 0);
+
+    const double width = interval.width();
+
+    double ratio = 0.0;
+    if ( width > 0.0 )
+        ratio = ( value - interval.minValue() ) / width;
+
+    return d_data->colorStops.rgb( d_data->mode, ratio );
+}
+
+/*!
+  Map a value of a given interval into a color index, between 0 and 255
+
+  \param interval Range for all values
+  \param value Value to map into a color index
+*/
+unsigned char QwtLinearColorMap::colorIndex(
+    const QwtInterval &interval, double value ) const
+{
+    const double width = interval.width();
+
+    if ( qIsNaN(value) || width <= 0.0 || value <= interval.minValue() )
+        return 0;
+
+    if ( value >= interval.maxValue() )
+        return ( unsigned char )255;
+
+    const double ratio = ( value - interval.minValue() ) / width;
+
+    unsigned char index;
+    if ( d_data->mode == FixedColors )
+        index = ( unsigned char )( ratio * 255 ); // always floor
+    else
+        index = ( unsigned char )qRound( ratio * 255 );
+
+    return index;
+}
+
+class QwtAlphaColorMap::PrivateData
+{
+public:
+    QColor color;
+    QRgb rgb;
+};
+
+
+/*!
+   Constructor
+   \param color Color of the map
+*/
+QwtAlphaColorMap::QwtAlphaColorMap( const QColor &color ):
+    QwtColorMap( QwtColorMap::RGB )
+{
+    d_data = new PrivateData;
+    d_data->color = color;
+    d_data->rgb = color.rgb() & qRgba( 255, 255, 255, 0 );
+}
+
+//! Destructor
+QwtAlphaColorMap::~QwtAlphaColorMap()
+{
+    delete d_data;
+}
+
+/*!
+   Set the color
+
+   \param color Color
+   \sa color()
+*/
+void QwtAlphaColorMap::setColor( const QColor &color )
+{
+    d_data->color = color;
+    d_data->rgb = color.rgb();
+}
+
+/*!
+  \return the color
+  \sa setColor()
+*/
+QColor QwtAlphaColorMap::color() const
+{
+    return d_data->color;
+}
+
+/*!
+  \brief Map a value of a given interval into a alpha value
+
+  alpha := (value - interval.minValue()) / interval.width();
+
+  \param interval Range for all values
+  \param value Value to map into a rgb value
+  \return rgb value, with an alpha value
+*/
+QRgb QwtAlphaColorMap::rgb( const QwtInterval &interval, double value ) const
+{
+    const double width = interval.width();
+    if ( !qIsNaN(value) && width >= 0.0 )
+    {
+        const double ratio = ( value - interval.minValue() ) / width;
+        int alpha = qRound( 255 * ratio );
+        if ( alpha < 0 )
+            alpha = 0;
+        if ( alpha > 255 )
+            alpha = 255;
+
+        return d_data->rgb | ( alpha << 24 );
+    }
+    return d_data->rgb;
+}
+
+/*!
+  Dummy function, needed to be implemented as it is pure virtual
+  in QwtColorMap. Color indices make no sense in combination with
+  an alpha channel.
+
+  \return Always 0
+*/
+unsigned char QwtAlphaColorMap::colorIndex(
+    const QwtInterval &, double ) const
+{
+    return 0;
+}

+ 197 - 0
starpu-top/qwt/qwt_color_map.h

@@ -0,0 +1,197 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#ifndef QWT_COLOR_MAP_H
+#define QWT_COLOR_MAP_H
+
+#include "qwt_global.h"
+#include "qwt_interval.h"
+#include <qcolor.h>
+#include <qvector.h>
+
+/*!
+  \brief QwtColorMap is used to map values into colors.
+
+  For displaying 3D data on a 2D plane the 3rd dimension is often
+  displayed using colors, like f.e in a spectrogram.
+
+  Each color map is optimized to return colors for only one of the
+  following image formats:
+
+  - QImage::Format_Indexed8\n
+  - QImage::Format_ARGB32\n
+
+  \sa QwtPlotSpectrogram, QwtScaleWidget
+*/
+
+class QWT_EXPORT QwtColorMap
+{
+public:
+    /*!
+        - RGB\n
+        The map is intended to map into QRgb values.
+        - Indexed\n
+        The map is intended to map into 8 bit values, that
+        are indices into the color table.
+
+        \sa rgb(), colorIndex(), colorTable()
+    */
+
+    enum Format
+    {
+        RGB,
+        Indexed
+    };
+
+    QwtColorMap( Format = QwtColorMap::RGB );
+    virtual ~QwtColorMap();
+
+    Format format() const;
+
+    /*!
+       Map a value of a given interval into a rgb value.
+       \param interval Range for the values
+       \param value Value
+       \return rgb value, corresponding to value
+    */
+    virtual QRgb rgb( const QwtInterval &interval,
+        double value ) const = 0;
+
+    /*!
+       Map a value of a given interval into a color index
+       \param interval Range for the values
+       \param value Value
+       \return color index, corresponding to value
+     */
+    virtual unsigned char colorIndex(
+        const QwtInterval &interval, double value ) const = 0;
+
+    QColor color( const QwtInterval &, double value ) const;
+    virtual QVector<QRgb> colorTable( const QwtInterval & ) const;
+
+private:
+    Format d_format;
+};
+
+/*!
+  \brief QwtLinearColorMap builds a color map from color stops.
+
+  A color stop is a color at a specific position. The valid
+  range for the positions is [0.0, 1.0]. When mapping a value
+  into a color it is translated into this interval. If
+  mode() == FixedColors the color is calculated from the next lower
+  color stop. If mode() == ScaledColors the color is calculated
+  by interpolating the colors of the adjacent stops.
+*/
+class QWT_EXPORT QwtLinearColorMap: public QwtColorMap
+{
+public:
+    /*!
+       Mode of color map
+       \sa setMode(), mode()
+    */
+    enum Mode
+    {
+        FixedColors,
+        ScaledColors
+    };
+
+    QwtLinearColorMap( QwtColorMap::Format = QwtColorMap::RGB );
+    QwtLinearColorMap( const QColor &from, const QColor &to,
+        QwtColorMap::Format = QwtColorMap::RGB );
+
+    virtual ~QwtLinearColorMap();
+
+    void setMode( Mode );
+    Mode mode() const;
+
+    void setColorInterval( const QColor &color1, const QColor &color2 );
+    void addColorStop( double value, const QColor& );
+    QVector<double> colorStops() const;
+
+    QColor color1() const;
+    QColor color2() const;
+
+    virtual QRgb rgb( const QwtInterval &, double value ) const;
+    virtual unsigned char colorIndex(
+        const QwtInterval &, double value ) const;
+
+    class ColorStops;
+
+private:
+    // Disabled copy constructor and operator=
+    QwtLinearColorMap( const QwtLinearColorMap & );
+    QwtLinearColorMap &operator=( const QwtLinearColorMap & );
+
+    class PrivateData;
+    PrivateData *d_data;
+};
+
+/*!
+  \brief QwtAlphaColorMap variies the alpha value of a color
+*/
+class QWT_EXPORT QwtAlphaColorMap: public QwtColorMap
+{
+public:
+    QwtAlphaColorMap( const QColor & = QColor( Qt::gray ) );
+    virtual ~QwtAlphaColorMap();
+
+    void setColor( const QColor & );
+    QColor color() const;
+
+    virtual QRgb rgb( const QwtInterval &, double value ) const;
+
+private:
+    QwtAlphaColorMap( const QwtAlphaColorMap & );
+    QwtAlphaColorMap &operator=( const QwtAlphaColorMap & );
+
+    virtual unsigned char colorIndex(
+        const QwtInterval &, double value ) const;
+
+    class PrivateData;
+    PrivateData *d_data;
+};
+
+
+/*!
+   Map a value into a color
+
+   \param interval Valid interval for values
+   \param value Value
+
+   \return Color corresponding to value
+
+   \warning This method is slow for Indexed color maps. If it is
+            necessary to map many values, its better to get the
+            color table once and find the color using colorIndex().
+*/
+inline QColor QwtColorMap::color(
+    const QwtInterval &interval, double value ) const
+{
+    if ( d_format == RGB )
+    {
+        return QColor( rgb( interval, value ) );
+    }
+    else
+    {
+        const unsigned int index = colorIndex( interval, value );
+        return colorTable( interval )[index]; // slow
+    }
+}
+
+/*!
+   \return Intended format of the color map
+   \sa Format
+*/
+inline QwtColorMap::Format QwtColorMap::format() const
+{
+    return d_format;
+}
+
+#endif

+ 405 - 0
starpu-top/qwt/qwt_curve_fitter.cpp

@@ -0,0 +1,405 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#include "qwt_curve_fitter.h"
+#include "qwt_math.h"
+#include "qwt_spline.h"
+#include <qstack.h>
+#include <qvector.h>
+
+#if QT_VERSION < 0x040601
+#define qFabs(x) ::fabs(x)
+#endif
+
+//! Constructor
+QwtCurveFitter::QwtCurveFitter()
+{
+}
+
+//! Destructor
+QwtCurveFitter::~QwtCurveFitter()
+{
+}
+
+class QwtSplineCurveFitter::PrivateData
+{
+public:
+    PrivateData():
+        fitMode( QwtSplineCurveFitter::Auto ),
+        splineSize( 250 )
+    {
+    }
+
+    QwtSpline spline;
+    QwtSplineCurveFitter::FitMode fitMode;
+    int splineSize;
+};
+
+//! Constructor
+QwtSplineCurveFitter::QwtSplineCurveFitter()
+{
+    d_data = new PrivateData;
+}
+
+//! Destructor
+QwtSplineCurveFitter::~QwtSplineCurveFitter()
+{
+    delete d_data;
+}
+
+/*!
+  Select the algorithm used for building the spline
+
+  \param mode Mode representing a spline algorithm
+  \sa fitMode()
+*/
+void QwtSplineCurveFitter::setFitMode( FitMode mode )
+{
+    d_data->fitMode = mode;
+}
+
+/*!
+  \return Mode representing a spline algorithm
+  \sa setFitMode()
+*/
+QwtSplineCurveFitter::FitMode QwtSplineCurveFitter::fitMode() const
+{
+    return d_data->fitMode;
+}
+
+/*!
+  Assign a spline
+
+  \param spline Spline
+  \sa spline()
+*/
+void QwtSplineCurveFitter::setSpline( const QwtSpline &spline )
+{
+    d_data->spline = spline;
+    d_data->spline.reset();
+}
+
+/*!
+  \return Spline
+  \sa setSpline()
+*/
+const QwtSpline &QwtSplineCurveFitter::spline() const
+{
+    return d_data->spline;
+}
+
+/*!
+  \return Spline
+  \sa setSpline()
+*/
+QwtSpline &QwtSplineCurveFitter::spline()
+{
+    return d_data->spline;
+}
+
+/*!
+   Assign a spline size ( has to be at least 10 points )
+
+   \param splineSize Spline size
+   \sa splineSize()
+*/
+void QwtSplineCurveFitter::setSplineSize( int splineSize )
+{
+    d_data->splineSize = qMax( splineSize, 10 );
+}
+
+/*!
+  \return Spline size
+  \sa setSplineSize()
+*/
+int QwtSplineCurveFitter::splineSize() const
+{
+    return d_data->splineSize;
+}
+
+/*!
+  Find a curve which has the best fit to a series of data points
+
+  \param points Series of data points
+  \return Curve points
+*/
+QPolygonF QwtSplineCurveFitter::fitCurve( const QPolygonF &points ) const
+{
+    const int size = ( int )points.size();
+    if ( size <= 2 )
+        return points;
+
+    FitMode fitMode = d_data->fitMode;
+    if ( fitMode == Auto )
+    {
+        fitMode = Spline;
+
+        const QPointF *p = points.data();
+        for ( int i = 1; i < size; i++ )
+        {
+            if ( p[i].x() <= p[i-1].x() )
+            {
+                fitMode = ParametricSpline;
+                break;
+            }
+        };
+    }
+
+    if ( fitMode == ParametricSpline )
+        return fitParametric( points );
+    else
+        return fitSpline( points );
+}
+
+QPolygonF QwtSplineCurveFitter::fitSpline( const QPolygonF &points ) const
+{
+    d_data->spline.setPoints( points );
+    if ( !d_data->spline.isValid() )
+        return points;
+
+    QPolygonF fittedPoints( d_data->splineSize );
+
+    const double x1 = points[0].x();
+    const double x2 = points[int( points.size() - 1 )].x();
+    const double dx = x2 - x1;
+    const double delta = dx / ( d_data->splineSize - 1 );
+
+    for ( int i = 0; i < d_data->splineSize; i++ )
+    {
+        QPointF &p = fittedPoints[i];
+
+        const double v = x1 + i * delta;
+        const double sv = d_data->spline.value( v );
+
+        p.setX( qRound( v ) );
+        p.setY( qRound( sv ) );
+    }
+    d_data->spline.reset();
+
+    return fittedPoints;
+}
+
+QPolygonF QwtSplineCurveFitter::fitParametric( const QPolygonF &points ) const
+{
+    int i;
+    const int size = points.size();
+
+    QPolygonF fittedPoints( d_data->splineSize );
+    QPolygonF splinePointsX( size );
+    QPolygonF splinePointsY( size );
+
+    const QPointF *p = points.data();
+    QPointF *spX = splinePointsX.data();
+    QPointF *spY = splinePointsY.data();
+
+    double param = 0.0;
+    for ( i = 0; i < size; i++ )
+    {
+        const double x = p[i].x();
+        const double y = p[i].y();
+        if ( i > 0 )
+        {
+            const double delta = qSqrt( qwtSqr( x - spX[i-1].y() )
+                      + qwtSqr( y - spY[i-1].y() ) );
+            param += qMax( delta, 1.0 );
+        }
+        spX[i].setX( param );
+        spX[i].setY( x );
+        spY[i].setX( param );
+        spY[i].setY( y );
+    }
+
+    d_data->spline.setPoints( splinePointsX );
+    if ( !d_data->spline.isValid() )
+        return points;
+
+    const double deltaX =
+        splinePointsX[size - 1].x() / ( d_data->splineSize - 1 );
+    for ( i = 0; i < d_data->splineSize; i++ )
+    {
+        const double dtmp = i * deltaX;
+        fittedPoints[i].setX( qRound( d_data->spline.value( dtmp ) ) );
+    }
+
+    d_data->spline.setPoints( splinePointsY );
+    if ( !d_data->spline.isValid() )
+        return points;
+
+    const double deltaY =
+        splinePointsY[size - 1].x() / ( d_data->splineSize - 1 );
+    for ( i = 0; i < d_data->splineSize; i++ )
+    {
+        const double dtmp = i * deltaY;
+        fittedPoints[i].setY( qRound( d_data->spline.value( dtmp ) ) );
+    }
+
+    return fittedPoints;
+}
+
+class QwtWeedingCurveFitter::PrivateData
+{
+public:
+    PrivateData():
+        tolerance( 1.0 )
+    {
+    }
+
+    double tolerance;
+};
+
+class QwtWeedingCurveFitter::Line
+{
+public:
+    Line( int i1 = 0, int i2 = 0 ):
+        from( i1 ),
+        to( i2 )
+    {
+    }
+
+    int from;
+    int to;
+};
+
+/*!
+   Constructor
+
+   \param tolerance Tolerance
+   \sa setTolerance(), tolerance()
+*/
+QwtWeedingCurveFitter::QwtWeedingCurveFitter( double tolerance )
+{
+    d_data = new PrivateData;
+    setTolerance( tolerance );
+}
+
+//! Destructor
+QwtWeedingCurveFitter::~QwtWeedingCurveFitter()
+{
+    delete d_data;
+}
+
+/*!
+ Assign the tolerance
+
+ The tolerance is the maximum distance, that is accaptable
+ between the original curve and the smoothed curve.
+
+ Increasing the tolerance will reduce the number of the
+ resulting points.
+
+ \param tolerance Tolerance
+
+ \sa tolerance()
+*/
+void QwtWeedingCurveFitter::setTolerance( double tolerance )
+{
+    d_data->tolerance = qMax( tolerance, 0.0 );
+}
+
+/*!
+  \return Tolerance
+  \sa setTolerance()
+*/
+double QwtWeedingCurveFitter::tolerance() const
+{
+    return d_data->tolerance;
+}
+
+/*!
+  \param points Series of data points
+  \return Curve points
+*/
+QPolygonF QwtWeedingCurveFitter::fitCurve( const QPolygonF &points ) const
+{
+    QStack<Line> stack;
+    stack.reserve( 500 );
+
+    const QPointF *p = points.data();
+    const int nPoints = points.size();
+
+    QVector<bool> usePoint( nPoints, false );
+
+    double distToSegment;
+
+    stack.push( Line( 0, nPoints - 1 ) );
+
+    while ( !stack.isEmpty() )
+    {
+        const Line r = stack.pop();
+
+        // initialize line segment
+        const double vecX = p[r.to].x() - p[r.from].x();
+        const double vecY = p[r.to].y() - p[r.from].y();
+
+        const double vecLength = qSqrt( vecX * vecX + vecY * vecY );
+
+        const double unitVecX = ( vecLength != 0.0 ) ? vecX / vecLength : 0.0;
+        const double unitVecY = ( vecLength != 0.0 ) ? vecY / vecLength : 0.0;
+
+        double maxDist = 0.0;
+        int nVertexIndexMaxDistance = r.from + 1;
+        for ( int i = r.from + 1; i < r.to; i++ )
+        {
+            //compare to anchor
+            const double fromVecX = p[i].x() - p[r.from].x();
+            const double fromVecY = p[i].y() - p[r.from].y();
+            const double fromVecLength =
+                qSqrt( fromVecX * fromVecX + fromVecY * fromVecY );
+
+            if ( fromVecX * unitVecX + fromVecY * unitVecY < 0.0 )
+            {
+                distToSegment = fromVecLength;
+            }
+            if ( fromVecX * unitVecX + fromVecY * unitVecY < 0.0 )
+            {
+                distToSegment = fromVecLength;
+            }
+            else
+            {
+                const double toVecX = p[i].x() - p[r.to].x();
+                const double toVecY = p[i].y() - p[r.to].y();
+                const double toVecLength = qSqrt( toVecX * toVecX + toVecY * toVecY );
+                const double s = toVecX * ( -unitVecX ) + toVecY * ( -unitVecY );
+                if ( s < 0.0 )
+                    distToSegment = toVecLength;
+                else
+                {
+                    distToSegment = qSqrt( qFabs( toVecLength * toVecLength - s * s ) );
+                }
+            }
+
+            if ( maxDist < distToSegment )
+            {
+                maxDist = distToSegment;
+                nVertexIndexMaxDistance = i;
+            }
+        }
+        if ( maxDist <= d_data->tolerance )
+        {
+            usePoint[r.from] = true;
+            usePoint[r.to] = true;
+        }
+        else
+        {
+            stack.push( Line( r.from, nVertexIndexMaxDistance ) );
+            stack.push( Line( nVertexIndexMaxDistance, r.to ) );
+        }
+    }
+
+    int cnt = 0;
+
+    QPolygonF stripped( nPoints );
+    for ( int i = 0; i < nPoints; i++ )
+    {
+        if ( usePoint[i] )
+            stripped[cnt++] = p[i];
+    }
+    stripped.resize( cnt );
+    return stripped;
+}

+ 130 - 0
starpu-top/qwt/qwt_curve_fitter.h

@@ -0,0 +1,130 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#ifndef QWT_CURVE_FITTER_H
+#define QWT_CURVE_FITTER_H
+
+#include "qwt_global.h"
+#include <qpolygon.h>
+#include <qrect.h>
+
+class QwtSpline;
+
+/*!
+  \brief Abstract base class for a curve fitter
+*/
+class QWT_EXPORT QwtCurveFitter
+{
+public:
+    virtual ~QwtCurveFitter();
+
+    /*!
+        Find a curve which has the best fit to a series of data points
+
+        \param polygon Series of data points
+        \return Curve points
+     */
+    virtual QPolygonF fitCurve( const QPolygonF &polygon ) const = 0;
+
+protected:
+    QwtCurveFitter();
+
+private:
+    QwtCurveFitter( const QwtCurveFitter & );
+    QwtCurveFitter &operator=( const QwtCurveFitter & );
+};
+
+/*!
+  \brief A curve fitter using cubic splines
+*/
+class QWT_EXPORT QwtSplineCurveFitter: public QwtCurveFitter
+{
+public:
+    /*!
+     - Spline\n
+       Use a default spline algorithm
+
+     - ParametricSpline\n
+       Use a parametric spline algorithm
+
+     - Auto\n
+       Use the default spline algorithm for polygons with
+       increasing x values ( p[i-1] < p[i] ), otherwise use
+       a parametric spline algorithm.
+
+     The default setting is Auto
+
+     \sa setFitMode(), FitMode()
+     */
+    enum FitMode
+    {
+        Auto,
+        Spline,
+        ParametricSpline
+    };
+
+    QwtSplineCurveFitter();
+    virtual ~QwtSplineCurveFitter();
+
+    void setFitMode( FitMode );
+    FitMode fitMode() const;
+
+    void setSpline( const QwtSpline& );
+    const QwtSpline &spline() const;
+    QwtSpline &spline();
+
+    void setSplineSize( int size );
+    int splineSize() const;
+
+    virtual QPolygonF fitCurve( const QPolygonF & ) const;
+
+private:
+    QPolygonF fitSpline( const QPolygonF & ) const;
+    QPolygonF fitParametric( const QPolygonF & ) const;
+
+    class PrivateData;
+    PrivateData *d_data;
+};
+
+/*!
+  \brief A curve fitter implementing Douglas and Peucker algorithm
+
+  The purpose of the Douglas and Peucker algorithm is that given a 'curve'
+  composed of line segments to find a curve not too dissimilar but that
+  has fewer points. The algorithm defines 'too dissimilar' based on the
+  maximum distance (tolerance) between the original curve and the
+  smoothed curve.
+
+  The smoothed curve consists of a subset of the points that defined the
+  original curve.
+
+  In opposite to QwtSplineCurveFitter the Douglas and Peucker algorithm reduces
+  the number of points. By adjusting the tolerance parameter according to the
+  axis scales QwtSplineCurveFitter can be used to implement different
+  level of details to speed up painting of curves of many points.
+*/
+class QWT_EXPORT QwtWeedingCurveFitter: public QwtCurveFitter
+{
+public:
+    QwtWeedingCurveFitter( double tolerance = 1.0 );
+    virtual ~QwtWeedingCurveFitter();
+
+    void setTolerance( double );
+    double tolerance() const;
+
+    virtual QPolygonF fitCurve( const QPolygonF & ) const;
+
+private:
+    class Line;
+
+    class PrivateData;
+    PrivateData *d_data;
+};
+
+#endif

File diff suppressed because it is too large
+ 1189 - 0
starpu-top/qwt/qwt_dial.cpp


+ 223 - 0
starpu-top/qwt/qwt_dial.h

@@ -0,0 +1,223 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#ifndef QWT_DIAL_H
+#define QWT_DIAL_H 1
+
+#include "qwt_global.h"
+#include "qwt_abstract_slider.h"
+#include "qwt_round_scale_draw.h"
+#include <qframe.h>
+#include <qpalette.h>
+
+class QwtDialNeedle;
+class QwtDial;
+
+/*!
+  \brief A special scale draw made for QwtDial
+
+  \sa QwtDial, QwtCompass
+*/
+class QWT_EXPORT QwtDialScaleDraw: public QwtRoundScaleDraw
+{
+public:
+    explicit QwtDialScaleDraw( QwtDial * );
+
+    virtual QwtText label( double value ) const;
+
+    void setPenWidth( double );
+    double penWidth() const;
+
+private:
+    QwtDial *d_parent;
+    double d_penWidth;
+};
+
+/*!
+  \brief QwtDial class provides a rounded range control.
+
+  QwtDial is intended as base class for dial widgets like
+  speedometers, compass widgets, clocks ...
+
+  \image html dials2.png
+
+  A dial contains a scale and a needle indicating the current value
+  of the dial. Depending on Mode one of them is fixed and the
+  other is rotating. If not isReadOnly() the
+  dial can be rotated by dragging the mouse or using keyboard inputs
+  (see keyPressEvent()). A dial might be wrapping, what means
+  a rotation below/above one limit continues on the other limit (f.e compass).
+  The scale might cover any arc of the dial, its values are related to
+  the origin() of the dial.
+
+  Qwt is missing a set of good looking needles (QwtDialNeedle).
+  Contributions are very welcome.
+
+  \sa QwtCompass, QwtAnalogClock, QwtDialNeedle
+  \note The examples/dials example shows different types of dials.
+*/
+
+class QWT_EXPORT QwtDial: public QwtAbstractSlider
+{
+    Q_OBJECT
+
+    Q_ENUMS( Shadow )
+    Q_ENUMS( Mode )
+    Q_ENUMS( Direction )
+
+    Q_PROPERTY( bool visibleBackground READ hasVisibleBackground WRITE showBackground )
+    Q_PROPERTY( int lineWidth READ lineWidth WRITE setLineWidth )
+    Q_PROPERTY( Shadow frameShadow READ frameShadow WRITE setFrameShadow )
+    Q_PROPERTY( Mode mode READ mode WRITE setMode )
+    Q_PROPERTY( double origin READ origin WRITE setOrigin )
+    Q_PROPERTY( bool wrapping READ wrapping WRITE setWrapping )
+    Q_PROPERTY( Direction direction READ direction WRITE setDirection )
+
+    friend class QwtDialScaleDraw;
+public:
+
+    /*!
+        \brief Frame shadow
+
+         Unfortunately it is not possible to use QFrame::Shadow
+         as a property of a widget that is not derived from QFrame.
+         The following enum is made for the designer only. It is safe
+         to use QFrame::Shadow instead.
+     */
+    enum Shadow
+    {
+        Plain = QFrame::Plain,
+        Raised = QFrame::Raised,
+        Sunken = QFrame::Sunken
+    };
+
+    //! see QwtDial::setScaleOptions
+    enum ScaleOptions
+    {
+        ScaleBackbone = 1,
+        ScaleTicks = 2,
+        ScaleLabel = 4
+    };
+
+    /*!
+        In case of RotateNeedle the needle is rotating, in case of
+        RotateScale, the needle points to origin()
+        and the scale is rotating.
+    */
+    enum Mode
+    {
+        RotateNeedle,
+        RotateScale
+    };
+
+    /*!
+      Direction of the dial
+    */
+    enum Direction
+    {
+        Clockwise,
+        CounterClockwise
+    };
+
+    explicit QwtDial( QWidget *parent = NULL );
+    virtual ~QwtDial();
+
+    void setFrameShadow( Shadow );
+    Shadow frameShadow() const;
+
+    bool hasVisibleBackground() const;
+    void showBackground( bool );
+
+    void setLineWidth( int );
+    int lineWidth() const;
+
+    void setMode( Mode );
+    Mode mode() const;
+
+    virtual void setWrapping( bool );
+    bool wrapping() const;
+
+    virtual void setScale( int maxMajIntv, int maxMinIntv, double step = 0.0 );
+
+    void setScaleArc( double min, double max );
+    void setScaleOptions( int );
+    void setScaleTicks( int minLen, int medLen, int majLen, int penWidth = 1 );
+
+    double minScaleArc() const;
+    double maxScaleArc() const;
+
+    virtual void setOrigin( double );
+    double origin() const;
+
+    void setDirection( Direction );
+    Direction direction() const;
+
+    virtual void setNeedle( QwtDialNeedle * );
+    const QwtDialNeedle *needle() const;
+    QwtDialNeedle *needle();
+
+    QRect boundingRect() const;
+    QRect contentsRect() const;
+    virtual QRect scaleContentsRect() const;
+
+    virtual QSize sizeHint() const;
+    virtual QSize minimumSizeHint() const;
+
+    virtual void setScaleDraw( QwtDialScaleDraw * );
+
+    QwtDialScaleDraw *scaleDraw();
+    const QwtDialScaleDraw *scaleDraw() const;
+
+protected:
+    virtual void paintEvent( QPaintEvent * );
+    virtual void resizeEvent( QResizeEvent * );
+    virtual void keyPressEvent( QKeyEvent * );
+
+    virtual void updateMask();
+
+    virtual void drawFrame( QPainter *p );
+    virtual void drawContents( QPainter * ) const;
+    virtual void drawFocusIndicator( QPainter * ) const;
+
+    virtual void drawScale( QPainter *, const QPoint &center,
+        int radius, double origin, double arcMin, double arcMax ) const;
+
+    /*!
+      Draw the contents inside the scale
+
+      Paints nothing.
+
+      \param painter Painter
+      \param center Center of the contents circle
+      \param radius Radius of the contents circle
+    */
+    virtual void drawScaleContents( QPainter *painter, 
+        const QPoint &center, int radius ) const;
+
+    virtual void drawNeedle( QPainter *, const QPoint &,
+        int radius, double direction, QPalette::ColorGroup ) const;
+
+    virtual QwtText scaleLabel( double ) const;
+    void updateScale();
+
+    virtual void rangeChange();
+    virtual void valueChange();
+
+    virtual double getValue( const QPoint & );
+    virtual void getScrollMode( const QPoint &,
+        int &scrollMode, int &direction );
+
+private:
+    void initDial();
+
+    class PrivateData;
+    PrivateData *d_data;
+};
+
+#endif

+ 605 - 0
starpu-top/qwt/qwt_dial_needle.cpp

@@ -0,0 +1,605 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#include "qwt_dial_needle.h"
+#include "qwt_global.h"
+#include "qwt_math.h"
+#include "qwt_painter.h"
+#include <qapplication.h>
+#include <qpainter.h>
+
+//! Constructor
+QwtDialNeedle::QwtDialNeedle():
+    d_palette( QApplication::palette() )
+{
+}
+
+//! Destructor
+QwtDialNeedle::~QwtDialNeedle()
+{
+}
+
+/*!
+    Sets the palette for the needle.
+
+    \param palette New Palette
+*/
+void QwtDialNeedle::setPalette( const QPalette &palette )
+{
+    d_palette = palette;
+}
+
+/*!
+  \return the palette of the needle.
+*/
+const QPalette &QwtDialNeedle::palette() const
+{
+    return d_palette;
+}
+
+//!  Draw the knob
+void QwtDialNeedle::drawKnob( QPainter *painter,
+    const QPoint &pos, int width, const QBrush &brush, bool sunken )
+{
+    painter->save();
+
+    QRect rect( 0, 0, width, width );
+    rect.moveCenter( pos );
+
+    painter->setPen( Qt::NoPen );
+    painter->setBrush( brush );
+    painter->drawEllipse( rect );
+
+    painter->setBrush( Qt::NoBrush );
+
+    const int colorOffset = 20;
+
+    int startAngle = 45;
+    if ( sunken )
+        startAngle += 180;
+
+    QPen pen;
+    pen.setWidth( 1 );
+
+    pen.setColor( brush.color().dark( 100 - colorOffset ) );
+    painter->setPen( pen );
+    painter->drawArc( rect, startAngle * 16, 180 * 16 );
+
+    pen.setColor( brush.color().dark( 100 + colorOffset ) );
+    painter->setPen( pen );
+    painter->drawArc( rect, ( startAngle + 180 ) * 16, 180 * 16 );
+
+    painter->restore();
+}
+
+/*!
+  Constructor
+
+  \param style Style
+  \param hasKnob With/Without knob
+  \param mid Middle color
+  \param base Base color
+*/
+QwtDialSimpleNeedle::QwtDialSimpleNeedle( Style style, bool hasKnob,
+        const QColor &mid, const QColor &base ):
+    d_style( style ),
+    d_hasKnob( hasKnob ),
+    d_width( -1 )
+{
+    QPalette palette;
+    for ( int i = 0; i < QPalette::NColorGroups; i++ )
+    {
+        palette.setColor( ( QPalette::ColorGroup )i,
+            QPalette::Mid, mid );
+        palette.setColor( ( QPalette::ColorGroup )i,
+            QPalette::Base, base );
+    }
+
+    setPalette( palette );
+}
+
+/*!
+  Set the width of the needle
+  \param width Width
+  \sa width()
+*/
+void QwtDialSimpleNeedle::setWidth( int width )
+{
+    d_width = width;
+}
+
+/*!
+  \return the width of the needle
+  \sa setWidth()
+*/
+int QwtDialSimpleNeedle::width() const
+{
+    return d_width;
+}
+
+/*!
+ Draw the needle
+
+ \param painter Painter
+ \param center Center of the dial, start position for the needle
+ \param length Length of the needle
+ \param direction Direction of the needle, in degrees counter clockwise
+ \param colorGroup Color group, used for painting
+*/
+void QwtDialSimpleNeedle::draw( QPainter *painter, const QPoint &center,
+    int length, double direction, QPalette::ColorGroup colorGroup ) const
+{
+    if ( d_style == Arrow )
+    {
+        drawArrowNeedle( painter, palette(), colorGroup,
+            center, length, d_width, direction, d_hasKnob );
+    }
+    else
+    {
+        drawRayNeedle( painter, palette(), colorGroup,
+            center, length, d_width, direction, d_hasKnob );
+    }
+}
+
+/*!
+  Draw a needle looking like a ray
+
+  \param painter Painter
+  \param palette Palette
+  \param colorGroup Color group
+  \param center center of the needle
+  \param length Length of the needle
+  \param width Width of the needle
+  \param direction Current Direction
+  \param hasKnob With/Without knob
+*/
+void QwtDialSimpleNeedle::drawRayNeedle( QPainter *painter,
+    const QPalette &palette, QPalette::ColorGroup colorGroup,
+    const QPoint &center, int length, int width, double direction,
+    bool hasKnob )
+{
+    if ( width <= 0 )
+        width = 5;
+
+    direction *= M_PI / 180.0;
+
+    painter->save();
+
+    const QPoint p1( center.x() + 1, center.y() + 2 );
+    const QPoint p2 = qwtPolar2Pos( p1, length, direction );
+
+    if ( width == 1 )
+    {
+        const QColor midColor =
+            palette.color( colorGroup, QPalette::Mid );
+
+        painter->setPen( QPen( midColor, 1 ) );
+        painter->drawLine( p1, p2 );
+    }
+    else
+    {
+        QPolygon pa( 4 );
+        pa.setPoint( 0, qwtPolar2Pos( p1, width / 2, direction + M_PI_2 ) );
+        pa.setPoint( 1, qwtPolar2Pos( p2, width / 2, direction + M_PI_2 ) );
+        pa.setPoint( 2, qwtPolar2Pos( p2, width / 2, direction - M_PI_2 ) );
+        pa.setPoint( 3, qwtPolar2Pos( p1, width / 2, direction - M_PI_2 ) );
+
+        painter->setPen( Qt::NoPen );
+        painter->setBrush( palette.brush( colorGroup, QPalette::Mid ) );
+        painter->drawPolygon( pa );
+    }
+    if ( hasKnob )
+    {
+        int knobWidth = qMax( qRound( width * 0.7 ), 5 );
+        if ( knobWidth % 2 == 0 )
+            knobWidth++;
+
+        drawKnob( painter, center, knobWidth,
+            palette.brush( colorGroup, QPalette::Base ),
+            false );
+    }
+
+    painter->restore();
+}
+
+/*!
+  Draw a needle looking like an arrow
+
+  \param painter Painter
+  \param palette Palette
+  \param colorGroup Color group
+  \param center center of the needle
+  \param length Length of the needle
+  \param width Width of the needle
+  \param direction Current Direction
+  \param hasKnob With/Without knob
+*/
+void QwtDialSimpleNeedle::drawArrowNeedle( QPainter *painter,
+    const QPalette &palette, QPalette::ColorGroup colorGroup,
+    const QPoint &center, int length, int width,
+    double direction, bool hasKnob )
+{
+    direction *= M_PI / 180.0;
+
+    painter->save();
+
+    if ( width <= 0 )
+    {
+        width = ( int )qMax( length * 0.06, 9.0 );
+        if ( width % 2 == 0 )
+            width++;
+    }
+
+    const int peak = 3;
+    const QPoint p1( center.x() + 1, center.y() + 1 );
+    const QPoint p2 = qwtPolar2Pos( p1, length - peak, direction );
+    const QPoint p3 = qwtPolar2Pos( p1, length, direction );
+
+    QPolygon pa( 5 );
+    pa.setPoint( 0, qwtPolar2Pos( p1, width / 2, direction - M_PI_2 ) );
+    pa.setPoint( 1, qwtPolar2Pos( p2, 1, direction - M_PI_2 ) );
+    pa.setPoint( 2, p3 );
+    pa.setPoint( 3, qwtPolar2Pos( p2, 1, direction + M_PI_2 ) );
+    pa.setPoint( 4, qwtPolar2Pos( p1, width / 2, direction + M_PI_2 ) );
+
+    painter->setPen( Qt::NoPen );
+    painter->setBrush( palette.brush( colorGroup, QPalette::Mid ) );
+    painter->drawPolygon( pa );
+
+    QPolygon shadowPa( 3 );
+
+    const int colorOffset = 10;
+
+    int i;
+    for ( i = 0; i < 3; i++ )
+        shadowPa.setPoint( i, pa[i] );
+
+    const QColor midColor = palette.color( colorGroup, QPalette::Mid );
+
+    painter->setPen( midColor.dark( 100 + colorOffset ) );
+    painter->drawPolyline( shadowPa );
+
+    for ( i = 0; i < 3; i++ )
+        shadowPa.setPoint( i, pa[i + 2] );
+
+    painter->setPen( midColor.dark( 100 - colorOffset ) );
+    painter->drawPolyline( shadowPa );
+
+    if ( hasKnob )
+    {
+        drawKnob( painter, center, qRound( width * 1.3 ),
+            palette.brush( colorGroup, QPalette::Base ),
+            false );
+    }
+
+    painter->restore();
+}
+
+//! Constructor
+
+QwtCompassMagnetNeedle::QwtCompassMagnetNeedle( Style style,
+        const QColor &light, const QColor &dark ):
+    d_style( style )
+{
+    QPalette palette;
+    for ( int i = 0; i < QPalette::NColorGroups; i++ )
+    {
+        palette.setColor( ( QPalette::ColorGroup )i,
+            QPalette::Light, light );
+        palette.setColor( ( QPalette::ColorGroup )i,
+            QPalette::Dark, dark );
+        palette.setColor( ( QPalette::ColorGroup )i,
+            QPalette::Base, Qt::darkGray );
+    }
+
+    setPalette( palette );
+}
+
+/*!
+    Draw the needle
+
+    \param painter Painter
+    \param center Center of the dial, start position for the needle
+    \param length Length of the needle
+    \param direction Direction of the needle, in degrees counter clockwise
+    \param colorGroup Color group, used for painting
+*/
+void QwtCompassMagnetNeedle::draw( QPainter *painter, const QPoint &center,
+   int length, double direction, QPalette::ColorGroup colorGroup ) const
+{
+    if ( d_style == ThinStyle )
+    {
+        drawThinNeedle( painter, palette(), colorGroup,
+            center, length, direction );
+    }
+    else
+    {
+        drawTriangleNeedle( painter, palette(), colorGroup,
+            center, length, direction );
+    }
+}
+
+/*!
+  Draw a compass needle
+
+  \param painter Painter
+  \param palette Palette
+  \param colorGroup Color group
+  \param center Center, where the needle starts
+  \param length Length of the needle
+  \param direction Direction
+*/
+void QwtCompassMagnetNeedle::drawTriangleNeedle( QPainter *painter,
+    const QPalette &palette, QPalette::ColorGroup colorGroup,
+    const QPoint &center, int length, double direction )
+{
+    const QBrush darkBrush = palette.brush( colorGroup, QPalette::Dark );
+    const QBrush lightBrush = palette.brush( colorGroup, QPalette::Light );
+
+    QBrush brush;
+
+    const int width = qRound( length / 3.0 );
+    const int colorOffset =  10;
+
+    painter->save();
+    painter->setPen( Qt::NoPen );
+
+    const QPoint arrowCenter( center.x() + 1, center.y() + 1 );
+
+    QPolygon pa( 3 );
+    pa.setPoint( 0, arrowCenter );
+    pa.setPoint( 1, qwtDegree2Pos( arrowCenter, length, direction ) );
+
+    pa.setPoint( 2, qwtDegree2Pos( arrowCenter, width / 2, direction + 90.0 ) );
+
+    brush = darkBrush;
+    brush.setColor( brush.color().dark( 100 + colorOffset ) );
+    painter->setBrush( brush );
+    painter->drawPolygon( pa );
+
+    pa.setPoint( 2, qwtDegree2Pos( arrowCenter, width / 2, direction - 90.0 ) );
+
+    brush = darkBrush;
+    brush.setColor( brush.color().dark( 100 - colorOffset ) );
+    painter->setBrush( brush );
+    painter->drawPolygon( pa );
+
+    // --
+
+    pa.setPoint( 1, qwtDegree2Pos( arrowCenter, length, direction + 180.0 ) );
+
+    pa.setPoint( 2, qwtDegree2Pos( arrowCenter, width / 2, direction + 90.0 ) );
+
+    brush = lightBrush;
+    brush.setColor( brush.color().dark( 100 + colorOffset ) );
+    painter->setBrush( brush );
+    painter->drawPolygon( pa );
+
+    pa.setPoint( 2, qwtDegree2Pos( arrowCenter, width / 2, direction - 90.0 ) );
+
+    brush = lightBrush;
+    brush.setColor( brush.color().dark( 100 - colorOffset ) );
+    painter->setBrush( brush );
+    painter->drawPolygon( pa );
+
+    painter->restore();
+}
+
+/*!
+  Draw a compass needle
+
+  \param painter Painter
+  \param palette Palette
+  \param colorGroup Color group
+  \param center Center, where the needle starts
+  \param length Length of the needle
+  \param direction Direction
+*/
+void QwtCompassMagnetNeedle::drawThinNeedle( QPainter *painter,
+    const QPalette &palette, QPalette::ColorGroup colorGroup,
+    const QPoint &center, int length, double direction )
+{
+    const QBrush darkBrush = palette.brush( colorGroup, QPalette::Dark );
+    const QBrush lightBrush = palette.brush( colorGroup, QPalette::Light );
+    const QBrush baseBrush = palette.brush( colorGroup, QPalette::Base );
+
+    const int colorOffset = 10;
+    const int width = qMax( qRound( length / 6.0 ), 3 );
+
+    painter->save();
+
+    const QPoint arrowCenter( center.x() + 1, center.y() + 1 );
+
+    drawPointer( painter, darkBrush, colorOffset,
+        arrowCenter, length, width, direction );
+    drawPointer( painter, lightBrush, -colorOffset,
+        arrowCenter, length, width, direction + 180.0 );
+
+    drawKnob( painter, arrowCenter, width, baseBrush, true );
+
+    painter->restore();
+}
+
+/*!
+  Draw a compass needle
+
+  \param painter Painter
+  \param brush Brush
+  \param colorOffset Color offset
+  \param center Center, where the needle starts
+  \param length Length of the needle
+  \param width Width of the needle
+  \param direction Direction
+*/
+void QwtCompassMagnetNeedle::drawPointer(
+    QPainter *painter, const QBrush &brush,
+    int colorOffset, const QPoint &center, int length,
+    int width, double direction )
+{
+    painter->save();
+
+    const int peak = qMax( qRound( length / 10.0 ), 5 );
+
+    const int knobWidth = width + 8;
+    QRect knobRect( 0, 0, knobWidth, knobWidth );
+    knobRect.moveCenter( center );
+
+    QPolygon pa( 5 );
+
+    pa.setPoint( 0, qwtDegree2Pos( center, width / 2, direction + 90.0 ) );
+    pa.setPoint( 1, center );
+    pa.setPoint( 2, qwtDegree2Pos( pa.point( 1 ), length - peak, direction ) );
+    pa.setPoint( 3, qwtDegree2Pos( center, length, direction ) );
+    pa.setPoint( 4, qwtDegree2Pos( pa.point( 0 ), length - peak, direction ) );
+
+    painter->setPen( Qt::NoPen );
+
+    QBrush darkBrush = brush;
+    darkBrush.setColor( darkBrush.color().dark( 100 + colorOffset ) );
+    painter->setBrush( darkBrush );
+    painter->drawPolygon( pa );
+    painter->drawPie( knobRect, qRound( direction * 16 ), 90 * 16 );
+
+    pa.setPoint( 0, qwtDegree2Pos( center, width / 2, direction - 90.0 ) );
+    pa.setPoint( 4, qwtDegree2Pos( pa.point( 0 ), length - peak, direction ) );
+
+    QBrush lightBrush = brush;
+    lightBrush.setColor( lightBrush.color().dark( 100 - colorOffset ) );
+    painter->setBrush( lightBrush );
+    painter->drawPolygon( pa );
+    painter->drawPie( knobRect, qRound( direction * 16 ), -90 * 16 );
+
+    painter->restore();
+}
+
+/*!
+   Constructor
+
+   \param style Arrow style
+   \param light Light color
+   \param dark Dark color
+*/
+QwtCompassWindArrow::QwtCompassWindArrow( Style style,
+        const QColor &light, const QColor &dark ):
+    d_style( style )
+{
+    QPalette palette;
+    for ( int i = 0; i < QPalette::NColorGroups; i++ )
+    {
+        palette.setColor( ( QPalette::ColorGroup )i,
+            QPalette::Light, light );
+        palette.setColor( ( QPalette::ColorGroup )i,
+            QPalette::Dark, dark );
+    }
+
+    setPalette( palette );
+}
+
+/*!
+ Draw the needle
+
+ \param painter Painter
+ \param center Center of the dial, start position for the needle
+ \param length Length of the needle
+ \param direction Direction of the needle, in degrees counter clockwise
+ \param colorGroup Color group, used for painting
+*/
+void QwtCompassWindArrow::draw( QPainter *painter, const QPoint &center,
+    int length, double direction, QPalette::ColorGroup colorGroup ) const
+{
+    if ( d_style == Style1 )
+    {
+        drawStyle1Needle( painter, palette(), colorGroup,
+            center, length, direction );
+    }
+    else
+    {
+        drawStyle2Needle( painter, palette(), colorGroup,
+            center, length, direction );
+    }
+}
+
+/*!
+  Draw a compass needle
+
+ \param painter Painter
+ \param palette Palette
+ \param colorGroup colorGroup
+ \param center Center of the dial, start position for the needle
+ \param length Length of the needle
+ \param direction Direction of the needle, in degrees counter clockwise
+*/
+void QwtCompassWindArrow::drawStyle1Needle( QPainter *painter,
+    const QPalette &palette, QPalette::ColorGroup colorGroup,
+    const QPoint &center, int length, double direction )
+{
+    const QBrush lightBrush = palette.brush( colorGroup, QPalette::Light );
+
+    const double AR1[] = {0, 0.4, 0.3, 1, 0.8, 1, 0.3, 0.4};
+    const double AW1[] = {0, -45, -20, -15, 0, 15, 20, 45};
+
+    const QPoint arrowCenter( center.x() + 1, center.y() + 1 );
+
+    QPolygon pa( 8 );
+    pa.setPoint( 0, arrowCenter );
+    for ( int i = 1; i < 8; i++ )
+    {
+        const QPoint p = qwtDegree2Pos( center,
+            AR1[i] * length, direction + AW1[i] );
+        pa.setPoint( i, p );
+    }
+
+    painter->save();
+    painter->setPen( Qt::NoPen );
+    painter->setBrush( lightBrush );
+    painter->drawPolygon( pa );
+    painter->restore();
+}
+
+/*!
+  Draw a compass needle
+
+ \param painter Painter
+ \param palette Palette
+ \param colorGroup colorGroup
+ \param center Center of the dial, start position for the needle
+ \param length Length of the needle
+ \param direction Direction of the needle, in degrees counter clockwise
+*/
+void QwtCompassWindArrow::drawStyle2Needle( QPainter *painter,
+    const QPalette &palette, QPalette::ColorGroup colorGroup,
+    const QPoint &center, int length, double direction )
+{
+    const QBrush lightBrush = palette.brush( colorGroup, QPalette::Light );
+    const QBrush darkBrush = palette.brush( colorGroup, QPalette::Dark );
+
+    painter->save();
+    painter->setPen( Qt::NoPen );
+
+    const double angle = 12.0;
+    const double ratio = 0.7;
+
+    const QPoint arrowCenter( center.x() + 1, center.y() + 1 );
+
+    QPolygon pa( 3 );
+
+    pa.setPoint( 0, center );
+    pa.setPoint( 2, qwtDegree2Pos( arrowCenter, ratio * length, direction ) );
+
+    pa.setPoint( 1, qwtDegree2Pos( arrowCenter, length, direction + angle ) );
+    painter->setBrush( darkBrush );
+    painter->drawPolygon( pa );
+
+    pa.setPoint( 1, qwtDegree2Pos( arrowCenter, length, direction - angle ) );
+    painter->setBrush( lightBrush );
+    painter->drawPolygon( pa );
+
+    painter->restore();
+}
+

+ 196 - 0
starpu-top/qwt/qwt_dial_needle.h

@@ -0,0 +1,196 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#ifndef QWT_DIAL_NEEDLE_H
+#define QWT_DIAL_NEEDLE_H 1
+
+#include "qwt_global.h"
+#include <qpalette.h>
+
+class QPainter;
+class QPoint;
+
+/*!
+  \brief Base class for needles that can be used in a QwtDial.
+
+  QwtDialNeedle is a pointer that indicates a value by pointing
+  to a specific direction.
+
+  Qwt is missing a set of good looking needles.
+  Contributions are very welcome.
+
+  \sa QwtDial, QwtCompass
+*/
+
+class QWT_EXPORT QwtDialNeedle
+{
+public:
+    QwtDialNeedle();
+    virtual ~QwtDialNeedle();
+
+    /*!
+      Draw the needle
+
+      \param painter Painter
+      \param center Center of the dial, start position for the needle
+      \param length Length of the needle
+      \param direction Direction of the needle, in degrees counter clockwise
+      \param colorGroup Color group, used for painting
+    */
+    virtual void draw( QPainter *painter, const QPoint &center,
+        int length, double direction,
+        QPalette::ColorGroup colorGroup = QPalette::Active ) const = 0;
+
+    virtual void setPalette( const QPalette & );
+    const QPalette &palette() const;
+
+protected:
+    static void drawKnob( QPainter *, const QPoint &pos,
+        int width, const QBrush &, bool sunken );
+
+private:
+    QPalette d_palette;
+};
+
+/*!
+  \brief A needle for dial widgets
+
+  The following colors are used:
+
+  - QPalette::Mid\n
+    Pointer
+  - QPalette::Base\n
+    Knob
+
+  \sa QwtDial, QwtCompass
+*/
+
+class QWT_EXPORT QwtDialSimpleNeedle: public QwtDialNeedle
+{
+public:
+    //! Style of the needle
+    enum Style
+    {
+        Arrow,
+        Ray
+    };
+
+    QwtDialSimpleNeedle( Style, bool hasKnob = true,
+        const QColor &mid = Qt::gray, const QColor &base = Qt::darkGray );
+
+    virtual void draw( QPainter *, const QPoint &, int length,
+        double direction, QPalette::ColorGroup = QPalette::Active ) const;
+
+    static void drawArrowNeedle( QPainter *, const QPalette &, QPalette::ColorGroup,
+        const QPoint &, int length, int width, double direction, bool hasKnob );
+
+    static void drawRayNeedle( QPainter *, const QPalette &, QPalette::ColorGroup,
+        const QPoint &, int length, int width, double direction, bool hasKnob );
+
+    void setWidth( int width );
+    int width() const;
+
+private:
+    Style d_style;
+    bool d_hasKnob;
+    int d_width;
+};
+
+/*!
+  \brief A magnet needle for compass widgets
+
+  A magnet needle points to two opposite directions indicating
+  north and south.
+
+  The following colors are used:
+  - QPalette::Light\n
+    Used for pointing south
+  - QPalette::Dark\n
+    Used for pointing north
+  - QPalette::Base\n
+    Knob (ThinStyle only)
+
+  \sa QwtDial, QwtCompass
+*/
+
+class QWT_EXPORT QwtCompassMagnetNeedle: public QwtDialNeedle
+{
+public:
+    //! Style of the needle
+    enum Style
+    {
+        TriangleStyle,
+        ThinStyle
+    };
+
+    QwtCompassMagnetNeedle( Style = TriangleStyle,
+        const QColor &light = Qt::white, const QColor &dark = Qt::red );
+
+    virtual void draw( QPainter *, const QPoint &, int length,
+        double direction, QPalette::ColorGroup = QPalette::Active ) const;
+
+    static void drawTriangleNeedle( QPainter *,
+        const QPalette &, QPalette::ColorGroup,
+        const QPoint &, int length, double direction );
+
+    static void drawThinNeedle( QPainter *,
+        const QPalette &, QPalette::ColorGroup,
+        const QPoint &, int length, double direction );
+
+protected:
+    static void drawPointer( QPainter *painter, const QBrush &brush,
+        int colorOffset, const QPoint &center,
+        int length, int width, double direction );
+
+private:
+    Style d_style;
+};
+
+/*!
+  \brief An indicator for the wind direction
+
+  QwtCompassWindArrow shows the direction where the wind comes from.
+
+  - QPalette::Light\n
+    Used for Style1, or the light half of Style2
+  - QPalette::Dark\n
+    Used for the dark half of Style2
+
+  \sa QwtDial, QwtCompass
+*/
+
+class QWT_EXPORT QwtCompassWindArrow: public QwtDialNeedle
+{
+public:
+    //! Style of the arrow
+    enum Style
+    {
+        Style1,
+        Style2
+    };
+
+    QwtCompassWindArrow( Style, const QColor &light = Qt::white,
+        const QColor &dark = Qt::gray );
+
+    virtual void draw( QPainter *, const QPoint &, int length,
+        double direction, QPalette::ColorGroup = QPalette::Active ) const;
+
+    static void drawStyle1Needle( QPainter *,
+        const QPalette &, QPalette::ColorGroup,
+        const QPoint &, int length, double direction );
+
+    static void drawStyle2Needle( QPainter *,
+        const QPalette &, QPalette::ColorGroup,
+        const QPoint &, int length, double direction );
+
+private:
+    Style d_style;
+};
+
+#endif 

+ 394 - 0
starpu-top/qwt/qwt_double_range.cpp

@@ -0,0 +1,394 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#include "qwt_double_range.h"
+#include "qwt_math.h"
+
+#if QT_VERSION < 0x040601
+#define qFabs(x) ::fabs(x)
+#endif
+
+static double MinRelStep = 1.0e-10;
+static double DefaultRelStep = 1.0e-2;
+static double MinEps = 1.0e-10;
+
+/*!
+  The range is initialized to [0.0, 100.0], the
+  step size to 1.0, and the value to 0.0.
+*/
+QwtDoubleRange::QwtDoubleRange():
+        d_minValue( 0.0 ),
+        d_maxValue( 0.0 ),
+        d_step( 1.0 ),
+        d_pageSize( 1 ),
+        d_isValid( false ),
+        d_value( 0.0 ),
+        d_exactValue( 0.0 ),
+        d_exactPrevValue( 0.0 ),
+        d_prevValue( 0.0 ),
+        d_periodic( false )
+{
+}
+
+//! Destroys the QwtDoubleRange
+QwtDoubleRange::~QwtDoubleRange()
+{
+}
+
+//! Set the value to be valid/invalid
+void QwtDoubleRange::setValid( bool isValid )
+{
+    if ( isValid != d_isValid )
+    {
+        d_isValid = isValid;
+        valueChange();
+    }
+}
+
+//! Indicates if the value is valid
+bool QwtDoubleRange::isValid() const
+{
+    return d_isValid;
+}
+
+/*!
+  \brief No docs
+
+  Description
+  \param x ???
+  \param align
+  \todo Documentation
+*/
+void QwtDoubleRange::setNewValue( double x, bool align )
+{
+    double vmin, vmax;
+
+    d_prevValue = d_value;
+
+    vmin = qMin( d_minValue, d_maxValue );
+    vmax = qMax( d_minValue, d_maxValue );
+
+    //
+    // Range check
+    //
+    if ( x < vmin )
+    {
+        if ( ( d_periodic ) && ( vmin != vmax ) )
+            d_value = x + qCeil( ( vmin - x ) / ( vmax - vmin ) )
+                      * ( vmax - vmin );
+        else
+            d_value = vmin;
+    }
+    else if ( x > vmax )
+    {
+        if ( ( d_periodic ) && ( vmin != vmax ) )
+            d_value = x - qCeil( ( x - vmax ) / ( vmax - vmin ) )
+                      * ( vmax - vmin );
+        else
+            d_value = vmax;
+    }
+    else
+        d_value = x;
+
+    d_exactPrevValue = d_exactValue;
+    d_exactValue = d_value;
+
+    // align to grid
+    if ( align )
+    {
+        if ( d_step != 0.0 )
+        {
+            d_value = d_minValue +
+                      qRound( ( d_value - d_minValue ) / d_step ) * d_step;
+        }
+        else
+            d_value = d_minValue;
+
+        // correct rounding error at the border
+        if ( qFabs( d_value - d_maxValue ) < MinEps * qAbs( d_step ) )
+            d_value = d_maxValue;
+
+        // correct rounding error if value = 0
+        if ( qFabs( d_value ) < MinEps * qAbs( d_step ) )
+            d_value = 0.0;
+    }
+
+    if ( !d_isValid || d_prevValue != d_value )
+    {
+        d_isValid = true;
+        valueChange();
+    }
+}
+
+/*!
+  \brief  Adjust the value to the closest point in the step raster.
+  \param x value
+  \warning The value is clipped when it lies outside the range.
+  When the range is QwtDoubleRange::periodic, it will
+  be mapped to a point in the interval such that
+  \verbatim new value := x + n * (max. value - min. value)\endverbatim
+  with an integer number n.
+*/
+void QwtDoubleRange::fitValue( double x )
+{
+    setNewValue( x, true );
+}
+
+
+/*!
+  \brief Set a new value without adjusting to the step raster
+  \param x new value
+  \warning The value is clipped when it lies outside the range.
+  When the range is QwtDoubleRange::periodic, it will
+  be mapped to a point in the interval such that
+  \verbatim new value := x + n * (max. value - min. value)\endverbatim
+  with an integer number n.
+*/
+void QwtDoubleRange::setValue( double x )
+{
+    setNewValue( x, false );
+}
+
+/*!
+  \brief Specify  range and step size
+
+  \param vmin   lower boundary of the interval
+  \param vmax   higher boundary of the interval
+  \param vstep  step width
+  \param pageSize  page size in steps
+  \warning
+  \li A change of the range changes the value if it lies outside the
+      new range. The current value
+      will *not* be adjusted to the new step raster.
+  \li vmax < vmin is allowed.
+  \li If the step size is left out or set to zero, it will be
+      set to 1/100 of the interval length.
+  \li If the step size has an absurd value, it will be corrected
+      to a better one.
+*/
+void QwtDoubleRange::setRange( double vmin, double vmax, double vstep, int pageSize )
+{
+    bool rchg = ( ( d_maxValue != vmax ) || ( d_minValue != vmin ) );
+
+    if ( rchg )
+    {
+        d_minValue = vmin;
+        d_maxValue = vmax;
+    }
+
+    //
+    // look if the step width has an acceptable
+    // value or otherwise change it.
+    //
+    setStep( vstep );
+
+    //
+    // limit page size
+    //
+    d_pageSize = qwtLim( pageSize, 0,
+        int( qAbs( ( d_maxValue - d_minValue ) / d_step ) ) );
+
+    // If the value lies out of the range, it
+    // will be changed. Note that it will not be adjusted to
+    // the new step width.
+    setNewValue( d_value, false );
+
+    // call notifier after the step width has been
+    // adjusted.
+    if ( rchg )
+        rangeChange();
+}
+
+/*!
+  \brief Change the step raster
+  \param vstep new step width
+  \warning The value will \e not be adjusted to the new step raster.
+*/
+void QwtDoubleRange::setStep( double vstep )
+{
+    double intv = d_maxValue - d_minValue;
+
+    double newStep;
+    if ( vstep == 0.0 )
+        newStep = intv * DefaultRelStep;
+    else
+    {
+        if ( ( intv > 0.0 && vstep < 0.0 ) || ( intv < 0.0 && vstep > 0.0 ) )
+            newStep = -vstep;
+        else
+            newStep = vstep;
+
+        if ( qFabs( newStep ) < qFabs( MinRelStep * intv ) )
+            newStep = MinRelStep * intv;
+    }
+
+    if ( newStep != d_step )
+    {
+        d_step = newStep;
+        stepChange();
+    }
+}
+
+
+/*!
+  \brief Make the range periodic
+
+  When the range is periodic, the value will be set to a point
+  inside the interval such that
+
+  \verbatim point = value + n * width \endverbatim
+
+  if the user tries to set a new value which is outside the range.
+  If the range is nonperiodic (the default), values outside the
+  range will be clipped.
+
+  \param tf true for a periodic range
+*/
+void QwtDoubleRange::setPeriodic( bool tf )
+{
+    d_periodic = tf;
+}
+
+/*!
+  \brief Increment the value by a specified number of steps
+  \param nSteps Number of steps to increment
+  \warning As a result of this operation, the new value will always be
+       adjusted to the step raster.
+*/
+void QwtDoubleRange::incValue( int nSteps )
+{
+    if ( isValid() )
+        setNewValue( d_value + double( nSteps ) * d_step, true );
+}
+
+/*!
+  \brief Increment the value by a specified number of pages
+  \param nPages Number of pages to increment.
+        A negative number decrements the value.
+  \warning The Page size is specified in the constructor.
+*/
+void QwtDoubleRange::incPages( int nPages )
+{
+    if ( isValid() )
+        setNewValue( d_value + double( nPages ) * double( d_pageSize ) * d_step, true );
+}
+
+/*!
+  \brief Notify a change of value
+
+  This virtual function is called whenever the value changes.
+  The default implementation does nothing.
+*/
+void QwtDoubleRange::valueChange()
+{
+}
+
+
+/*!
+  \brief Notify a change of the range
+
+  This virtual function is called whenever the range changes.
+  The default implementation does nothing.
+*/
+void QwtDoubleRange::rangeChange()
+{
+}
+
+
+/*!
+  \brief Notify a change of the step size
+
+  This virtual function is called whenever the step size changes.
+  The default implementation does nothing.
+*/
+void QwtDoubleRange::stepChange()
+{
+}
+
+/*!
+  \return the step size
+  \sa setStep(), setRange()
+*/
+double QwtDoubleRange::step() const
+{
+    return qAbs( d_step );
+}
+
+/*!
+  \brief Returns the value of the second border of the range
+
+  maxValue returns the value which has been specified
+  as the second parameter in  QwtDoubleRange::setRange.
+
+  \sa setRange()
+*/
+double QwtDoubleRange::maxValue() const
+{
+    return d_maxValue;
+}
+
+/*!
+  \brief Returns the value at the first border of the range
+
+  minValue returns the value which has been specified
+  as the first parameter in  setRange().
+
+  \sa setRange()
+*/
+double QwtDoubleRange::minValue() const
+{
+    return d_minValue;
+}
+
+/*!
+  \brief Returns true if the range is periodic
+  \sa setPeriodic()
+*/
+bool QwtDoubleRange::periodic() const
+{
+    return d_periodic;
+}
+
+//! Returns the page size in steps.
+int QwtDoubleRange::pageSize() const
+{
+    return d_pageSize;
+}
+
+//! Returns the current value.
+double QwtDoubleRange::value() const
+{
+    return d_value;
+}
+
+/*!
+  \brief Returns the exact value
+
+  The exact value is the value which QwtDoubleRange::value would return
+  if the value were not adjusted to the step raster. It differs from
+  the current value only if QwtDoubleRange::fitValue or
+  QwtDoubleRange::incValue have been used before. This function
+  is intended for internal use in derived classes.
+*/
+double QwtDoubleRange::exactValue() const
+{
+    return d_exactValue;
+}
+
+//! Returns the exact previous value
+double QwtDoubleRange::exactPrevValue() const
+{
+    return d_exactPrevValue;
+}
+
+//! Returns the previous value
+double QwtDoubleRange::prevValue() const
+{
+    return d_prevValue;
+}

+ 88 - 0
starpu-top/qwt/qwt_double_range.h

@@ -0,0 +1,88 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#ifndef QWT_DOUBLE_RANGE_H
+#define QWT_DOUBLE_RANGE_H
+
+#include "qwt_global.h"
+
+/*!
+  \brief A class which controls a value within an interval
+
+  This class is useful as a base class or a member for sliders.
+  It represents an interval of type double within which a value can
+  be moved. The value can be either an arbitrary point inside
+  the interval (see QwtDoubleRange::setValue), or it can be fitted
+  into a step raster (see QwtDoubleRange::fitValue and
+  QwtDoubleRange::incValue).
+
+  As a special case, a QwtDoubleRange can be periodic, which means that
+  a value outside the interval will be mapped to a value inside the
+  interval when QwtDoubleRange::setValue(), QwtDoubleRange::fitValue(),
+  QwtDoubleRange::incValue() or QwtDoubleRange::incPages() are called.
+*/
+
+class QWT_EXPORT QwtDoubleRange
+{
+public:
+    QwtDoubleRange();
+    virtual ~QwtDoubleRange();
+
+    void setRange( double vmin, double vmax, 
+        double vstep = 0.0, int pagesize = 1 );
+
+    void setValid( bool );
+    bool isValid() const;
+
+    virtual void setValue( double );
+    double value() const;
+
+    void setPeriodic( bool tf );
+    bool periodic() const;
+
+    void setStep( double );
+    double step() const;
+
+    double maxValue() const;
+    double minValue() const;
+
+    int pageSize() const;
+
+    virtual void incValue( int );
+    virtual void incPages( int );
+    virtual void fitValue( double );
+
+protected:
+
+    double exactValue() const;
+    double exactPrevValue() const;
+    double prevValue() const;
+
+    virtual void valueChange();
+    virtual void stepChange();
+    virtual void rangeChange();
+
+private:
+    void setNewValue( double x, bool align = false );
+
+    double d_minValue;
+    double d_maxValue;
+    double d_step;
+    int d_pageSize;
+
+    bool d_isValid;
+    double d_value;
+    double d_exactValue;
+    double d_exactPrevValue;
+    double d_prevValue;
+
+    bool d_periodic;
+};
+
+#endif

+ 571 - 0
starpu-top/qwt/qwt_dyngrid_layout.cpp

@@ -0,0 +1,571 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#include "qwt_dyngrid_layout.h"
+#include "qwt_math.h"
+#include <qwidget.h>
+#include <qlist.h>
+
+class QwtDynGridLayout::PrivateData
+{
+public:
+    PrivateData():
+        isDirty( true )
+    {
+    }
+
+    void updateLayoutCache();
+
+    mutable QList<QLayoutItem*> itemList;
+
+    uint maxCols;
+    uint numRows;
+    uint numCols;
+
+    Qt::Orientations expanding;
+
+    bool isDirty;
+    QVector<QSize> itemSizeHints;
+};
+
+void QwtDynGridLayout::PrivateData::updateLayoutCache()
+{
+    itemSizeHints.resize( itemList.count() );
+
+    int index = 0;
+
+    for ( QList<QLayoutItem*>::iterator it = itemList.begin();
+        it != itemList.end(); ++it, index++ )
+    {
+        itemSizeHints[ index ] = ( *it )->sizeHint();
+    }
+
+    isDirty = false;
+}
+
+/*!
+  \param parent Parent widget
+  \param margin Margin
+  \param spacing Spacing
+*/
+
+QwtDynGridLayout::QwtDynGridLayout( QWidget *parent,
+        int margin, int spacing ):
+    QLayout( parent )
+{
+    init();
+
+    setSpacing( spacing );
+    setMargin( margin );
+}
+
+/*!
+  \param spacing Spacing
+*/
+
+QwtDynGridLayout::QwtDynGridLayout( int spacing )
+{
+    init();
+    setSpacing( spacing );
+}
+
+/*!
+  Initialize the layout with default values.
+*/
+void QwtDynGridLayout::init()
+{
+    d_data = new QwtDynGridLayout::PrivateData;
+    d_data->maxCols = d_data->numRows = d_data->numCols = 0;
+    d_data->expanding = 0;
+}
+
+//! Destructor
+
+QwtDynGridLayout::~QwtDynGridLayout()
+{
+    for ( int i = 0; i < d_data->itemList.size(); i++ )
+        delete d_data->itemList[i];
+
+    delete d_data;
+}
+
+//! Invalidate all internal caches
+void QwtDynGridLayout::invalidate()
+{
+    d_data->isDirty = true;
+    QLayout::invalidate();
+}
+
+/*!
+  Limit the number of columns.
+  \param maxCols upper limit, 0 means unlimited
+  \sa maxCols()
+*/
+void QwtDynGridLayout::setMaxCols( uint maxCols )
+{
+    d_data->maxCols = maxCols;
+}
+
+/*!
+  Return the upper limit for the number of columns.
+  0 means unlimited, what is the default.
+  \sa setMaxCols()
+*/
+
+uint QwtDynGridLayout::maxCols() const
+{
+    return d_data->maxCols;
+}
+
+//! Adds item to the next free position.
+
+void QwtDynGridLayout::addItem( QLayoutItem *item )
+{
+    d_data->itemList.append( item );
+    invalidate();
+}
+
+/*!
+  \return true if this layout is empty.
+*/
+
+bool QwtDynGridLayout::isEmpty() const
+{
+    return d_data->itemList.isEmpty();
+}
+
+/*!
+  \return number of layout items
+*/
+
+uint QwtDynGridLayout::itemCount() const
+{
+    return d_data->itemList.count();
+}
+
+/*!
+  Find the item at a spcific index
+
+  \param index Index
+  \sa takeAt()
+*/
+QLayoutItem *QwtDynGridLayout::itemAt( int index ) const
+{
+    if ( index < 0 || index >= d_data->itemList.count() )
+        return NULL;
+
+    return d_data->itemList.at( index );
+}
+
+/*!
+  Find the item at a spcific index and remove it from the layout
+
+  \param index Index
+  \sa itemAt()
+*/
+QLayoutItem *QwtDynGridLayout::takeAt( int index )
+{
+    if ( index < 0 || index >= d_data->itemList.count() )
+        return NULL;
+
+    d_data->isDirty = true;
+    return d_data->itemList.takeAt( index );
+}
+
+//! \return Number of items in the layout
+int QwtDynGridLayout::count() const
+{
+    return d_data->itemList.count();
+}
+
+/*!
+  Set whether this layout can make use of more space than sizeHint().
+  A value of Qt::Vertical or Qt::Horizontal means that it wants to grow in only
+  one dimension, while Qt::Vertical | Qt::Horizontal means that it wants
+  to grow in both dimensions. The default value is 0.
+
+  \param expanding Or'd orientations
+  \sa expandingDirections()
+*/
+void QwtDynGridLayout::setExpandingDirections( Qt::Orientations expanding )
+{
+    d_data->expanding = expanding;
+}
+
+/*!
+  Returns whether this layout can make use of more space than sizeHint().
+  A value of Qt::Vertical or Qt::Horizontal means that it wants to grow in only
+  one dimension, while Qt::Vertical | Qt::Horizontal means that it wants
+  to grow in both dimensions.
+  \sa setExpandingDirections()
+*/
+Qt::Orientations QwtDynGridLayout::expandingDirections() const
+{
+    return d_data->expanding;
+}
+
+/*!
+  Reorganizes columns and rows and resizes managed widgets within
+  the rectangle rect.
+
+  \param rect Layout geometry
+*/
+void QwtDynGridLayout::setGeometry( const QRect &rect )
+{
+    QLayout::setGeometry( rect );
+
+    if ( isEmpty() )
+        return;
+
+    d_data->numCols = columnsForWidth( rect.width() );
+    d_data->numRows = itemCount() / d_data->numCols;
+    if ( itemCount() % d_data->numCols )
+        d_data->numRows++;
+
+    QList<QRect> itemGeometries = layoutItems( rect, d_data->numCols );
+
+    int index = 0;
+    for ( QList<QLayoutItem*>::iterator it = d_data->itemList.begin();
+        it != d_data->itemList.end(); ++it )
+    {
+        QWidget *w = ( *it )->widget();
+        if ( w )
+        {
+            w->setGeometry( itemGeometries[index] );
+            index++;
+        }
+    }
+}
+
+/*!
+  Calculate the number of columns for a given width. It tries to
+  use as many columns as possible (limited by maxCols())
+
+  \param width Available width for all columns
+  \sa maxCols(), setMaxCols()
+*/
+
+uint QwtDynGridLayout::columnsForWidth( int width ) const
+{
+    if ( isEmpty() )
+        return 0;
+
+    const int maxCols = ( d_data->maxCols > 0 ) ? d_data->maxCols : itemCount();
+    if ( maxRowWidth( maxCols ) <= width )
+        return maxCols;
+
+    for ( int numCols = 2; numCols <= maxCols; numCols++ )
+    {
+        const int rowWidth = maxRowWidth( numCols );
+        if ( rowWidth > width )
+            return numCols - 1;
+    }
+
+    return 1; // At least 1 column
+}
+
+/*!
+  Calculate the width of a layout for a given number of
+  columns.
+
+  \param numCols Given number of columns
+  \param itemWidth Array of the width hints for all items
+*/
+int QwtDynGridLayout::maxRowWidth( int numCols ) const
+{
+    int col;
+
+    QVector<int> colWidth( numCols );
+    for ( col = 0; col < ( int )numCols; col++ )
+        colWidth[col] = 0;
+
+    if ( d_data->isDirty )
+        d_data->updateLayoutCache();
+
+    for ( uint index = 0;
+        index < ( uint )d_data->itemSizeHints.count(); index++ )
+    {
+        col = index % numCols;
+        colWidth[col] = qMax( colWidth[col],
+            d_data->itemSizeHints[int( index )].width() );
+    }
+
+    int rowWidth = 2 * margin() + ( numCols - 1 ) * spacing();
+    for ( col = 0; col < ( int )numCols; col++ )
+        rowWidth += colWidth[col];
+
+    return rowWidth;
+}
+
+/*!
+  \return the maximum width of all layout items
+*/
+int QwtDynGridLayout::maxItemWidth() const
+{
+    if ( isEmpty() )
+        return 0;
+
+    if ( d_data->isDirty )
+        d_data->updateLayoutCache();
+
+    int w = 0;
+    for ( uint i = 0; i < ( uint )d_data->itemSizeHints.count(); i++ )
+    {
+        const int itemW = d_data->itemSizeHints[int( i )].width();
+        if ( itemW > w )
+            w = itemW;
+    }
+
+    return w;
+}
+
+/*!
+  Calculate the geometries of the layout items for a layout
+  with numCols columns and a given rect.
+
+  \param rect Rect where to place the items
+  \param numCols Number of columns
+  \return item geometries
+*/
+
+QList<QRect> QwtDynGridLayout::layoutItems( const QRect &rect,
+    uint numCols ) const
+{
+    QList<QRect> itemGeometries;
+    if ( numCols == 0 || isEmpty() )
+        return itemGeometries;
+
+    uint numRows = itemCount() / numCols;
+    if ( numRows % itemCount() )
+        numRows++;
+
+    QVector<int> rowHeight( numRows );
+    QVector<int> colWidth( numCols );
+
+    layoutGrid( numCols, rowHeight, colWidth );
+
+    bool expandH, expandV;
+    expandH = expandingDirections() & Qt::Horizontal;
+    expandV = expandingDirections() & Qt::Vertical;
+
+    if ( expandH || expandV )
+        stretchGrid( rect, numCols, rowHeight, colWidth );
+
+    const int maxCols = d_data->maxCols;
+    d_data->maxCols = numCols;
+    const QRect alignedRect = alignmentRect( rect );
+    d_data->maxCols = maxCols;
+
+    const int xOffset = expandH ? 0 : alignedRect.x();
+    const int yOffset = expandV ? 0 : alignedRect.y();
+
+    QVector<int> colX( numCols );
+    QVector<int> rowY( numRows );
+
+    const int xySpace = spacing();
+
+    rowY[0] = yOffset + margin();
+    for ( int r = 1; r < ( int )numRows; r++ )
+        rowY[r] = rowY[r-1] + rowHeight[r-1] + xySpace;
+
+    colX[0] = xOffset + margin();
+    for ( int c = 1; c < ( int )numCols; c++ )
+        colX[c] = colX[c-1] + colWidth[c-1] + xySpace;
+
+    const int itemCount = d_data->itemList.size();
+    for ( int i = 0; i < itemCount; i++ )
+    {
+        const int row = i / numCols;
+        const int col = i % numCols;
+
+        QRect itemGeometry( colX[col], rowY[row],
+            colWidth[col], rowHeight[row] );
+        itemGeometries.append( itemGeometry );
+    }
+
+    return itemGeometries;
+}
+
+
+/*!
+  Calculate the dimensions for the columns and rows for a grid
+  of numCols columns.
+
+  \param numCols Number of columns.
+  \param rowHeight Array where to fill in the calculated row heights.
+  \param colWidth Array where to fill in the calculated column widths.
+*/
+
+void QwtDynGridLayout::layoutGrid( uint numCols,
+    QVector<int>& rowHeight, QVector<int>& colWidth ) const
+{
+    if ( numCols <= 0 )
+        return;
+
+    if ( d_data->isDirty )
+        d_data->updateLayoutCache();
+
+    for ( uint index = 0;
+        index < ( uint )d_data->itemSizeHints.count(); index++ )
+    {
+        const int row = index / numCols;
+        const int col = index % numCols;
+
+        const QSize &size = d_data->itemSizeHints[int( index )];
+
+        rowHeight[row] = ( col == 0 )
+            ? size.height() : qMax( rowHeight[row], size.height() );
+        colWidth[col] = ( row == 0 )
+            ? size.width() : qMax( colWidth[col], size.width() );
+    }
+}
+
+/*!
+  \return true: QwtDynGridLayout implements heightForWidth.
+  \sa heightForWidth()
+*/
+bool QwtDynGridLayout::hasHeightForWidth() const
+{
+    return true;
+}
+
+/*!
+  \return The preferred height for this layout, given the width w.
+  \sa hasHeightForWidth()
+*/
+int QwtDynGridLayout::heightForWidth( int width ) const
+{
+    if ( isEmpty() )
+        return 0;
+
+    const uint numCols = columnsForWidth( width );
+    uint numRows = itemCount() / numCols;
+    if ( itemCount() % numCols )
+        numRows++;
+
+    QVector<int> rowHeight( numRows );
+    QVector<int> colWidth( numCols );
+
+    layoutGrid( numCols, rowHeight, colWidth );
+
+    int h = 2 * margin() + ( numRows - 1 ) * spacing();
+    for ( int row = 0; row < ( int )numRows; row++ )
+        h += rowHeight[row];
+
+    return h;
+}
+
+/*!
+  Stretch columns in case of expanding() & QSizePolicy::Horizontal and
+  rows in case of expanding() & QSizePolicy::Vertical to fill the entire
+  rect. Rows and columns are stretched with the same factor.
+
+  \sa setExpanding(), expanding()
+*/
+void QwtDynGridLayout::stretchGrid( const QRect &rect,
+    uint numCols, QVector<int>& rowHeight, QVector<int>& colWidth ) const
+{
+    if ( numCols == 0 || isEmpty() )
+        return;
+
+    bool expandH, expandV;
+    expandH = expandingDirections() & Qt::Horizontal;
+    expandV = expandingDirections() & Qt::Vertical;
+
+    if ( expandH )
+    {
+        int xDelta = rect.width() - 2 * margin() - ( numCols - 1 ) * spacing();
+        for ( int col = 0; col < ( int )numCols; col++ )
+            xDelta -= colWidth[col];
+
+        if ( xDelta > 0 )
+        {
+            for ( int col = 0; col < ( int )numCols; col++ )
+            {
+                const int space = xDelta / ( numCols - col );
+                colWidth[col] += space;
+                xDelta -= space;
+            }
+        }
+    }
+
+    if ( expandV )
+    {
+        uint numRows = itemCount() / numCols;
+        if ( itemCount() % numCols )
+            numRows++;
+
+        int yDelta = rect.height() - 2 * margin() - ( numRows - 1 ) * spacing();
+        for ( int row = 0; row < ( int )numRows; row++ )
+            yDelta -= rowHeight[row];
+
+        if ( yDelta > 0 )
+        {
+            for ( int row = 0; row < ( int )numRows; row++ )
+            {
+                const int space = yDelta / ( numRows - row );
+                rowHeight[row] += space;
+                yDelta -= space;
+            }
+        }
+    }
+}
+
+/*!
+   Return the size hint. If maxCols() > 0 it is the size for
+   a grid with maxCols() columns, otherwise it is the size for
+   a grid with only one row.
+
+   \sa maxCols(), setMaxCols()
+*/
+QSize QwtDynGridLayout::sizeHint() const
+{
+    if ( isEmpty() )
+        return QSize();
+
+    const uint numCols = ( d_data->maxCols > 0 ) ? d_data->maxCols : itemCount();
+    uint numRows = itemCount() / numCols;
+    if ( itemCount() % numCols )
+        numRows++;
+
+    QVector<int> rowHeight( numRows );
+    QVector<int> colWidth( numCols );
+
+    layoutGrid( numCols, rowHeight, colWidth );
+
+    int h = 2 * margin() + ( numRows - 1 ) * spacing();
+    for ( int row = 0; row < ( int )numRows; row++ )
+        h += rowHeight[row];
+
+    int w = 2 * margin() + ( numCols - 1 ) * spacing();
+    for ( int col = 0; col < ( int )numCols; col++ )
+        w += colWidth[col];
+
+    return QSize( w, h );
+}
+
+/*!
+  \return Number of rows of the current layout.
+  \sa numCols()
+  \warning The number of rows might change whenever the geometry changes
+*/
+uint QwtDynGridLayout::numRows() const
+{
+    return d_data->numRows;
+}
+
+/*!
+  \return Number of columns of the current layout.
+  \sa numRows()
+  \warning The number of columns might change whenever the geometry changes
+*/
+uint QwtDynGridLayout::numCols() const
+{
+    return d_data->numCols;
+}

+ 83 - 0
starpu-top/qwt/qwt_dyngrid_layout.h

@@ -0,0 +1,83 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#ifndef QWT_DYNGRID_LAYOUT_H
+#define QWT_DYNGRID_LAYOUT_H
+
+#include "qwt_global.h"
+#include <qlayout.h>
+#include <qsize.h>
+#include <qlist.h>
+
+/*!
+  \brief The QwtDynGridLayout class lays out widgets in a grid,
+         adjusting the number of columns and rows to the current size.
+
+  QwtDynGridLayout takes the space it gets, divides it up into rows and
+  columns, and puts each of the widgets it manages into the correct cell(s).
+  It lays out as many number of columns as possible (limited by maxCols()).
+*/
+
+class QWT_EXPORT QwtDynGridLayout : public QLayout
+{
+    Q_OBJECT
+public:
+    explicit QwtDynGridLayout( QWidget *, int margin = 0, int space = -1 );
+    explicit QwtDynGridLayout( int space = -1 );
+
+    virtual ~QwtDynGridLayout();
+
+    virtual void invalidate();
+
+    void setMaxCols( uint maxCols );
+    uint maxCols() const;
+
+    uint numRows () const;
+    uint numCols () const;
+
+    virtual void addItem( QLayoutItem * );
+
+    virtual QLayoutItem *itemAt( int index ) const;
+    virtual QLayoutItem *takeAt( int index );
+    virtual int count() const;
+
+    void setExpandingDirections( Qt::Orientations );
+    virtual Qt::Orientations expandingDirections() const;
+    QList<QRect> layoutItems( const QRect &, uint numCols ) const;
+
+    virtual int maxItemWidth() const;
+
+    virtual void setGeometry( const QRect &rect );
+
+    virtual bool hasHeightForWidth() const;
+    virtual int heightForWidth( int ) const;
+
+    virtual QSize sizeHint() const;
+
+    virtual bool isEmpty() const;
+    uint itemCount() const;
+
+    virtual uint columnsForWidth( int width ) const;
+
+protected:
+
+    void layoutGrid( uint numCols,
+        QVector<int>& rowHeight, QVector<int>& colWidth ) const;
+    void stretchGrid( const QRect &rect, uint numCols,
+        QVector<int>& rowHeight, QVector<int>& colWidth ) const;
+
+private:
+    void init();
+    int maxRowWidth( int numCols ) const;
+
+    class PrivateData;
+    PrivateData *d_data;
+};
+
+#endif

+ 46 - 0
starpu-top/qwt/qwt_global.h

@@ -0,0 +1,46 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#ifndef QWT_GLOBAL_H
+#define QWT_GLOBAL_H
+
+#include <qglobal.h>
+
+// QWT_VERSION is (major << 16) + (minor << 8) + patch.
+
+#define QWT_VERSION       0x060000
+#define QWT_VERSION_STR   "6.0.0-svn"
+
+#if defined(Q_WS_WIN) || defined(Q_WS_S60)
+
+#if defined(_MSC_VER) /* MSVC Compiler */
+/* template-class specialization 'identifier' is already instantiated */
+#pragma warning(disable: 4660)
+#endif // _MSC_VER
+
+#ifdef QWT_DLL
+
+#if defined(QWT_MAKEDLL)     // create a Qwt DLL library 
+#define QWT_EXPORT  __declspec(dllexport)
+#define QWT_TEMPLATEDLL
+#else                        // use a Qwt DLL library
+#define QWT_EXPORT  __declspec(dllimport)
+#endif
+
+#endif // QWT_DLL
+
+#endif // Q_WS_WIN || Q_WS_S60
+
+#ifndef QWT_EXPORT
+#define QWT_EXPORT
+#endif
+
+// #define QWT_NO_COMPAT 1 // disable withdrawn functionality
+
+#endif 

+ 334 - 0
starpu-top/qwt/qwt_interval.cpp

@@ -0,0 +1,334 @@
+/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
+ * Qwt Widget Library
+ * Copyright (C) 1997   Josef Wilgen
+ * Copyright (C) 2002   Uwe Rathmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the Qwt License, Version 1.0
+ *****************************************************************************/
+
+#include "qwt_interval.h"
+#include "qwt_math.h"
+#include <qalgorithms.h>
+
+/*!
+   \brief Normalize the limits of the interval
+
+   If maxValue() < minValue() the limits will be inverted.
+   \return Normalized interval
+
+   \sa isValid(), inverted()
+*/
+QwtInterval QwtInterval::normalized() const
+{
+    if ( d_minValue > d_maxValue )
+    {
+        return inverted();
+    }
+    if ( d_minValue == d_maxValue && d_borderFlags == ExcludeMinimum )
+    {
+        return inverted();
+    }
+
+    return *this;
+}
+
+/*!
+   Invert the limits of the interval
+   \return Inverted interval
+   \sa normalized()
+*/
+QwtInterval QwtInterval::inverted() const
+{
+    int borderFlags = 0;
+    if ( d_borderFlags & ExcludeMinimum )
+        borderFlags |= ExcludeMaximum;
+    if ( d_borderFlags & ExcludeMaximum )
+        borderFlags |= ExcludeMinimum;
+
+    return QwtInterval( d_maxValue, d_minValue, borderFlags );
+}
+
+/*!
+  Test if a value is inside an interval
+
+  \param value Value
+  \return true, if value >= minValue() && value <= maxValue()
+*/
+bool QwtInterval::contains( double value ) const
+{
+    if ( !isValid() )
+        return false;
+
+    if ( value < d_minValue || value > d_maxValue )
+        return false;
+
+    if ( value == d_minValue && d_borderFlags & ExcludeMinimum )
+        return false;
+
+    if ( value == d_maxValue && d_borderFlags & ExcludeMaximum )
+        return false;
+
+    return true;
+}
+
+//! Unite 2 intervals
+QwtInterval QwtInterval::unite( const QwtInterval &other ) const
+{
+    /*
+     If one of the intervals is invalid return the other one.
+     If both are invalid return an invalid default interval
+     */
+    if ( !isValid() )
+    {
+        if ( !other.isValid() )
+            return QwtInterval();
+        else
+            return other;
+    }
+    if ( !other.isValid() )
+        return *this;
+
+    QwtInterval united;
+    int flags = 0;
+
+    // minimum
+    if ( d_minValue < other.minValue() )
+    {
+        united.setMinValue( d_minValue );
+        flags &= d_borderFlags & ExcludeMinimum;
+    }
+    else if ( other.minValue() < d_minValue )
+    {
+        united.setMinValue( other.minValue() );
+        flags &= other.borderFlags() & ExcludeMinimum;
+    }
+    else // d_minValue == other.minValue()
+    {
+        united.setMinValue( d_minValue );
+        flags &= ( d_borderFlags & other.borderFlags() ) & ExcludeMinimum;
+    }
+
+    // maximum
+    if ( d_maxValue > other.maxValue() )
+    {
+        united.setMaxValue( d_maxValue );
+        flags &= d_borderFlags & ExcludeMaximum;
+    }
+    else if ( other.maxValue() > d_maxValue )
+    {
+        united.setMaxValue( other.maxValue() );
+        flags &= other.borderFlags() & ExcludeMaximum;
+    }
+    else // d_maxValue == other.maxValue() )
+    {
+        united.setMaxValue( d_maxValue );
+        flags &= d_borderFlags & other.borderFlags() & ExcludeMaximum;
+    }
+
+    united.setBorderFlags( flags );
+    return united;
+}
+
+//! Intersect 2 intervals
+QwtInterval QwtInterval::intersect( const QwtInterval &other ) const
+{
+    if ( !other.isValid() || !isValid() )
+        return QwtInterval();
+
+    QwtInterval i1 = *this;
+    QwtInterval i2 = other;
+
+    // swap i1/i2, so that the minimum of i1
+    // is smaller then the minimum of i2
+
+    if ( i1.minValue() > i2.minValue() )
+    {
+        qSwap( i1, i2 );
+    }
+    else if ( i1.minValue() == i2.minValue() )
+    {
+        if ( i1.borderFlags() & ExcludeMinimum )
+            qSwap( i1, i2 );
+    }
+
+    if ( i1.maxValue() < i2.minValue() )
+    {
+        return QwtInterval();
+    }
+
+    if ( i1.maxValue() == i2.minValue() )
+    {
+        if ( i1.borderFlags() & ExcludeMaximum ||
+            i2.borderFlags() & ExcludeMinimum )
+        {
+            return QwtInterval();
+        }
+    }
+
+    QwtInterval intersected;
+    int flags = 0;
+
+    intersected.setMinValue( i2.minValue() );
+    flags |= i2.borderFlags() & ExcludeMinimum;
+
+    if ( i1.maxValue() < i2.maxValue() )
+    {
+        intersected.setMaxValue( i1.maxValue() );
+        flags |= i1.borderFlags() & ExcludeMaximum;
+    }
+    else if ( i2.maxValue() < i1.maxValue() )
+    {
+        intersected.setMaxValue( i2.maxValue() );
+        flags |= i2.borderFlags() & ExcludeMaximum;
+    }
+    else // i1.maxValue() == i2.maxValue()
+    {
+        intersected.setMaxValue( i1.maxValue() );
+        flags |= i1.borderFlags() & i2.borderFlags() & ExcludeMaximum;
+    }
+
+    intersected.setBorderFlags( flags );
+    return intersected;
+}
+
+//! Unites this interval with the given interval.
+QwtInterval& QwtInterval::operator|=( const QwtInterval & interval )
+{
+    *this = *this | interval;
+    return *this;
+}
+
+//! Intersects this interval with the given interval.
+QwtInterval& QwtInterval::operator&=( const QwtInterval & interval )
+{
+    *this = *this & interval;
+    return *this;
+}
+
+/*!
+   Test if two intervals overlap
+*/
+bool QwtInterval::intersects( const QwtInterval &other ) const
+{
+    if ( !isValid() || !other.isValid() )
+        return false;
+
+    QwtInterval i1 = *this;
+    QwtInterval i2 = other;
+
+    // swap i1/i2, so that the minimum of i1
+    // is smaller then the minimum of i2
+
+    if ( i1.minValue() > i2.minValue() )
+    {
+        qSwap( i1, i2 );
+    }
+    else if ( i1.minValue() == i2.minValue() &&
+              i1.borderFlags() & ExcludeMinimum )
+    {
+        qSwap( i1, i2 );
+    }
+
+    if ( i1.maxValue() > i2.minValue() )
+    {
+        return true;
+    }
+    if ( i1.maxValue() == i2.minValue() )
+    {
+        return !( ( i1.borderFlags() & ExcludeMaximum ) ||
+            ( i2.borderFlags() & ExcludeMinimum ) );
+    }
+    return false;
+}
+
+/*!
+   Adjust the limit that is closer to value, so that value becomes
+   the center of the interval.
+
+   \param value Center
+   \return Interval with value as center
+*/
+QwtInterval QwtInterval::symmetrize( double value ) const
+{
+    if ( !isValid() )
+        return *this;
+
+    const double delta =
+        qMax( qAbs( value - d_maxValue ), qAbs( value - d_minValue ) );
+
+    return QwtInterval( value - delta, value + delta );
+}
+
+/*!
+   Limit the interval, keeping the border modes
+
+   \param lowerBound Lower limit
+   \param upperBound Upper limit
+
+   \return Limited interval
+*/
+QwtInterval QwtInterval::limited( double lowerBound, double upperBound ) const
+{
+    if ( !isValid() || lowerBound > upperBound )
+        return QwtInterval();
+
+    double minValue = qMax( d_minValue, lowerBound );
+    minValue = qMin( minValue, upperBound );
+
+    double maxValue = qMax( d_maxValue, lowerBound );
+    maxValue = qMin( maxValue, upperBound );
+
+    return QwtInterval( minValue, maxValue, d_borderFlags );
+}
+
+/*!
+   Extend the interval
+
+   If value is below minValue, value becomes the lower limit.
+   If value is above maxValue, value becomes the upper limit.
+
+   extend has no effect for invalid intervals
+
+   \param value Value
+   \sa isValid()
+*/
+QwtInterval QwtInterval::extend( double value ) const
+{
+    if ( !isValid() )
+        return *this;
+
+    return QwtInterval( qMin( value, d_minValue ),
+        qMax( value, d_maxValue ), d_borderFlags );
+}
+
+/*!
+   Extend an interval
+
+   \param value Value
+   \return Reference of the extended interval
+
+   \sa extend()
+*/
+QwtInterval& QwtInterval::operator|=( double value )
+{
+    *this = *this | value;
+    return *this;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+
+QDebug operator<<( QDebug debug, const QwtInterval &interval )
+{
+    const int flags = interval.borderFlags();
+
+    debug.nospace() << "QwtInterval("
+        << ( ( flags & QwtInterval::ExcludeMinimum ) ? "]" : "[" )
+        << interval.minValue() << "," << interval.maxValue()
+        << ( ( flags & QwtInterval::ExcludeMaximum ) ? "[" : "]" )
+        << ")";
+
+    return debug.space();
+}
+
+#endif

+ 0 - 0
starpu-top/qwt/qwt_interval.h


Some files were not shown because too many files changed in this diff