hitcounter
dpointer
Sunday, December 24, 2006
 
Which color role?

Are you sometimes confused which one of QPalette::Background or QPalette::Base you need to use? Look no more, using this small utility shown below, you can find the exact RGB of each color role of the default widget. This is how it looks like (left: Linux, right: Windows):

And here is the code. You can compile it with:

g++ -o qpal qpal.cpp -I/usr/include/QtGui -L/usr/lib -lQtGui

or create a simple pro file (you know how to this, don't you?

/* QPAL - show colors for the palette

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

 */

#include <QtGui>

int main(int argc, char** argv)
{
 QApplication app(argc, argv);

 QWidget w;
 w.setWindowTitle("QPAL - Palette Viewer");
 QGridLayout layout;
 w.setLayout(&layout);

 QPalette palette;
 palette = w.palette();

 const char* roleNames[] =
 {
  "Window",
  "Background",
  "WindowText",
  "Foreground",
  "Base",
  "AlternateBase",
  "Text",
  "Button",
  "ButtonText",
  "BrightText",
  "",
  "Light",
  "Midlight",
  "Dark",
  "Mid",
  "Shadow",
  "",
  "Highlight",
  "HighlightedText",
  "",
  "Link",
  "LinkVisited"
 };

 const char* groupNames[] = 
 {
  "Active",
  "Inactive",
  "Disabled"
 };

 QPalette::ColorRole roles[] = 
 {
  QPalette::Window,
  QPalette::Background,
  QPalette::WindowText,
  QPalette::Foreground,
  QPalette::Base,
  QPalette::AlternateBase,
  QPalette::Text,
  QPalette::Button,
  QPalette::ButtonText,
  QPalette::BrightText,
  QPalette::Window, // separator
  QPalette::Light,
  QPalette::Midlight,
  QPalette::Dark,
  QPalette::Mid,
  QPalette::Shadow,
  QPalette::Window, // separator
  QPalette::Highlight,
  QPalette::HighlightedText,
  QPalette::Window, // separator
  QPalette::Link,
  QPalette::LinkVisited
 };

 QPalette::ColorGroup groups[] = 
 {
  QPalette::Active,
  QPalette::Inactive,
  QPalette::Disabled
 };

 QLabel* label;
 QLabel* sample;
 QLabel* red;
 QLabel* green;
 QLabel* blue;
 QColor color;

 label = new QLabel(&w);
 label->setText("<b>ROLE</b>");
 layout.addWidget(label, 0, 0);
 for(int k = 0; k < 3; k++)
 {
  layout.addItem(new QSpacerItem(50,10), 0, 1 + k*5);
  label = new QLabel(&w);
  label->setText(QLatin1String(groupNames[k]));
  layout.addWidget(label, 0, 2 + k*5, 1, 4);
 }

 for(int i = 0; i < 19+3; i++)
 {
  QString name = QLatin1String(roleNames[i]);
  label = new QLabel(&w);
  label->setText(name);
  layout.addWidget(label, i+1, 0);
  if(!name.isEmpty())
  for(int j = 0; j < 3; j++)
  {
   color = palette.brush(groups[j], roles[i]).color();
   sample = new QLabel(&w);
   sample->setAutoFillBackground(true);
   QPalette special = sample->palette();
   special.setColor(QPalette::Background, color);
   sample->setPalette(special);
   sample->setFrameShape(QFrame::Box);
   sample->setFixedSize(12, 12);
   red = new QLabel(&w);
   red->setText(QString::number(color.red()));
   red->setAlignment(Qt::AlignRight);
   green = new QLabel(&w);
   green->setText(QString::number(color.green()));
   green->setAlignment(Qt::AlignRight);
   blue = new QLabel(&w);
   blue->setText(QString::number(color.blue()));
   blue->setAlignment(Qt::AlignRight);
   layout.addWidget(sample, i+1, 2 + j*5);
   layout.addWidget(red, i+1, 3 + j*5);
   layout.addWidget(green, i+1, 4 + j*5);
   layout.addWidget(blue, i+1, 5 + j*5);
  }
 }

 w.show();
 return app.exec();
}

Wednesday, October 11, 2006
 
soc 2006 t-shirt

soc 2006 t-shirt


Wednesday, September 13, 2006
 
Underwater effect

Basic idea: shift the pixel in horizontal and vertical direction sinusoidally.

Here it is assumed that buffer is the off-screen buffer (will be copied to the video buffer), width and height hold the dimension of the buffer. tick is the time variable, in this example it is taken using SDL_GetTicks function. Divide by 4 causes the oscillation period to be 4 seconds. Bonus for readers who figure out why it is masked with 1023 instead of modulo 1000.

In real-world, these calculations are expensive and thus should be helped with some look-up tables, at least for the sine function. Everything will look simpler.

 unsigned char* ptr = buffer;
 int amp = width/64;
 const int tick = (SDL_GetTicks()/4) & 1023;
 for(int yi = 0; yi < height; yi++, ptr+= width)
 {
  int shift = amp/2 + amp/2*sin((4*yi/(double)height + tick/(double)1024)*2*M_PI);
  memmove(ptr+shift, ptr, width-shift);
 }
 for(int xi = 0; xi < width; xi++)
 {
  int shift = amp/2 + amp/2*sin((4*xi/(double)width + tick/(double)1024)*2*M_PI);
  ptr = buffer + xi + (height-1)*width;
  for(int c = 0; c < height-shift; c++, ptr -= width)
   *ptr = *(ptr-shift*width);
 }

underwater effect

Update: here is the screencast.


Monday, November 21, 2005
 
Simple Unzip

How to extract files from a ZIP file? Simple. The code fragment below shows how to do it. You need to have zlib for the decompression routine and minizip for the actual ZIP-compatible implementation. Note that minizip package already contains a full implementation of unzip, called mini-unzip, yet the function presented here is simpler to understand and to modify.

To compile, you need to link to libzlib and few files from minizip (unzip.c and ioapi.c, also iowin32.c in Windows). The function is self-explained, it will extract filename inside the zipfile (must be a valid ZIP) and write it to outfile. If outfile already exists, it will be overwritten. Note that error handling is minimal to make the code readable.

This code is BSD licensed.

#include "unzip.h"

#define UNZIP_OK 0
#define UNZIP_ERROPEN 1
#define UNZIP_ERRNOTFOUND 2
#define UNZIP_ERRCREATE 3
#define UNZIP_ERRREAD 4
#define UNZIP_ERRWRITE 5

int unzipFile( char* zipfile, char* filename, char* outfile )
{
  unzFile uf = 0;
  FILE* fout = 0;
  int result, bytes;
  char buffer[1024];

  uf = unzOpen( zipfile );
  if( !uf )
  {
    printf( "Can not open file '%s' !\n", zipfile );
    return UNZIP_ERROPEN;
  }

  if( unzLocateFile( uf, filename, 0 ) != UNZ_OK )
  {
    printf( "Can not find '%s' inside the zipfile !\n", filename );
    unzCloseCurrentFile(uf);
    return UNZIP_ERRNOTFOUND;
  }
  
  if( unzOpenCurrentFile( uf) != UNZ_OK )
  {
    printf( "Can not open '%s' inside the zipfile !\n", filename );
    unzCloseCurrentFile(uf);
    return UNZIP_ERRNOTFOUND;
  }

  fout = fopen( outfile,"wb" );
  if( !fout )
  {
    printf( "Can not create file '%s' !\n", outfile );
    unzCloseCurrentFile(uf);
    return UNZIP_ERRCREATE;
  }

  result = UNZIP_OK;
  for(;;)
  {
    bytes = unzReadCurrentFile( uf, buffer, sizeof(buffer) );
    if( bytes == 0 ) break; /* finish */
    if( bytes < 0 )
    {
      printf( "Error reading %s %d!\n", filename, bytes );
      result = UNZIP_ERRREAD;
      break;
    }
    else
      if( fwrite( buffer, 1, bytes, fout )!= bytes )
      {
        printf("error in writing extracted file\n");
        result = UNZIP_ERRWRITE;
        break;
      }
  }
  
  fclose( fout );
  unzCloseCurrentFile( uf );

  return result;
}

Thursday, July 14, 2005
 
Logging to String

It it easier for later troubleshooting if your classes have logging facility, or at least a special member function used to dump their state. Since we might not want to dump always to screen, a logical declaration would be:

void FooBar::dump( std::ostream& out ) const

since we can call it with instance->dump( std::cout ) and it will output to screen.

Suppose there are many instances of different classes, they are arranged in a tree, and we want to call all those dump. Would be easier to trace if the output is arranged also like a tree, i.e. with different indentation to mark different depth level:

Root
(dump output of root class)

      Container 1
      (dump output of the above container)

      Container 2
      (dump output of the above container)

           Node A
          (dump output of this node)


      Container 3
      (dump output of the above container)

The key here is to know the level of the instance and prepend its debug output with proper number of whitespaces. Assuming you have created the spaces already for certain depth level (how to do it is left as an exercise!), then call the dump function not to screen (std::cout), but to a local buffer instead and later on add some spaces.

  std::ostringstream t;
  instance->dump( t );
  std::string d = t.str();
  std::cout << spaces;
  for( unsigned i = 0; i < d.size(); i++ )
    if( d[i] != '\n' )
      std::cout << d[i];    
    else
      std::cout << std::endl << spaces;

The trick here is the use of std::ostringstream (so do no forget to include sstream) to allow dumping to a string buffer, than manipulate the buffer so that spaces (of course needs to be constructed beforehand) is outputted at the beginning and after each end-of-line.


Thursday, June 02, 2005
 
FreeVCS (Win32) for Easy Version Control

Developers of open-source project are normally very familiar with the use of version control, e.g. CVS which is quite popular. If you code in Win32 platform, source code management software is either not free (sometimes very expensive) or difficult to setup. Look no more, should you need basic features of version control: check in, check out, history, and diff/merge, then you can use FreeVCS (now being open-sourced as JediVCS).

FreeVCS has a nice integration with Delphi IDE. However, if you do not use Delphi IDE, you can still opt for the stand alone version. Here are steps to get your feet wet quickly:

First, download the client and install. Assuming you do not work with Delphi, get fvcs_exe221.zip, extract it to temporary folder, and run the installer. In short time, the stand-alone FreeVCS Project Manager is ready.

Now you need a simple server. This is still necessary even if you work alone and use only one computer, due the server-client characteristic of FreeVCS. Select the easiest DBISAM server. Get dbisam109srv.zip and extract the content.

Next you have to prepare the repository. Choose a folder for the repository. Take file dbiarch.zip which you get from the previous step, extract the content to your repository folder.

The server, FVCSAppSrv.exe, you should get when you extract dbisam109srv.zip beforehand. Copy this file, along ServerCrypt.dll to your repository folder. Run the exe file now to start FreeVCS server

Download the manual. Print it or just read it on the screen.

Now launch the FreeVCS Project Manager, connect to the server, create a new project, and start importing your files. You are ready to rock!


Thursday, February 24, 2005
 
OpenWatcom (and STLport)

The Watcom family of compilers always amazed me. First time I faced it years ago, when I was about to help my uncle debugging his program (this was WATFOR 77). Although Fortran was never my soul, it has ever caught my attention thanks to its wonderful features. Years after, knowing that DOOM was built using Watcom C/C++ compiler, I could imagine what kind of luxury it would offer; due to the fact that I have to live either with Borland C++ and/on DJGPP only.

When Watcom compilers became open-source, I was very exciting to try it out. But only lately I had time to examine it in details. OpenWatcom - that is the new name - is available from www.openwatcom.org. Unfortunately AFAIK the IDE has been ported to Linux yet, and the Windows version still resembles the look-and-feel for legacy Windows 3.1 application. But it works, and it works well.

I almost can not live without STL nowadays. Sadly the latest STLport still do not build with OpenWatcom. After searching around (WATCOM C/C++ Programmer's FAQ is highly recommended), I tried STLport modification from Peter Chapin's OpenWatcom page and it worked flawlessly.

The steps to install STLport follows. This assumes that you have downloaded the above mentioned STLport package for OpenWatcom.

Copy stlport subdirectory to your Watcom installation, e.g. to C:\Watcom

In file setvars.bat, modify the INCLUDE variable so that it becomes something like:

SET INCLUDE=C:\watcom\stlport;C:\watcom\H;C:\watcom\H\NT

Then you can start compiling your program that uses STL.

If, however, you use the IDE, then your project must have the stlport path before Watcom include files; else you will face billions of error messages. Use menu Sources, Source Options, C++ Compiler Switches to manage it.

Note: Seems that Peter Chapin's fixes for STLport are only for the 32-bit target platform (e.g. Win32). I am still trying to figure out how to modify this STLport so that I can also target DOS 32-bit.



Powered by Blogger