Sunday, February 22, 2009

Qt's aboutToShow() signal: Did we find a bug?

While converting the wxWidgets code to Qt, I realized something. A QMenu's "aboutToShow()" signal is triggered around 30 TIMES whenever you open that menu. So my menu refreshing routines will be called that many times.

The question is: How to work around it?

Update (Feb 23, 2009, 19:35): Alexandru wrote a sample application, and surprisingly for me, the application does NOT trigger the aboutToShow() signal a lot of times per menu, but rather, only once. Which means only one thing:

The bug's mine. Now I need to check out what went wrong.

Update (Feb 23, 2009, 19:43): I see now what happened. The function I used to automate the connection creation was recursive, but I added the aboutToShow() connections on that same function, which, obviously, got called a lot of times.

I moved the aboutToShow connections elsewhere, and problem solved :)

Alexandru gets a trust point for helping me fix this bug. Yay!

Thursday, February 19, 2009

Mom's feeling better, and progress has been made!

Good news people!

The first, is that my mom is feeling better :). She's under treatment and the fever is gone. In a month we'll see how her kidney is doing.

The second good news, is that the event handling code has been finished and the Welcome dialog is functional (but still ugly).

The one-month goal for the Qt4 conversion deadline now seems possible. Stay tuned.

Sunday, February 15, 2009

Alexandru's video demo.

Alexandru sent me a demo of filling an area of the screen with a determinate pattern of pixels. I modified his demo a bit so it would display random pixels, and so I could find out which bits corresponded to which color.

After a while, here's what I got:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>

/*demo took from a saya example*/
void fill_image(char *data, int w, int h, int bpp) {
int x, y;

char *adr;
for (y=0; y<h; y++) {
for (x=0; x<w; x++) {
adr = data + (y * w + x) * bpp;

unsigned long pixel;
// if(!(x % 10)) {
// pixel = 0xFFFF0000;
// } else if (x & 1) {
// pixel = 0xFF00FF00;
// } else {
// pixel = 0XFFFFFFFF;
// }
unsigned int r = rand() & 255;
unsigned int g = rand() & 255;
unsigned int b = rand() & 255;
pixel = (b << 24) | (g << 16) | r << 8;

*adr = pixel>>24;
*(adr + 1) = pixel>>16;
*(adr + 2) = pixel>>8;
*(adr + 3) = pixel;
}
}
}

void clear_image(char *data, int w, int h, int bpp) {
memset(data, 0xFF, w * h * bpp);
}


