Import upstream version 0.99.2
[fmit.git] / src / modules / GLStatistics.cpp
1 // Copyright 2007 "Gilles Degottex"
2
3 // This file is part of "fmit"
4
5 // "fmit" is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // "fmit" is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19 #include "GLStatistics.h"
20
21 static const unsigned char g_icon_statistics[] = {
22         0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
23         0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20,
24         0x08, 0x06, 0x00, 0x00, 0x00, 0x73, 0x7a, 0x7a, 0xf4, 0x00, 0x00, 0x06,
25         0xc4, 0x49, 0x44, 0x41, 0x54, 0x58, 0x85, 0xb5, 0x97, 0x6d, 0x4c, 0x5b,
26         0xd7, 0x19, 0xc7, 0x7f, 0xf7, 0x5e, 0x1b, 0x1b, 0xdb, 0x04, 0x6c, 0x63,
27         0xc0, 0xe1, 0xd5, 0x04, 0x92, 0x40, 0x63, 0x9c, 0x89, 0xac, 0x1f, 0x12,
28         0xa1, 0x69, 0x5a, 0x84, 0x14, 0x05, 0x91, 0x69, 0x5a, 0xaa, 0x54, 0x51,
29         0x42, 0xb6, 0x26, 0x43, 0x8b, 0xca, 0x40, 0xcd, 0x3e, 0xa4, 0xca, 0xa2,
30         0x4a, 0x45, 0xcd, 0xb4, 0x2f, 0xec, 0x43, 0x22, 0xa5, 0x48, 0x93, 0x26,
31         0x2d, 0x9b, 0x54, 0x6d, 0x51, 0xa3, 0xd2, 0xa8, 0xeb, 0xa6, 0xee, 0x25,
32         0xb3, 0x50, 0xa7, 0x89, 0xa5, 0x84, 0xb2, 0x26, 0x59, 0x49, 0x00, 0x63,
33         0x9b, 0xf2, 0x6e, 0xe3, 0x6b, 0x83, 0x5f, 0xef, 0x3e, 0xf8, 0x05, 0x1b,
34         0x9b, 0x8e, 0x6d, 0xda, 0x23, 0x1d, 0x9d, 0x73, 0x8f, 0xce, 0x39, 0xff,
35         0xdf, 0xf3, 0x9c, 0x97, 0x7b, 0x8e, 0xc0, 0xff, 0xc1, 0x3a, 0xba, 0x7b,
36         0xb5, 0x40, 0x15, 0x60, 0x06, 0xca, 0x80, 0x35, 0xe0, 0x13, 0xe7, 0xc8,
37         0xb0, 0xb2, 0xbd, 0xad, 0xf0, 0x5f, 0x0c, 0x2e, 0x02, 0xd5, 0x80, 0x0d,
38         0x68, 0x00, 0xea, 0x80, 0x9a, 0x54, 0x5d, 0x4d, 0x2a, 0x99, 0x0b, 0x8c,
39         0x3d, 0x09, 0x9c, 0x72, 0x8e, 0x0c, 0x3f, 0xcf, 0xae, 0x54, 0xed, 0x20,
40         0x62, 0x04, 0x9a, 0x53, 0x22, 0xe9, 0xd4, 0x90, 0xca, 0xeb, 0x81, 0xa2,
41         0x9d, 0x00, 0x35, 0x45, 0x45, 0x18, 0xf4, 0xc5, 0xe8, 0xf5, 0xc5, 0x18,
42         0x74, 0xc5, 0x68, 0x8a, 0xd4, 0x3c, 0x7d, 0xe6, 0x22, 0xb4, 0xb1, 0x79,
43         0x08, 0x78, 0x0d, 0x78, 0xb5, 0x20, 0x40, 0x47, 0x77, 0xaf, 0x1e, 0xb8,
44         0x02, 0x9c, 0x4d, 0x89, 0x0b, 0x00, 0x92, 0x24, 0x52, 0x69, 0x31, 0x61,
45         0x31, 0x19, 0x29, 0x2b, 0x35, 0x50, 0x56, 0x5a, 0x82, 0xb1, 0xb4, 0x24,
46         0x93, 0x97, 0x96, 0x96, 0xa0, 0xd7, 0xeb, 0xd1, 0xe9, 0xf4, 0xa8, 0x35,
47         0x5a, 0xe2, 0x8a, 0x48, 0x38, 0x9a, 0x20, 0xa1, 0x80, 0x4a, 0x14, 0xa8,
48         0xb7, 0x68, 0xf8, 0xe0, 0x0f, 0xa3, 0xfc, 0xe4, 0xe6, 0x1d, 0x52, 0x0e,
49         0x90, 0x07, 0x90, 0x12, 0x1f, 0x05, 0x1c, 0xa2, 0x28, 0x72, 0xec, 0xab,
50         0x76, 0x8e, 0xbe, 0xd8, 0x46, 0x5b, 0x4b, 0x13, 0x55, 0x95, 0xe5, 0x44,
51         0xe3, 0x02, 0xa1, 0x70, 0x9c, 0x60, 0x38, 0x41, 0x28, 0x92, 0xe0, 0xaf,
52         0x1f, 0x7f, 0x8c, 0xae, 0xa2, 0x99, 0x88, 0x5a, 0xcf, 0x6c, 0x28, 0x41,
53         0x5c, 0x56, 0x50, 0x88, 0xa3, 0x28, 0x41, 0x14, 0x05, 0x14, 0x40, 0x51,
54         0x14, 0x14, 0x05, 0x4c, 0x25, 0x2a, 0xf6, 0x37, 0xd6, 0xa5, 0xf5, 0x6a,
55         0x0b, 0x02, 0x00, 0x97, 0x00, 0x87, 0x24, 0x8a, 0xdc, 0xfc, 0xf1, 0x0f,
56         0xd9, 0xdf, 0x64, 0x63, 0x66, 0x31, 0x8c, 0x6b, 0x3d, 0xca, 0xe3, 0x65,
57         0x99, 0x44, 0x42, 0x49, 0x0d, 0x9c, 0xcc, 0xff, 0xfc, 0xe0, 0x01, 0xdd,
58         0x67, 0x5a, 0x50, 0xa3, 0x20, 0x8a, 0x02, 0x82, 0x40, 0x96, 0x70, 0x56,
59         0xae, 0x80, 0xbc, 0x19, 0xc7, 0x64, 0xdc, 0x93, 0xd6, 0xdb, 0xd7, 0xd1,
60         0xdd, 0x2b, 0x64, 0x2f, 0xc6, 0x34, 0x40, 0x23, 0xc0, 0xc1, 0xe6, 0x7a,
61         0x0e, 0x34, 0xd9, 0x18, 0x7b, 0x2e, 0xb3, 0x19, 0x49, 0x86, 0x51, 0x12,
62         0x41, 0x14, 0x84, 0x9c, 0x81, 0xd5, 0x92, 0x84, 0x28, 0x24, 0x50, 0x49,
63         0xe9, 0x3a, 0x21, 0x23, 0x98, 0x1e, 0x39, 0xa1, 0x00, 0x0a, 0x84, 0x23,
64         0x0a, 0xd6, 0x8a, 0x3d, 0x68, 0x35, 0x45, 0x6c, 0x86, 0x23, 0x3a, 0x60,
65         0x2f, 0xe0, 0x49, 0x03, 0x88, 0xd9, 0x20, 0x55, 0x95, 0xe5, 0x78, 0xd7,
66         0x22, 0xc4, 0xe2, 0xc9, 0xf9, 0xcb, 0x24, 0x49, 0x40, 0x25, 0x91, 0x29,
67         0x1b, 0xcd, 0xe5, 0xc8, 0xbe, 0x95, 0x64, 0x7d, 0xa1, 0x36, 0xe2, 0x56,
68         0xff, 0x70, 0x2c, 0x81, 0x20, 0x08, 0xd4, 0xec, 0xad, 0x48, 0x6b, 0x1e,
69         0xc8, 0x9e, 0x02, 0x31, 0xfb, 0x43, 0xa7, 0xd5, 0x10, 0x8b, 0x2b, 0xc9,
70         0x81, 0x24, 0x61, 0x2b, 0x89, 0x59, 0xdf, 0xa2, 0x40, 0xd5, 0xde, 0x1a,
71         0x56, 0x97, 0x3c, 0x59, 0xc2, 0xdb, 0x20, 0xb2, 0xfa, 0x46, 0x63, 0xc9,
72         0x98, 0x34, 0xd4, 0x5a, 0xd3, 0x32, 0x2d, 0x85, 0x00, 0x22, 0x00, 0x5a,
73         0x4d, 0x51, 0xae, 0xb0, 0x54, 0x48, 0x40, 0xa0, 0xb6, 0xce, 0xc6, 0x17,
74         0x9e, 0x99, 0x2f, 0x6d, 0x93, 0x4e, 0xb1, 0x44, 0x12, 0xa0, 0xb1, 0x7e,
75         0x6f, 0x5a, 0xf3, 0x60, 0x21, 0x80, 0x75, 0x80, 0x78, 0x22, 0x81, 0x5a,
76         0x25, 0xe4, 0x86, 0xbf, 0x80, 0x97, 0xd5, 0x35, 0xb5, 0x78, 0x66, 0xa7,
77         0x08, 0xc9, 0xbe, 0xc2, 0x6d, 0x32, 0x09, 0xd4, 0x52, 0x52, 0xc2, 0x56,
78         0x57, 0xfd, 0xef, 0x01, 0x22, 0x91, 0x28, 0x45, 0x2a, 0x31, 0xcb, 0x03,
79         0xf2, 0x3c, 0xfb, 0xfc, 0xb3, 0x71, 0x2e, 0xbe, 0xf4, 0x75, 0xde, 0xf9,
80         0xf9, 0x2d, 0xbe, 0xfd, 0x0d, 0x3b, 0xaf, 0xbf, 0xfa, 0x32, 0xb2, 0x7f,
81         0x25, 0x77, 0x9a, 0x24, 0x81, 0xf2, 0x12, 0x15, 0x0e, 0x9b, 0x9e, 0x43,
82         0x75, 0xc5, 0x49, 0x80, 0xdd, 0x44, 0x20, 0x12, 0x8d, 0xa1, 0xfe, 0x92,
83         0x29, 0xf0, 0xb8, 0xa6, 0xf8, 0xc1, 0x2b, 0xdf, 0xa2, 0xe7, 0x52, 0x3f,
84         0xe7, 0xbf, 0x37, 0xc0, 0x47, 0x7f, 0x9b, 0xc6, 0xb6, 0xaf, 0x99, 0xfe,
85         0xef, 0x76, 0x13, 0x0d, 0x87, 0x50, 0x4b, 0x02, 0x95, 0x65, 0x6a, 0x0e,
86         0xdb, 0x74, 0xd8, 0xeb, 0x75, 0x98, 0x0c, 0x5b, 0x07, 0xad, 0xb5, 0xc2,
87         0x4c, 0xb1, 0x56, 0x03, 0x50, 0xdd, 0xd1, 0xdd, 0x5b, 0xb2, 0x1d, 0x60,
88         0x19, 0x20, 0x18, 0xdc, 0x48, 0x02, 0xe4, 0xac, 0xe4, 0x2d, 0xcf, 0xde,
89         0xfe, 0xe9, 0x5b, 0x5c, 0xb8, 0xd4, 0x47, 0xd7, 0x37, 0x5f, 0xc2, 0x58,
90         0x66, 0x24, 0x16, 0xdd, 0xe4, 0xb5, 0xd7, 0xdf, 0xa2, 0x69, 0x7f, 0x2b,
91         0xbf, 0x7c, 0xfb, 0x06, 0x8e, 0x06, 0x3d, 0x4d, 0x55, 0x5a, 0xf4, 0x1a,
92         0x29, 0xdb, 0x49, 0x42, 0xa1, 0x10, 0x82, 0x20, 0xd0, 0x50, 0x67, 0x85,
93         0xe4, 0x09, 0x7b, 0x70, 0x3b, 0xc0, 0x22, 0x80, 0x3f, 0x10, 0xdc, 0xd1,
94         0xfb, 0x68, 0x38, 0xc4, 0x83, 0x3f, 0x7e, 0xc8, 0xcb, 0xe7, 0x2e, 0xa2,
95         0x92, 0x04, 0x5a, 0xed, 0x0e, 0x9e, 0x3d, 0xfd, 0x14, 0x4b, 0xa9, 0x8a,
96         0x9f, 0x0d, 0xdf, 0xe4, 0xdd, 0x5f, 0xff, 0x8a, 0x79, 0x8f, 0x8b, 0x40,
97         0x20, 0x80, 0xdf, 0xef, 0xc7, 0xe7, 0xf3, 0x65, 0x92, 0x28, 0x8a, 0xa9,
98         0x85, 0x98, 0x59, 0x07, 0x2f, 0x6c, 0x07, 0x58, 0x02, 0x58, 0x97, 0x83,
99         0xa9, 0x79, 0x27, 0x0f, 0xe2, 0x9f, 0x8f, 0x27, 0xd8, 0xd7, 0x7c, 0x00,
100         0x93, 0xc9, 0x88, 0x4a, 0x12, 0x38, 0xdc, 0xf6, 0x02, 0x9f, 0x4f, 0x8c,
101         0xa2, 0x13, 0x42, 0x14, 0x6b, 0xd4, 0x9c, 0x3e, 0x7d, 0x9a, 0x5b, 0xb7,
102         0x6e, 0xa1, 0xd7, 0xeb, 0x29, 0x2d, 0x2d, 0xa5, 0xac, 0xac, 0x2c, 0x93,
103         0xb4, 0x5a, 0x2d, 0x00, 0xfb, 0xb6, 0x00, 0x0e, 0x15, 0x8e, 0x80, 0x5f,
104         0x46, 0x14, 0x84, 0xad, 0x69, 0xc8, 0xf2, 0xde, 0x3d, 0x3b, 0x8d, 0x41,
105         0x6f, 0x20, 0x24, 0xfb, 0xd0, 0x12, 0xa4, 0xc5, 0x56, 0x81, 0x28, 0x90,
106         0x11, 0xe9, 0xeb, 0xeb, 0xe3, 0xce, 0x9d, 0x3b, 0x78, 0x3c, 0x99, 0x43,
107         0x2e, 0xcf, 0x1a, 0x77, 0x02, 0x70, 0x8e, 0x0c, 0xaf, 0x01, 0x41, 0x7f,
108         0x40, 0xc6, 0xbf, 0x1e, 0x60, 0x23, 0xe0, 0x27, 0x28, 0xfb, 0x09, 0x06,
109         0x7c, 0xc8, 0xb2, 0x8f, 0xa2, 0x22, 0x35, 0xe6, 0x72, 0x33, 0x92, 0x24,
110         0xd0, 0x62, 0xab, 0xa4, 0xa6, 0xca, 0x9c, 0xf1, 0x2a, 0x6d, 0xad, 0xad,
111         0xad, 0x5c, 0xbd, 0x7a, 0x95, 0x93, 0x27, 0x4f, 0xb2, 0xba, 0xba, 0x5a,
112         0x18, 0xa0, 0x61, 0xe7, 0x08, 0x00, 0xb8, 0x01, 0x02, 0xf2, 0x06, 0x16,
113         0x8b, 0x19, 0xb3, 0xd9, 0x84, 0xc5, 0x6c, 0xa2, 0xdc, 0x64, 0x42, 0xaf,
114         0xd3, 0xf2, 0xa7, 0x8f, 0x7e, 0x4b, 0xe7, 0xf1, 0xe3, 0xa8, 0xa4, 0xad,
115         0x7b, 0x86, 0xc9, 0x64, 0xca, 0x11, 0x1b, 0x18, 0x18, 0xe0, 0xd4, 0xa9,
116         0x53, 0x1c, 0x3d, 0x7a, 0x94, 0xd1, 0xd1, 0xd1, 0x3c, 0x80, 0xb2, 0x3d,
117         0x06, 0xcc, 0xc6, 0x52, 0x48, 0xee, 0x04, 0x23, 0xe4, 0x5e, 0x48, 0xe6,
118         0x80, 0x03, 0x8b, 0x2b, 0x6b, 0x58, 0x2c, 0x96, 0xe4, 0x4f, 0x45, 0x49,
119         0xfe, 0x54, 0xbc, 0x5e, 0x0f, 0xef, 0xbd, 0xfb, 0x1b, 0x26, 0x27, 0x27,
120         0x73, 0x06, 0x3c, 0x72, 0xe4, 0x08, 0x63, 0x63, 0x63, 0x74, 0x76, 0x76,
121         0x66, 0xea, 0x06, 0x07, 0x07, 0xb1, 0xdb, 0xed, 0x9c, 0x39, 0x73, 0x86,
122         0xaa, 0xaa, 0x2a, 0x3a, 0x3b, 0x3b, 0xb9, 0x7e, 0xfd, 0x3a, 0x13, 0x13,
123         0x13, 0x8c, 0x8f, 0x8f, 0x53, 0x5f, 0x5b, 0xc9, 0xca, 0x9a, 0x3f, 0x1d,
124         0x05, 0x67, 0x76, 0x04, 0xe6, 0x00, 0x96, 0x96, 0xd7, 0x90, 0x44, 0x32,
125         0xdb, 0x10, 0x25, 0x4e, 0xdf, 0xf7, 0x5f, 0xa1, 0xbf, 0xbf, 0x1f, 0xab,
126         0xd5, 0x9a, 0x03, 0xd0, 0xde, 0xde, 0xce, 0xd8, 0xd8, 0x58, 0x4e, 0x9d,
127         0x2c, 0xcb, 0x54, 0x57, 0x57, 0x73, 0xe5, 0xca, 0x15, 0xec, 0x76, 0x3b,
128         0x5e, 0xaf, 0x97, 0xa1, 0xa1, 0x21, 0x16, 0x17, 0x17, 0xe9, 0xea, 0xea,
129         0xa2, 0xae, 0xba, 0x2a, 0xdd, 0xd4, 0xbe, 0x3d, 0x02, 0x6e, 0x80, 0xc5,
130         0xe5, 0x35, 0x44, 0x51, 0x40, 0x05, 0x2c, 0x2d, 0x2d, 0x73, 0xe9, 0xe2,
131         0x77, 0xd0, 0xeb, 0x74, 0x5c, 0xbb, 0x76, 0x2d, 0x2f, 0xa4, 0xe1, 0x70,
132         0x98, 0x27, 0x4f, 0x9e, 0x30, 0x34, 0x34, 0x84, 0xcf, 0xe7, 0x03, 0xc0,
133         0x60, 0x30, 0xe0, 0x70, 0x38, 0x38, 0x7b, 0xf6, 0x2c, 0x03, 0x03, 0x03,
134         0x79, 0x7d, 0x6a, 0xf6, 0x56, 0xa6, 0x8b, 0x87, 0x0b, 0x4d, 0x41, 0x12,
135         0x40, 0x80, 0x37, 0x07, 0xdf, 0xe4, 0xf6, 0xed, 0xdb, 0x9c, 0x3f, 0x7f,
136         0x8e, 0x1b, 0x37, 0x6e, 0xb0, 0xba, 0xba, 0xca, 0xc3, 0x87, 0x0f, 0x79,
137         0xf4, 0xe8, 0x11, 0xb2, 0x2c, 0x03, 0xc9, 0x1d, 0xa0, 0x28, 0x0a, 0x3d,
138         0x3d, 0x3d, 0x98, 0xcd, 0xe6, 0x3c, 0xb1, 0x42, 0x56, 0xbb, 0xf5, 0x5b,
139         0xfe, 0x4a, 0x41, 0x80, 0x85, 0xa5, 0x55, 0xbc, 0x5e, 0x2f, 0x82, 0x00,
140         0x17, 0x2e, 0xf4, 0xa0, 0xd1, 0x68, 0x18, 0x1c, 0x1c, 0xa4, 0xbc, 0xbc,
141         0x9c, 0xf6, 0xf6, 0x76, 0x2e, 0x5f, 0xbe, 0x8c, 0xc1, 0x60, 0xc8, 0x74,
142         0xba, 0x7b, 0xf7, 0x2e, 0x6e, 0xb7, 0x7b, 0xd7, 0x00, 0x16, 0xb3, 0x31,
143         0x5d, 0x6c, 0xeb, 0xe8, 0xee, 0xd5, 0x65, 0x03, 0xb8, 0x00, 0x66, 0xe6,
144         0xe6, 0xb9, 0x7f, 0xff, 0x3e, 0x27, 0x4e, 0x9c, 0xa0, 0xad, 0xad, 0x2d,
145         0x6f, 0xbb, 0x6d, 0xb7, 0x63, 0xc7, 0x8e, 0x71, 0xef, 0xde, 0x3d, 0x1c,
146         0x0e, 0xc7, 0xae, 0x00, 0x34, 0x1a, 0x75, 0xba, 0x58, 0x04, 0xd8, 0xb2,
147         0x01, 0x9e, 0x03, 0x89, 0x85, 0xa5, 0x55, 0xb1, 0xa7, 0xe7, 0x0d, 0x34,
148         0x9a, 0x1d, 0x6f, 0xde, 0x39, 0x66, 0xb5, 0x5a, 0x99, 0x9f, 0x9f, 0xdf,
149         0x55, 0xdb, 0x8d, 0xcd, 0x30, 0xf7, 0x7f, 0x9f, 0xb3, 0x3d, 0x7d, 0x19,
150         0x00, 0xe7, 0xc8, 0xf0, 0x66, 0x47, 0x77, 0xaf, 0x4b, 0x51, 0x94, 0x06,
151         0x97, 0x67, 0x81, 0xe6, 0xc6, 0xbc, 0x0b, 0xec, 0x7f, 0x64, 0x4b, 0x2b,
152         0x3e, 0xa6, 0xa6, 0xdd, 0x4c, 0x4d, 0xcf, 0x31, 0x35, 0xe3, 0x66, 0x6a,
153         0xda, 0x8d, 0x67, 0x7e, 0x91, 0x44, 0x22, 0x73, 0x1f, 0x7d, 0xdf, 0x39,
154         0x32, 0xec, 0xd9, 0xfe, 0x30, 0x79, 0x0c, 0x34, 0xcc, 0xce, 0xcd, 0xef,
155         0x1a, 0x20, 0x16, 0x8b, 0x63, 0x3f, 0x7c, 0x84, 0xf7, 0x7f, 0xe7, 0xc4,
156         0xe5, 0x5d, 0x48, 0x89, 0xba, 0xf1, 0xaf, 0xcb, 0x3b, 0x75, 0x99, 0x05,
157         0xee, 0x01, 0x6f, 0x40, 0xfe, 0xcb, 0xe8, 0xef, 0xc0, 0x89, 0xa7, 0xcf,
158         0x5c, 0x1c, 0xff, 0xda, 0x8b, 0x79, 0x3d, 0x03, 0x72, 0x28, 0x29, 0x30,
159         0x33, 0x97, 0x11, 0x9a, 0x99, 0x9b, 0x27, 0x1a, 0x8d, 0x15, 0x12, 0x4a,
160         0x00, 0xcf, 0x80, 0x4f, 0x81, 0x71, 0xe0, 0x13, 0x60, 0xcc, 0x39, 0x32,
161         0xfc, 0x45, 0x76, 0xa3, 0xed, 0x00, 0x0f, 0x80, 0x1f, 0xbd, 0xf7, 0xe1,
162         0x5f, 0xd0, 0x15, 0x6b, 0xd9, 0x53, 0xa2, 0x67, 0x65, 0xcd, 0xcf, 0xb4,
163         0xcb, 0xcb, 0xd4, 0xb4, 0x9b, 0x85, 0xa5, 0xc2, 0x67, 0x3c, 0xb0, 0x42,
164         0xf2, 0xed, 0x37, 0x91, 0x12, 0x9c, 0x00, 0x26, 0x9d, 0x23, 0xc3, 0xc1,
165         0x9d, 0x3a, 0xa4, 0x2d, 0xef, 0x71, 0xda, 0xd1, 0xdd, 0xfb, 0x0b, 0xe0,
166         0xdc, 0x0e, 0xed, 0x03, 0xc0, 0x67, 0x29, 0xb1, 0x7f, 0xa4, 0xf2, 0x49,
167         0xe7, 0xc8, 0xf0, 0xee, 0x56, 0x61, 0x01, 0x2b, 0xf4, 0x38, 0xed, 0x01,
168         0xde, 0x01, 0xba, 0x00, 0x43, 0x96, 0xe0, 0x24, 0x30, 0x5b, 0xe8, 0x89,
169         0xfd, 0xbf, 0xd8, 0xbf, 0x00, 0x33, 0x30, 0x7d, 0x18, 0x07, 0x61, 0x44,
170         0x81, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60,
171         0x82
172 };
173
174 #include <iostream>
175 #include <limits>
176 using namespace std;
177 #include <GL/glut.h>
178 #include <qtimer.h>
179 #include <qtooltip.h>
180 #include <qimage.h>
181 #include <qboxlayout.h>
182 #include <qwidgetaction.h>
183 #include <Music/Music.h>
184
185 void GLStatistics::AverageNote::init()
186 {
187         err_mean = 0.0;
188         err_std = 0.0;
189 }
190 GLStatistics::AverageNote::AverageNote()
191         : ht(-1000)
192 {
193         init();
194 }
195 GLStatistics::AverageNote::AverageNote(int h)
196         : ht(h)
197 {
198         init();
199 }
200 GLStatistics::AverageNote::AverageNote(int h, int num, int den)
201         : ht(h)
202 {
203         init();
204         factor = QString::number(num)+"/"+QString::number(den);
205 }
206 GLStatistics::AverageNote::AverageNote(int h, float cents)
207         : ht(h)
208 {
209         init();
210         factor = QString::number(cents);
211 }
212 QString GLStatistics::AverageNote::getName() const
213 {
214         return QString::fromStdString(Music::h2n(ht))+factor;
215 }
216 void GLStatistics::AverageNote::addErr(float err)
217 {
218         // mean estimation
219         if(!errs.empty())
220                 err_mean *= errs.size();
221         errs.push_back(err);
222         err_mean += err;
223         err_mean /= errs.size();
224
225         // standard deviation estimation
226         err_std = 0.0;
227         for(size_t i=0; i<errs.size(); i++)
228         {
229                 float de = errs[i]-err_mean;
230                 err_std += de*de;
231         }
232         if(errs.size()>1)
233         {
234                 err_std /= errs.size()-1;               // unbiased estimation of the variance
235                 err_std = sqrt(err_std);
236         }
237 }
238
239 void GLStatistics::addNote(int ht, float err)
240 {
241         m_current_ht = ht;
242
243         if(isHidden() && !setting_keep_hidden->isChecked())
244                 return;
245
246         if(ht<setting_scale_min->minimum() || ht>setting_scale_max->maximum())
247                 return;
248
249 //      cerr << "ht=" << ht << endl;
250
251         if(!setting_scale_auto->isChecked())
252         {
253                 resizeScale();
254
255                 // drop ht outside of scale
256                 if(ht<setting_scale_min->value() || ht>setting_scale_max->value())
257                         return;
258
259                 // add note
260                 m_avg_notes[ht-setting_scale_min->value()].addErr(err);
261         }
262         else
263         {
264                 if(m_avg_notes.empty())
265                 {
266                         m_avg_notes.resize(1);
267                         m_avg_notes[0] = AverageNote(ht);
268                         setting_scale_min->setValue(ht);
269                         setting_scale_max->setValue(ht);
270                 }
271                 else if(ht<setting_scale_min->value())
272                 {
273 //                      cerr << "min: ";
274                         int min_ht = ht;
275                         vector<AverageNote> avg_notes(setting_scale_max->value()-min_ht+1);
276                         for(int i=0; i<setting_scale_min->value()-min_ht; i++)
277                                 avg_notes[i].ht = min_ht+i;
278                         for(size_t i=0; i<m_avg_notes.size(); i++)
279                                 avg_notes[setting_scale_min->value()-min_ht+i] = m_avg_notes[i];
280                         m_avg_notes = avg_notes;
281                         setting_scale_min->setValue(ht);
282 /*                      for(size_t i=0; i<m_avg_notes.size(); i++)
283                                 cerr << m_avg_notes[i].ht << " ";
284                         cerr << "[" << setting_scale_min->value() << ":" << setting_scale_max->value() << "]" << endl;*/
285                 }
286                 else if(ht>setting_scale_max->value())
287                 {
288 //                      cerr << "max: ";
289                         int max_ht = ht;
290                         vector<AverageNote> avg_notes(max_ht-setting_scale_min->value()+1);
291                         for(size_t i=0; i<m_avg_notes.size(); i++)
292                                 avg_notes[i] = m_avg_notes[i];
293                         for(size_t i=m_avg_notes.size(); i<avg_notes.size(); i++)
294                                 avg_notes[i].ht = setting_scale_min->value()+i;
295                         m_avg_notes = avg_notes;
296                         setting_scale_max->setValue(ht);
297 /*                      for(size_t i=0; i<m_avg_notes.size(); i++)
298                                 cerr << m_avg_notes[i].ht << " ";
299                         cerr << "[" << setting_scale_min->value() << ":" << setting_scale_max->value() << "]" << endl;*/
300                 }
301
302 //              cerr << setting_scale_min->value()-ht << endl;
303
304                 m_avg_notes[ht-setting_scale_min->value()].addErr(err);
305         }
306 }
307 void GLStatistics::addNote(int ht, int num, int den, float err)
308 {
309         m_current_ht = ht;
310 }
311 void GLStatistics::addNote(int ht, float cents, float err)
312 {
313         m_current_ht = ht;
314 }
315
316 void GLStatistics::resizeScale()
317 {
318         if(setting_scale_auto->isChecked() || setting_scale_max->value()-setting_scale_min->value()+1<1)
319                 return;
320
321         if(m_avg_notes.size()==0 || m_avg_notes[0].ht!=setting_scale_min->value() || m_avg_notes[m_avg_notes.size()-1].ht!=setting_scale_max->value())
322         {
323                 vector<AverageNote> avg_notes(setting_scale_max->value()-setting_scale_min->value()+1);
324                 for(int i=0; i<int(m_avg_notes.size()); i++)
325                 {
326                         int in = i+m_avg_notes[0].ht-setting_scale_min->value();
327                         if(in>=0 && in<int(avg_notes.size()))
328                                 avg_notes[in] = m_avg_notes[i];
329                 }
330                 for(size_t i=0; i<avg_notes.size(); i++)
331                         avg_notes[i].ht = setting_scale_min->value()+i;
332                 m_avg_notes = avg_notes;
333         }
334 }
335
336 GLStatistics::GLStatistics(QWidget* parent)
337 : QGLWidget(parent)
338 , View(tr("Statistics"), this)
339 {
340         // settings
341         QPixmap img;
342         img.loadFromData(g_icon_statistics, sizeof(g_icon_statistics), "PNG");
343         setting_show->setIcon(QIcon(img));
344         setting_show->setChecked(false);
345         hide();
346
347         setting_reset = new QAction(tr("Reset statistics"), this);
348         setting_reset->setShortcut('r');
349         connect(setting_reset, SIGNAL(activated()), this, SLOT(reset()));
350         m_popup_menu.addAction(setting_reset);
351
352         setting_keep_hidden = new QAction(tr("Keep notes when hidden"), this);
353         setting_keep_hidden->setCheckable(true);
354         setting_keep_hidden->setChecked(false);
355         connect(setting_keep_hidden, SIGNAL(toggled(bool)), this, SLOT(update()));
356         m_popup_menu.addAction(setting_keep_hidden);
357
358         QHBoxLayout* keepActionLayout = new QHBoxLayout(&m_popup_menu);
359
360         QLabel* keepActionTitle = new QLabel(tr("Keep n values"), &m_popup_menu);
361         keepActionLayout->addWidget(keepActionTitle);
362
363         setting_keep_n_values = new QSpinBox(&m_popup_menu);
364         setting_keep_n_values->setObjectName("setting_keep_n_values");
365         setting_keep_n_values->setMinimum(1);
366         setting_keep_n_values->setMaximum(500);
367         setting_keep_n_values->setSingleStep(3);
368         setting_keep_n_values->setValue(100);
369         setting_keep_n_values->setToolTip(tr("Keep this number of values in the computation of the statistics"));
370         connect(setting_keep_n_values, SIGNAL(valueChanged(int)), this, SLOT(update()));
371         keepActionLayout->addWidget(setting_keep_n_values);
372
373         QWidget* keepActionWidget = new QWidget(&m_popup_menu);
374         keepActionWidget->setLayout(keepActionLayout);
375
376         QWidgetAction* keepAction = new QWidgetAction(&m_popup_menu);
377         keepAction->setDefaultWidget(keepActionWidget);
378         m_popup_menu.addAction(keepAction);
379
380         setting_keep_n_values->setEnabled(false);
381         s_settings->add(setting_keep_n_values);
382
383         setting_show_std = new QAction(tr("Show standard deviation"), this);
384         setting_show_std->setCheckable(true);
385         setting_show_std->setChecked(true);
386         connect(setting_show_std, SIGNAL(toggled(bool)), this, SLOT(update()));
387         m_popup_menu.addAction(setting_show_std);
388
389         setting_scale_auto = new QAction(tr("Scale auto"), this);
390         setting_scale_auto->setCheckable(true);
391         setting_scale_auto->setChecked(true);
392         setting_scale_auto->setEnabled(false);
393         connect(setting_scale_auto, SIGNAL(toggled(bool)), this, SLOT(update()));
394         m_popup_menu.addAction(setting_scale_auto);
395
396         QHBoxLayout* scaleMinActionLayout = new QHBoxLayout(&m_popup_menu);
397
398         QLabel* scaleMinActionTitle = new QLabel(tr("Scale min"), &m_popup_menu);
399         scaleMinActionLayout->addWidget(scaleMinActionTitle);
400
401         setting_scale_min = new QSpinBox(&m_popup_menu);
402         setting_scale_min->setObjectName("setting_scale_min");
403         setting_scale_min->setMinimum(-96);
404         setting_scale_min->setMaximum(96);
405         setting_scale_min->setSingleStep(6);
406         setting_scale_min->setValue(-12);
407         setting_scale_min->setToolTip(tr("Scale min value (in semi-tones)"));
408         connect(setting_scale_min, SIGNAL(valueChanged(int)), this, SLOT(update()));
409         scaleMinActionLayout->addWidget(setting_scale_min);
410
411         QWidget* scaleMinActionWidget = new QWidget(&m_popup_menu);
412         scaleMinActionWidget->setLayout(scaleMinActionLayout);
413
414         QWidgetAction* scaleMinAction = new QWidgetAction(&m_popup_menu);
415         scaleMinAction->setDefaultWidget(scaleMinActionWidget);
416         m_popup_menu.addAction(scaleMinAction);
417
418         setting_scale_min->setEnabled(false);
419         s_settings->add(setting_scale_min);
420         connect(setting_scale_auto, SIGNAL(toggled(bool)), setting_scale_min, SLOT(setDisabled(bool)));
421         connect(setting_scale_min, SIGNAL(valueChanged(int)), this, SLOT(resizeScale()));
422
423         QHBoxLayout* scaleMaxActionLayout = new QHBoxLayout(&m_popup_menu);
424
425         QLabel* scaleMaxActionTitle = new QLabel(tr("Scale max"), &m_popup_menu);
426         scaleMaxActionLayout->addWidget(scaleMaxActionTitle);
427
428         setting_scale_max = new QSpinBox(&m_popup_menu);
429         setting_scale_max->setObjectName("setting_scale_max");
430         setting_scale_max->setMinimum(-96);
431         setting_scale_max->setMaximum(96);
432         setting_scale_max->setSingleStep(6);
433         setting_scale_max->setValue(+12);
434         setting_scale_max->setToolTip(tr("Scale max value (in semi-tones)"));
435         connect(setting_scale_max, SIGNAL(valueChanged(int)), this, SLOT(update()));
436         scaleMaxActionLayout->addWidget(setting_scale_max);
437
438         QWidget* scaleMaxActionWidget = new QWidget(&m_popup_menu);
439         scaleMaxActionWidget->setLayout(scaleMaxActionLayout);
440
441         QWidgetAction* scaleMaxAction = new QWidgetAction(&m_popup_menu);
442         scaleMaxAction->setDefaultWidget(scaleMaxActionWidget);
443         m_popup_menu.addAction(scaleMaxAction);
444
445         setting_scale_max->setEnabled(false);
446         s_settings->add(setting_scale_max);
447         connect(setting_scale_auto, SIGNAL(toggled(bool)), setting_scale_max, SLOT(setDisabled(bool)));
448         connect(setting_scale_max, SIGNAL(valueChanged(int)), this, SLOT(resizeScale()));
449
450         setting_showTolerance = new QAction(tr("Show tolerance"), this);
451         setting_showTolerance->setCheckable(true);
452         setting_showTolerance->setChecked(true);
453         connect(setting_showTolerance, SIGNAL(toggled(bool)), this, SLOT(update()));
454         m_popup_menu.addAction(setting_showTolerance);
455
456         setting_useCents = new QAction(tr("Use cents"), this);
457         setting_useCents->setCheckable(true);
458         setting_useCents->setChecked(true);
459         connect(setting_useCents, SIGNAL(toggled(bool)), this, SLOT(update()));
460         m_popup_menu.addAction(setting_useCents);
461
462         QHBoxLayout* scaleActionLayout = new QHBoxLayout(&m_popup_menu);
463
464         QLabel* scaleActionTitle = new QLabel(tr("Scale range"), &m_popup_menu);
465         scaleActionLayout->addWidget(scaleActionTitle);
466
467         setting_spinScale = new QSpinBox(&m_popup_menu);
468         setting_spinScale->setMinimum(5);
469         setting_spinScale->setMaximum(50);
470         setting_spinScale->setSingleStep(1);
471         setting_spinScale->setValue(50);
472         setting_spinScale->setToolTip(tr("Scale range (in cents)"));
473         connect(setting_spinScale, SIGNAL(valueChanged(int)), this, SLOT(update()));
474         scaleActionLayout->addWidget(setting_spinScale);
475
476         QWidget* scaleActionWidget = new QWidget(&m_popup_menu);
477         scaleActionWidget->setLayout(scaleActionLayout);
478
479         QWidgetAction* scaleAction = new QWidgetAction(&m_popup_menu);
480         scaleAction->setDefaultWidget(scaleActionWidget);
481         m_popup_menu.addAction(scaleAction);
482 }
483
484 void GLStatistics::save()
485 {
486         s_settings->setValue("setting_keep_hidden", setting_keep_hidden->isChecked());
487         s_settings->setValue("setting_show_std", setting_show_std->isChecked());
488         s_settings->setValue("setting_scale_auto", setting_scale_auto->isChecked());
489 }
490 void GLStatistics::load()
491 {
492         setting_keep_hidden->setChecked(s_settings->value("setting_keep_hidden", setting_keep_hidden->isChecked()).toBool());
493         setting_show_std->setChecked(s_settings->value("setting_show_std", setting_show_std->isChecked()).toBool());
494         setting_scale_auto->setChecked(s_settings->value("setting_scale_auto", setting_scale_auto->isChecked()).toBool());
495 }
496 void GLStatistics::clearSettings()
497 {
498         s_settings->remove("setting_keep_hidden");
499         s_settings->remove("setting_show_std");
500         s_settings->remove("setting_scale_auto");
501 }
502
503 void GLStatistics::reset()
504 {
505         m_avg_notes.clear();
506         if(setting_scale_auto->isChecked())
507         {
508                 setting_scale_min->setValue(0);
509                 setting_scale_max->setValue(0);
510         }
511         resizeScale();
512         updateGL();
513 }
514
515 void GLStatistics::initializeGL()
516 {
517         // Set the clear color to black
518         glClearColor(1.0, 1.0, 1.0, 0.0);
519
520         // glShadeModel( GL_FLAT );
521         glShadeModel( GL_SMOOTH );
522
523         glLoadIdentity();
524 }
525
526 void GLStatistics::drawTicksCent(int r, int dx, int dy)
527 {
528         // only work within range that is a pure multiple of r
529         float range = int(setting_spinScale->value()/r)*r;
530
531         float scale = 50.0f/setting_spinScale->value();
532
533         if((height()-dy)*r/100.0f*scale>2)
534         {
535                 for(float i=-range; i<=range; i+=r)
536                 {
537                         int y = int((height()-dy)*i/100.0f*scale) + (height()-dy)/2 + dy;
538                         glVertex2i(dx,  y);
539                         glVertex2i(width(),  y);
540                 }
541         }
542 }
543 void GLStatistics::drawTextTickCent(int r, int dy)
544 {
545         // only work within range that is a pure multiple of r
546         int range = int(setting_spinScale->value()/r)*r;
547
548         float scale = 50.0f/setting_spinScale->value();
549         QString txt;
550         for(int i=-range; i<range; i+=r)
551         {
552                 txt = QString::number(i);
553                 if(i>=0) txt = QString("  ")+txt;
554                 if(i==0) txt = QString("  ")+txt;
555                 glRasterPos2i(2, int((height()-dy)*i/100.0f*scale) + (height()-dy)/2 + dy - 4);
556                 string str = txt.toStdString();
557                 for(size_t i=0; i<str.length(); i++)
558                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)str[i]);
559         }
560 }
561
562 void GLStatistics::paintGL()
563 {
564 //      cerr << "GLStatistics::paintGL " << m_notes.size() << endl;
565
566         glClear(GL_COLOR_BUFFER_BIT);
567
568         glLineWidth(1.0f);
569         float human_tol = Music::f2hf(441.0,440.0);
570         float scale;
571         if(setting_useCents->isChecked())
572                 scale = 50.0f/setting_spinScale->value();
573         else
574                 scale = int(50/setting_spinScale->value());
575
576         // name
577         string str = tr("Statistics").toStdString();
578         glColor3f(0.75,0.75,0.75);
579         glRasterPos2i(2, height()-20);
580         for(size_t i = 0; i < str.length(); i++)
581                 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, (unsigned char)str[i]);
582
583         int char_size = 9;
584         int ticks_size = 2+3*char_size;
585         int grid_width = width()-ticks_size;
586         int dy = char_size/2;
587         int legend_height = 40;
588         int grid_height = height()-legend_height;
589
590         // draw green rect
591         if(setting_showTolerance->isChecked())
592         {
593                 int green_ytop = int((scale*human_tol+0.5)*grid_height) + legend_height;
594                 int green_ybottom = int((-scale*human_tol+0.5)*grid_height) + legend_height;
595
596                 glBegin(GL_QUADS);
597                 glColor3f(168/256.0,221/256.0,182/256.0);
598                 glVertex2i(ticks_size, green_ytop);
599                 glVertex2i(ticks_size, green_ybottom);
600                 glVertex2i(width(), green_ybottom);
601                 glVertex2i(width(), green_ytop);
602                 glEnd();
603
604                 // draw green lines
605                 glBegin(GL_LINES);
606                 glColor3f(0.48,0.80,0.57);
607                 glVertex2i(ticks_size, green_ytop);
608                 glVertex2i(width(), green_ytop);
609                 glVertex2i(ticks_size, green_ybottom);
610                 glVertex2i(width(), green_ybottom);
611                 glEnd();
612         }
613
614         // std
615         if(setting_show_std->isChecked())
616         {
617                 glBegin(GL_QUADS);
618                 glLineWidth(1.0f);
619                 glColor3f(0.85, 0.85, 0.85);
620                 for(size_t i=0; i<m_avg_notes.size(); i++)
621                 {
622                         if(!m_avg_notes[i].errs.empty())
623                         {
624                                 int top = int((scale*(m_avg_notes[i].err_mean+m_avg_notes[i].err_std)+0.5)*grid_height) + legend_height;
625                                 top = max(top, legend_height);
626                                 int bottom = int((scale*(m_avg_notes[i].err_mean-m_avg_notes[i].err_std)+0.5)*grid_height) + legend_height;
627                                 bottom = max(bottom, legend_height);
628                                 int left = ticks_size+int(i*float(grid_width)/m_avg_notes.size())+1;
629                                 int right = ticks_size+int((i+1)*float(grid_width)/m_avg_notes.size());
630
631                                 glVertex2i(left, top);
632                                 glVertex2i(left, bottom);
633                                 glVertex2i(right, bottom);
634                                 glVertex2i(right, top);
635                         }
636                 }
637                 glEnd();
638         }
639
640         // horiz lines
641         if(setting_useCents->isChecked())
642         {
643                 glBegin(GL_LINES);
644                 float gray = 0.87;
645 //              glColor3f(gray, gray, gray);
646 //              drawTicksCent(1, ticks_size);
647                 gray = 0.875;
648                 glColor3f(gray, gray, gray);
649                 drawTicksCent(2, ticks_size, legend_height);
650                 gray = 0.75;
651                 glColor3f(gray, gray, gray);
652                 drawTicksCent(10, ticks_size, legend_height);
653                 glEnd();
654         }
655         else
656         {
657                 glBegin(GL_LINES);
658                         float gray = 0.5;
659                         glColor3f(gray, gray, gray);
660                         glVertex2i(ticks_size,  grid_height/2+legend_height);
661                         glVertex2i(width(),  grid_height/2+legend_height);
662                         gray = 0.75;
663                         glColor3f(gray, gray, gray);
664                         glVertex2i(ticks_size,  grid_height/4+legend_height);
665                         glVertex2i(width(),  grid_height/4+legend_height);
666                         glVertex2i(ticks_size,  3*grid_height/4+legend_height);
667                         glVertex2i(width(),  3*grid_height/4+legend_height);
668                         gray = 0.87;
669                         glColor3f(gray, gray, gray);
670                         glVertex2i(ticks_size,  grid_height/8+legend_height);
671                         glVertex2i(width(),  grid_height/8+legend_height);
672                         glVertex2i(ticks_size,  7*grid_height/8+legend_height);
673                         glVertex2i(width(),  7*grid_height/8+legend_height);
674                         glVertex2i(ticks_size,  3*grid_height/8+legend_height);
675                         glVertex2i(width(),  3*grid_height/8+legend_height);
676                         glVertex2i(ticks_size,  5*grid_height/8+legend_height);
677                         glVertex2i(width(),  5*grid_height/8+legend_height);
678                 glEnd();
679         }
680
681         // center line
682 //      glBegin(GL_LINES);
683 //      glColor3f(0,0,0);
684 //      glVertex2i(ticks_size, grid_height/2+legend_height);
685 //      glVertex2i(width(), grid_height/2+legend_height);
686 //      glEnd();
687
688         // text marks
689         float gray = 0.5;
690         glColor3f(gray, gray, gray);
691         if(setting_useCents->isChecked())
692         {
693                 int grad = 10;
694                 if(setting_spinScale->value() <= 25) grad=5;
695                 if(setting_spinScale->value() <= 10) grad=1;
696                 drawTextTickCent(grad, legend_height);
697         }
698         else
699         {
700                 string sfraq, sufraq;
701                 sufraq = string("1/")+QString::number(int(50/setting_spinScale->value())*2).toStdString();
702                 sfraq = string("+")+sufraq;
703                 glRasterPos2i(2, 3*grid_height/4-dy+legend_height);
704                 for(size_t i = 0; i < sfraq.size(); i++)
705                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)sfraq[i]);
706                 sfraq = string("-")+sufraq;
707                 glRasterPos2i(2, grid_height/4-dy+legend_height);
708                 for(size_t i = 0; i < sfraq.size(); i++)
709                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)sfraq[i]);
710
711                 sufraq = string("1/")+QString::number(int(50/setting_spinScale->value())*4).toStdString();
712                 sfraq = string("+")+sufraq;
713                 glRasterPos2i(2, 5*grid_height/8-dy+legend_height);
714                 for(size_t i = 0; i < sfraq.size(); i++)
715                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)sfraq[i]);
716                 sfraq = string("-")+sufraq;
717                 glRasterPos2i(2, 3*grid_height/8-dy+legend_height);
718                 for(size_t i = 0; i < sfraq.size(); i++)
719                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)sfraq[i]);
720         }
721
722         // vertical lines
723         glBegin(GL_LINES);
724         gray = 0.5;
725         glColor3f(gray, gray, gray);
726         for(size_t i=0; i<m_avg_notes.size(); i++)
727         {
728                 int x = ticks_size+int(i*float(grid_width)/m_avg_notes.size());
729                 glVertex2i(x, legend_height);
730                 glVertex2i(x, height());
731         }
732         glEnd();
733
734         // note names
735         glColor3f(0, 0, 1);
736         for(size_t i=0; i<m_avg_notes.size(); i++)
737         {
738                 string str = m_avg_notes[i].getName().toStdString();
739
740                 glRasterPos2f(ticks_size+(i+0.5)*float(grid_width)/m_avg_notes.size(), 2);
741
742                 for(size_t c=0; c<str.length(); c++)
743                         glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)str[c]);
744         }
745
746         // sizes
747         glColor3f(0, 0, 1);
748         for(size_t i=0; i<m_avg_notes.size(); i++)
749         {
750                 if(!m_avg_notes[i].errs.empty())
751                 {
752
753                         string str = QString::number(m_avg_notes[i].errs.size()).toStdString();
754
755                         glRasterPos2f(ticks_size+(i+0.5)*float(grid_width)/m_avg_notes.size(), 4+legend_height/2);
756
757                         for(size_t c=0; c<str.length(); c++)
758                                 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)str[c]);
759                 }
760         }
761
762         // means
763         glLineWidth(2.0f);
764         glBegin(GL_LINES);
765         glColor3f(0, 0, 0);
766         for(size_t i=0; i<m_avg_notes.size(); i++)
767         {
768                 if(!m_avg_notes[i].errs.empty())
769                 {
770                         int y = int((scale*(m_avg_notes[i].err_mean)+0.5)*grid_height) + legend_height;
771                         int left = ticks_size+int(i*float(grid_width)/m_avg_notes.size())+1;
772                         int right = ticks_size+int((i+1)*float(grid_width)/m_avg_notes.size());
773
774                         glVertex2i(left, y);
775                         glVertex2i(right, y);
776                 }
777         }
778         glEnd();
779
780         // Marks around current note
781         glBegin(GL_LINES);
782         gray = 0;
783         glColor3f(gray, gray, gray);
784         for(size_t i=0; i<m_avg_notes.size(); i++)
785         {
786                 if(m_avg_notes[i].ht==m_current_ht)
787                 {
788                         int x = ticks_size+int(i*float(grid_width)/m_avg_notes.size());
789                         glVertex2i(x, legend_height);
790                         glVertex2i(x, height());
791                         x = ticks_size+int((i+1)*float(grid_width)/m_avg_notes.size());
792                         glVertex2i(x, legend_height);
793                         glVertex2i(x, height());
794                 }
795         }
796         glEnd();
797
798         glFlush();
799 }
800
801 void GLStatistics::resizeGL( int w, int h )
802 {
803         // Set the new viewport size
804         glViewport(0, 0, (GLint)w, (GLint)h);
805
806         // Choose the projection matrix to be the matrix
807         // manipulated by the following calls
808         glMatrixMode(GL_PROJECTION);
809
810         // Set the projection matrix to be the identity matrix
811         glLoadIdentity();
812
813         // Define the dimensions of the Orthographic Viewing Volume
814         glOrtho(0.0, w, 0.0, h, 0.0, 1.0);
815
816         // Choose the modelview matrix to be the matrix
817         // manipulated by further calls
818         glMatrixMode(GL_MODELVIEW);
819 }