int main() {
Display *m_display;
Window m_window;
GC m_gc;
Visual *m_visual;
int m_screen;
unsigned int m_width;
unsigned int m_height;
unsigned int m_x;
unsigned int m_y;

XImage *image;

XEvent event;

XSizeHints hints;
XSetWindowAttributes attributes;

int format;
int offset;
char *data;
int bitmap_pad;
int bytes_per_line;

unsigned int depth;
int bpp;


if ((m_display = XOpenDisplay((char *)0)) == NULL) {
printf("cant open x connection\n");
return -1;
}
m_screen = XDefaultScreen(m_display);

m_visual = DefaultVisual(m_display, m_screen);

depth = XDefaultDepth(m_display, m_screen);

/*list supported depth for demo purposes*/
int count_return;
int *depths = XListDepths(m_display, m_screen, &count_return);
if (depths) {
int i;
printf("supported depths:\n");
for (i=0; i<count_return; i++) {
if (depths[i] == depth) {
printf("%d [default]\n", depths[i]);
} else {
printf("%d\n", depths[i]);
}
}

XFree(depths);
}

/*list pixmap formats for demo purposes*/
XPixmapFormatValues defaultPixmapFormat;
XPixmapFormatValues *pixmapFormats = XListPixmapFormats(m_display, &count_return);
if (pixmapFormats) {
int i;
for (i=0; i<count_return; i++) {
printf("depth: %d\n", (pixmapFormats + i)->depth);
printf("bits_per_pixel: %d\n", (pixmapFormats + i)->bits_per_pixel);
printf("scanline_pad: %d\n\n", (pixmapFormats + i)->scanline_pad);
if (depth == (pixmapFormats + i)->depth) {
memcpy(&defaultPixmapFormat, pixmapFormats + i, sizeof(XPixmapFormatValues));
}
}

XFree(pixmapFormats);

bpp = defaultPixmapFormat.bits_per_pixel / 8;
}

m_width = 200;
m_height = 100;
m_x = 500;
m_y = 500;

attributes.event_mask = ExposureMask | KeyPressMask;
attributes.background_pixel = BlackPixel(m_display, m_screen);

/*depth 32 doesnt work !!*/
m_window = XCreateWindow(m_display, XDefaultRootWindow(m_display), m_x, m_y,
m_width, m_height, 0, depth, InputOutput, m_visual, CWEventMask | CWBackPixel, &attributes);

if (!m_window) {
printf("error creating window\n");
XCloseDisplay(m_display);
return -1;
}

/*set size hints for window*/
hints.min_width = hints.max_width = m_width;
hints.min_height = hints.max_height = m_height;
hints.flags = PSize | PMinSize | PMaxSize;
XSetWMNormalHints(m_display, m_window, &hints);

/*set windows title*/
XStoreName(m_display, m_window, "X11 Saya");

/*create graphic context*/
m_gc = XCreateGC(m_display, m_window, 0, NULL);

/*display the window*/
XMapWindow(m_display, m_window);

offset = 0;

/*alloc data buffer for storing image*/
if ((data = (char *) malloc(m_width * m_height * bpp)) == NULL) {
printf("error malloc");
//free x structures
return -1;
}
memset(data, 0, m_width * m_height * bpp);


bitmap_pad = 32;
bytes_per_line = m_width * bpp;

image = XCreateImage(m_display, m_visual, depth, ZPixmap, offset, data, m_width, m_height,
bitmap_pad, bytes_per_line);

if (image == NULL) {
printf("error creating image\n");
free(data);
return -1;
}

int step = 1;
while (1) {
XNextEvent(m_display, &event);
if (event.type == Expose) {
// printf("expose\n");
XClearWindow(m_display, m_window);
// if (step % 2 == 0) {
// clear_image(data, m_width, m_height, bpp);
// } else {
fill_image(data, m_width, m_height, bpp);
// }
XPutImage(m_display, m_window, m_gc, image, 0, 0, 0, 0, m_width, m_height);
} else if (event.type == KeyPress) {
/*size up the image*/

m_width += step*5;
m_height += step*5;

XDestroyImage(image);

data = (char *) malloc(m_width * m_height * bpp);
image = XCreateImage(m_display, m_visual, depth, ZPixmap, offset, data, m_width, m_height,
bitmap_pad, 0);
if (image == NULL) {
printf("error creating image\n");
free(data);
return -1;
}

XResizeWindow(m_display, m_window, m_width, m_height);

step++;
if (step == 10)
break;
}
}


XDestroyImage(image);

XFreeGC(m_display, m_gc);

if (m_window) {
XDestroyWindow(m_display, m_window);
}
if (m_display) {
XCloseDisplay(m_display);
}

return 0;
}


And here's the result:

[x11.png]

With some more effort, we'll be able to reproduce a computer-generated video in realtime. At least in X11, the windows driver will use other code. Thanks a lot, Alexandru! Keep up the good work!

Saturday, February 14, 2009

Mother's ill...

My mother got a kidney stone, and until she gets the stone removed I'll have to help her do the dialy chores, so I guess I won't have free time to work on Saya for the next 2 or 3 weeks.

Sorry guys. I'll keep in touch.

Wednesday, February 4, 2009

My books finally arrived!

Herb Stutter: Exceptional C++

and

Hughes & Hughes: Professional Multicore Programming.

Yay!

Monday, February 2, 2009

Programmer's block

I hate it when this happens. The conversion to Qt might seem easy at a glance, but then you realize there's so much to do, and don't even know where to start.

The worst part is that I had the whole day to program, and I couldn't do anything (well, I updated the website). What a waste.

Anyway, finally I realized I should leave the main frame for the end, when the rest of the functionality is ported. So I'll start to work on the welcome dialog. Let's hope I can do that this week.

Sigh.