2009-11-27

Run OpenGL demos on Mini2440

Mini2440-Arm9 has no graphic hardware accelerator. In order to make opengl program run on it, I think we need do following things:

=======================
Install a crossing toolchain
=======================
  • Extract the package to root
>tar zxvf arm920t-eabi.tgz –C /
  • Export path of toolchains, run also add following line in /root/.bashrc
==================================
Cross-compile mesa library (openGL in Linux)
==================================
  • Download and unpack mesa libraries. See the tutorial here (http://www.mesa3d.org/)
  • You need to use arm-gcc instead of your host gcc to build the mesa library. Max just create a symbolic link refer to the arm-gcc, by
>ln -s /opt/toolchains/arm920t-eabi/bin/arm-linux-gcc /usr/bin/gcc
>cd ~/project/mesa/Mesa-7.5.1
>./configure --host=arm-linux --prefix=/usr/local/mesa
>make
>make install
  • Then, you can find the library and include files at /usr/local/mesa.
=======================
Copy the demo to target board
=======================
My mini2440 is remotely loaded by nfs network on my host machine. The root directory of mini2440 is located at /disk1/nfs/root/ on my host machine. Just copy some demo executables (you can find at for examples Mesa-7.5.1/progs/xdemos) to /disk1/nfs/root/. And start the demos by minicom. See the tutorial.

2009-11-25

OpenGL for Qt

OpenGL for qt-x11-opensource-src.
  • You have to install mesa, which is open source OpenGL library in Linux. Follow this thread: http://www.larsen-b.com/Article/231.html
  • When you configure your Qt-X11, you would see a text info like : "OpenGL support .... yes (Desktop)"
OpenGL for qt-embedded-linux-opensource-src

  • Embedded Qt doesn't support full OpenGL, instead, it supports OpenGL ES (OpenGL for embedded system), a subset of full OpenGL with a smaller, more constrained API. The most important to OpenGL ES is its header file (API) and specification, you can find them at www.khronos.org. There exist various opensource libraries implementing OpenGL ES. You can find more opensource implementations at http://www.khronos.org/developers/resources/opengles/.
OpegGL for Qtopia
  • Starting with the 4.2 release, Qtopia Core supports OpenGL ES (OpenGL for Embedded Systems). To be able to use the OpenGL API in Qtopia Core, it must be integrated with the Q Window System (QWS). This is done by providing an EGL implementation, i.e., a native platform window system interface.

Reference:

create a branch in SVN repository

  1. svn mkdir svn://svnhost:3690/SvnRepos/CokiQt/branch -m "create an branch"
  2. svn cp svn://svnhost:3690/SvnRepos/CokiQt/trunk svn://svnhost:3690/SvnRepos/CokiQt/branch/2009-11-22 -m "copy trunk to branch"

2009-11-12

Tango Icon


Tango is nice. It provides not only a set of fee beautiful icons, but also his own guideline for the icon artist. Not bad! You can use inkscape or gimp to create your own icon. Both of them are open source software. Tango provides also online video to show how to do it. Great!

Another good source of icons, classified in different categories:
http://www.iconarchive.com/category

2009-11-09

QTimer in QThread

Multithreaded programming is also a useful paradigm for performing time-consuming operations without freezing the user interface of an application. QThread is the easy-to-use class in Qt allow user to implement things in a sperated thread.

"As of Qt4, you can use QThread to start your own event loops. This might sound somewhat uninteresting at first, but it means you can have your own signals and slots outside the main thread."

In GUI applications, the main thread is also called the GUI thread because it's the only thread that is allowed to perform GUI-related operations. You can implement, for instance, of a algorithm executed in a blocking way, into a sperated thread. Therefore, your GUI will not be frozen during the execution of algorithm. Then connect the main thread and algorithm thread by signal and slots. Namely, you can now emit a signal in one thread and receive it in a slot in a different thread.

The following is a simple example, in which a second-timer is wrapped in a QThread and a QWidget in main thread can start and stop the timer in any time.

//-----------------------------
CookingClock.cpp in timer thread
//-----------------------------


CookingClock::CookingClock(QObject *parent )
:QThread( parent)
,iSeconds_(10)
,iSecondsAccu_(0)
{

timer_.setInterval(1000); //second timer
connect( &timer_, SIGNAL(timeout()), this, SLOT(countSeconds()));

QThread::start();
}
void CookingClock::run()
{
exec();
}
void CookingClock::countSeconds()
{
iSecondsAccu_++;
emit( secondTicked(iSeconds_ - iSecondsAccu_));

if(iSecondsAccu_>=iSeconds_)
{
emit( timeIsUp());
timer_.stop();
}
}
void CookingClock::stop()
{
if(timer_.isActive())
{
timer_.stop();
}
}
void CookingClock::start()
{
iSecondsAccu_ = 0;
timer_.start();
}



//-----------------------------
CookingClockWidget.cpp in main thread
//-----------------------------



CookingClockWidget::CookingClockWidget(QWidget *parent)
:QWidget(parent)
, clock_(0)
{
clock_ = new CookingClock_v2();
QPushButton* pButtonStart = new QPushButton("start");
QPushButton* pButtonStop = new QPushButton("stop");
connect( pButtonStart, SIGNAL(clicked()), clock_, SLOT(start()));
connect( pButtonStop, SIGNAL(clicked()), clock_, SLOT(stop()));
connect( clock_, SIGNAL(secondTicked(int)), this, SLOT(print(int)));
QHBoxLayout* pLayout = new QHBoxLayout;
pLayout->addWidget(pButtonStart);
pLayout->addWidget(pButtonStop);

setLayout(pLayout);
}
void CookingClockWidget::print( int second)
{
qDebug("second : %d", second);
}




Reference:

2009-11-03

Strip Error during 'make install'

...
arm-linux-strip: /disk1/nfs/mini2440/root_qtopia/usr/local/coki/db/createDB.sh: File format not recognized
make: [install_db] Error 1 (ignored)
...

Strip is the command in linux to remove the information for debug, e.g symbols and line number, from object files, thereby reducing file sizes and freeing disk space. It can greatly reduce the size:

259920 coki.stripped
354524 coki.notstripped

The reason of these troublesome error is obvious: 'make install' tried to strip some other files than binary executables. Actually you can just ignored these error. If you are some kind of perfectionist, see this thread for the solution.

2009-11-02

Qt embedded font

  • Which setFont() works?
For a Qt Widget, as long as no special font has been set, or after setFont(QFont()) is called, this is either a special font for the widget class, the parent's font or (if this widget is a top level widget), the default application font.

  • How to make font smooth?
To be continued..
  • How to deploy font ?
See the artical "Deploying Qt for Embedded Linux Applications" http://doc.trolltech.com/4.6/deployment.html

Reference:

2009-10-28

Sort all installed package by Size


dpkg-query -W --showformat='${Installed-Size;10}\t${Package}\n' | sort -k1,1n



dpkg-query --show --showformat='${Package;-50}\t${Installed-Size}\n' | sort -k 2 -n


source:

Adding a new disk to a VMWare Virtual Machine in Linux

Nice tutorial with snapshots:
Adding a new disk to a VMWare Virtual Machine in Linux

Svn Access through a Proxy

The Subversion client can go through a proxy, if you configure it to do so.

First, edit your servers configuration file to indicate which proxy to use. The file's location depends on your operating system. On Linux or Unix it is located in the directory ~/.subversion. On Windows it is in %APPDATA%\Subversion (try echo %APPDATA%, note this is a hidden directory).
Example: Edit the servers file and add something like at global session:
[global]
http-proxy-host = your.proxy.name
http-proxy-port = 3128
Check your internet browser setting, if you have only a proxy configuration, for example http://proxyconf.some.name. You can simply open this link using your browser and download the configuration script, I believe you can find the proxy server and the port.

Play OpenEmbedded

OpenEmbedded is
".. a framework from the first download of meta framework to the final system installation.. "

A comprehensive tutorial is OpenEmbedded Guide by Example. But in the time, OpenEmbedded uses git not monotone to download stuffs. But you'd better also read an updated version Setting up the toolchain and doing a build .

For users of VMplaer, which at default allocated only 8 G, you should notice that OpenEmbedded needs more than 10G space. Use VMware workstation, instead!

References:

2009-10-27

2009-10-26

Don't Forget Firewall for VMware Bridged Network

Max has a windows host and debian vm guest. In host-only and NAT vm network, everything fine. But if the vmware has a bridged network, host has no access the guest anymore. The basic differences between the three network configurations is briefly explain here. For example, putty. Don't forget add an exception to host firewall, in which your vmware workstation should not be blocked.

VMWare Network Modes

VMware has three kinds of network configurations:
  • Host-Only Networking: Principally, the virtual guest can only talk with host and has no access to outside. But, with help of proxy server, it is possible.
  • Network Address Translation (NAT) The guest can connect to a TCP/IP network using a Token Ring adapter on the host computer. The virtual machine does not have its own IP address on the external network. Instead, a separate private network is set up on the host computer.
  • Bridged Networking: Bridged mode lets the virtual machine share the host's Ethernet connection, while appearing as a separate machine with its own MAC and TCP/IP address.



References:
  1. VMware Networks, Bridged vs. Nat vs. Host
  2. Network address translation

2009-10-19

A Bach Script Adding File Description

Now Max has a small problem. He just read the code guideline of project and found that he forgot to add a pre-defined doxgen description for his source files. He has implemented more than 20 c++ classes in 5 directories. Never mind. The following bash scripts can help him. It includes
  • header.in
  • add-header.sh
  • add-header-dir.sh
Usage cannot be simpler.
  • add-header-dir.sh ${codedir}
The followings are the scripts:

header.in(header info template)
/****************************************************************************
**
** file: [filename]
** author: [your name]
** date: [date goes here]
** summary: 
** Copyright (C) 2010 xxx GmbH and/or its subsidiary(-ies).
** All rights reserved.
**
****************************************************************************/

add-header.sh (add the header to single file)
if [ $# -ne 1 ]; then
echo "Usage: add-header.sh filename"
exit 1
fi

file=$1
# check if the header exists
firstline=`head -1 ${file}`

if [ "${firstline:0:2}" = "/*" ]; then
echo "header exists. do nothing."
else
# add header.in at the begin of the file
# and copy to a temp file
( cat header.in; cat ${file} ) > ${file}.new

# replace the [filename] by current file name
filename=`echo ${file}|sed "s,.*/\(.*\),\1,"`
sed -i "s#\[filename\]#$filename#g" ${file}.new

# replace the author name
author='Jingfeng Han'
sed -i "s#\[your name]#$author#g" ${file}.new

# replace the date
date=`date +"%y/%m/%d/"`
sed -i "s#\[date goes here]#$date#g" ${file}.new

# replace old file with the temp file
rm ${file}
mv ${file}.new ${file}
fi

exit 0

add-header-dir.sh (recursively add the header to all source in the fold)
find $1 -type f -iname "*.h" -o -iname "*.cpp" -o -iname "*.qml" | while read file; do
# display info
echo ${file} ...

# add header to the file
./add-header.sh ${file}
done
exit 0

Sed Tips

In sed, if a pattern can be included inside of single quotes, no variable will be extented. Exmple 1 and 2. In order to use value of a variable, the pattern need to be included by double quotes and use "#" instead of "/" for seperator. See example 3 and 4.
  1. sed -i 's/\[filename\]/myfile/g' ${file}.new------>succ.
  2. sed -i 's/\[filename\]/$file/g' ${file}.new------->variable is not extended.
  3. sed -i "s/\[filename\]/$file/g" ${file}.new------->fails( Unknown option to 's')
  4. sed -i "s#\[filename\]#$file#g" ${file}.new-------->succ.

2009-10-17

Reset SQL Statement in sqlite3

Reset all bindings on a prepared statement, reset all host parameters to NULL.

int sqlite3_clear_bindings(sqlite3_stmt*);

Reset a prepared statement object back to its initial state, ready to be re-executed.

int sqlite3_reset(sqlite3_stmt *pStmt);

2009-10-16

On Redrawing a Qt Widget

As a GUI deverloper, Max is always looking for a elegant way to dynamically determine the appearance of widgets.

For example, now we have a wonderful recipe software, which can allow user input the name and display its ingredient. I want to open a dialog to show the ingredients of a recipe, let's say IngredientDialog. According to the recipe name, program retrieves the associated ingredients from database in the background. Assume that each ingredients are displayed in a QLabel. Obviously, we don't know the number of ingredients until the moment to open the dialog.

Solution 1: Everytime create a completely new IngredientDialog. Actually, it isn't a bad idea. Clear, easy but may be slow, because you need to remove everytime the old IngredientDialog and create a new one, in which a number of QLabel objects are created according to current recipe.

Solution 2: IngredientDialog is created once. Everytime it is open, the IngredientDialog cleans up the old QLabels and creates a new collection of QLabel, the others widgets keep unchanged. Looks very efficient. But frequent delete and new operations may lead to a memory leak, especially if the widgets are complicated or are implemented from the third parts.

Solution 3: Let's return back to the old style of C: allocate all the required variables and memory at the beginning of function and avoid to reallocate memory afterwards. For this example, IngredientDialog create enough QLabels in its constructor, but dynamically determine it is shown or hiden when the dialog is opened.
Seldomly, if a speical recipe has even more ingredients, the more QLabels will be created, but it is really seldom.

Tips: for a frequrently redrawn widget, it is a good idea to perserve the pointers of every created widgets and layout. In such way, the widgets can be easily altered, relocated or deleted among the layouts.

2009-10-14

A Simple Qt SAX Parser

Qt Xml framework implements two kinds of xml parser: "SAX2" and "DOM level 2". The difference between these two parsers are summarized in this blob artical. A nice code example of Qt SAX2 is discussed in the "tagreader walkthrough".

The most important characteristic of SAX parser is that it traverses the entire xml tree only once, from top to bottom. There is no intermediate memory for the element nodes, as in DOM parser. Therefore, SAX parser is memory efficient but cannot traverse backwards.

How the SAX parser works? By serveral events and their event handlers:
  • startElement
  • endElement
  • characters



Here is an example of a Qt SAX parser, which is a subclass of QXmlDefaultHandler.


=========================================

<Items>

<Item>
<Material>all purpose flour, stir before measuring</Material>
<Mount Unit="cups">3</Mount>
</Item>

<Item>
<Material>1 1/2 teaspoons baking soda</Material>
</Item>

<Item>
<Material>1 1/2 teaspoons ground cinnamon</Material>
</Item>

<Item>
<Material>8 ounces unsalted butter</Material>
</Item>

</Items>


=========================================


#include <QtXml/qxml.h>
#include <QString>

static const char TAG_ITEM[] = "Item";
static const char TAG_MATERIAL[]= "Material";
static const char TAG_MOUNT[] = "Mount";

class MyParser : public QXmlDefaultHandler
{
public:
bool startElement( const QString & namespaceURI,
const QString & localName,
const QString & qName,
const QXmlAttributes & atts )
{

if( localName == TAG_ITEM) {}
else if( localName == TAG_MATERIAL ) {}
else if( localName == TAG_MOUNT ){}
else{return false;}

currElement_ = localName;
return true;
}
bool characters ( const QString& ch_in)
{
if( currElement_ == TAG_ITEM) {}
else if( currElement_ == TAG_MATERIAL ) {}
else if( currElement_ == TAG_MOUNT ){}
else{return false;}

return true;

}
bool endElement( const QString&, const QString& localName, const QString& )
{
if( localName == TAG_ITEM) {}
else if( localName == TAG_MATERIAL ) {}
else if( localName == TAG_MOUNT ){}
else{return false;}

currElement_ = localName;
return true;
}

private:
QString currElement_;

};

2009-10-12

Difference between SAX and DOM

SAX: Was developed to run the java programs especially.
DOM: Was developed by w3c consortium so that it is an open standard.

SAX: It uses a memory resident model.
DOM: The xml file is arranged as a tree.

SAX: Top to bottom traversing
DOM: Traverse in any direction.


SAX: We cant insert or delete a node
DOM: We can insert or delete nodes


SAX: Doesnt store the XML in memory.
DOM: Occupies more memory

reference:
http://www.geekinterview.com/question_details/12797
SAX examples

Replace and Find String Cross Multiple Files

> find . -name "*.php" -print | xargs sed -i 's/foo/bar/g'
> find . | xargs grep 'string'
> find . -name "*.cpp" -o -name "*.h" -print

reference:
Rushi's blog

2009-10-10

sqlite3. Binding Values To Prepared Statements

The basic use of sqlite3 c++ interface can be found here:
A simple but nice example can be found here.

Another very important and useful function is sqlite3_bind. Why do we need it?

Usually, though, it is not useful to evaluate exactly the same SQL statement more than once. More often, one wants to evalute similar statements. sqlite3_prepare_v2() can not only parse the state SQL statement, but also possible a SQL statement template, in which some parameters can be given later. The literals parameters are bound by the function sqlite3_bind. It is very flexible and efficient, because the SQL statement is need to be prepared only once and be used forever. In many SQL statements, the time needed to run sqlite3_prepare() equals or exceeds the time needed by sqlite3_step().

The following code is c++ class do a select sql operation, retrieving "File" according given "ID".

"select File from tb_image where ID=?1"

The parametrized SQL statement is prepared in constructor once using

SqlHandler::prepare_sql(const char* sql_in, sqlite3_stmt*& pStmt_in)

The image object can be retrieved with different id.

bool SqlHandler::getRecipeHeaderImage( const int& imageId_in, QImage& image_out)

//-----------------------Example Code---------------------


static const char SQL_SELECT_HEADERIMAGE[]= "select File from tb_image where ID=?1";

SqlHandler::SqlHandler()
:bIsDBAvailable_(false)
,db_(0)
,pStmtHeaderImage_(0)
{
// Open the database
sqlite3_open(COKI_DB_FILE, &db_);
if( SQLITE_OK!=sqlite3_errcode(db_) )
{
qCritical("DB error: fail to open db file.");
sqlite3_close(db_);
return;
}

//prepare the SQL statement for select header info
if(!prepare_sql(SQL_SELECT_HEADERINFO, pStmtHeaderInfo_))
{
return;
}
SqlHandler::~SqlHandler()
{
sqlite3_finalize(pStmtHeaderImage_);
sqlite3_close(db_);
}
bool SqlHandler::isDBAvailable()
{
return bIsDBAvailable_;
}
bool SqlHandler::getRecipeHeaderImage( const int& imageId_in,
QImage& image_out)
{
if(!isDBAvailable())
{
return false;
}

// add id into sql statement
int iReturnCode = sqlite3_bind_int( pStmtHeaderImage_, 1, imageId_in);
if(iReturnCode != SQLITE_OK)
{
qCritical("Error: sqlite3_bind_in fails for ImageId = %d",imageId_in);
return false;
}

QString strFileName = COKI_IMAGE_DIR;
//execute the statement
iReturnCode = sqlite3_step( pStmtHeaderImage_ );
switch (iReturnCode )
{
case SQLITE_DONE:
return false;
break;

case SQLITE_ROW:
//load image
strFileName.append ((const char*)sqlite3_column_text( pStmtHeaderImage_, 0));
image_out.load(strFileName);
return true;
break;

default:
return false;

}


}
bool SqlHandler::prepare_sql(const char* sql_in, sqlite3_stmt*& pStmt_in)
{
if(sqlite3_prepare_v2(db_, sql_in, -1, &pStmt_in, 0))
{
sqlite3_finalize(pStmt_in);
return false;
}
return true;

}

2009-10-07

An example to retreive colume from a sqlite3 db

The following example shows how to retrieve the colume info from sqlite3 by its c interface. Some basic information

  • DB: my.db
  • table: tb
  • COLUMNs: Name, Owner, Category, Duration, ID

Given record id. now I want to retrieve the other column info.

bool MyClass::initialize(int id_in)
{

sqlite3* db;
sqlite3_stmt * pSTmt;
int iReturnCode = 0;
bool bRet = true;

// Open the database
sqlite3_open("my.db", &db);
if( SQLITE_OK!=sqlite3_errcode(db) )
{
qWarning("DB error: fail to open db file.");
sqlite3_close(db);
return false;
}

//prepare the SQL statement
char sSql[1000];
sprintf(sSql, "select Name, Owner, Category, Duration from tb where ID=%d", id_in);
if(sqlite3_prepare_v2(db, sSql, -1, &pSTmt, 0))
{
qWarning("DB error: fail to prepare the sql statement: [%s]", sSql);
sqlite3_finalize(pSTmt);
sqlite3_close(db);
return false;
}

//execute the statement
iReturnCode = sqlite3_step(pSTmt);
switch (iReturnCode )
{
case SQLITE_DONE:
qWarning("Warning: No record is found!");
bRet = false;
break;

case SQLITE_ROW:

sName_ = (const char*)sqlite3_column_text(pSTmt, 0);
sCategory_ = (const char*)sqlite3_column_text(pSTmt, 1);
sOwner_ = (const char*)sqlite3_column_text(pSTmt, 2);
sDuration_ = (const char*)sqlite3_column_text(pSTmt, 3);

bRet = true;
break;

default:

qWarning("DB error: fail to step the sql statement: [%s]", sSql);
qWarning("DB error code:");
bRet = false;
}

//finialize the state statement
sqlite3_finalize(pSTmt);
sqlite3_close(db);
return bRet;
}

2009-10-05

Convert Number to QString

Useful API of OString, converting number to QString

QString number ( long n, int base = 10 )
QString number ( ulong n, int base = 10 )
QString number ( int n, int base = 10 )
QString number ( uint n, int base = 10 )
QString number ( qlonglong n, int base = 10 )
QString number ( qulonglong n, int base = 10 )
QString number ( double n, char format = 'g', int precision = 6 )

2009-10-04

Create a Dialog with Scrollbar


ListDialog::ListDialog()
{
QScrollArea *scrollArea = new QScrollArea(this);
QGroupBox *groupBox = new QGroupBox(scrollArea);
QVBoxLayout *vbox = new QVBoxLayout;

for (int i=0; i< 20; i++)
{
vbox->addWidget(new QRadioButton("item xxx"));
}

groupBox->setLayout(vbox);
scrollArea->setWidget(groupBox);

QHBoxLayout* layout = new QHBoxLayout();
layout->addWidget(scrollArea);
setLayout(layout);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
}

2009-10-02

Useful sqlite3 Commands

>sqlite3 $DB //create a db
>sqlite3 $DB < $sql_script //create a db using a sql script
>sqlite3 //enter sqlite3 sql shell
>.exit //leave the sqlite3 sql shell
>
.header ON //Column title is printed out by select

2009-10-01

protected and private constructor in C++/C# class

1) There exists only one reason to make constructor protected: The class will not be instantiated, but its subclass will be.
Bingo! Abstract class. See the C# example below:


//abstract class, never be created because abstract
//functions is not yet implemented
public abstract class MarkerBase
{
protected MarkerBase( string req_in ) {}
protected abstract int getMarkerID();
}
//subclass implement the abstract function and
//its constructor reuses the protected
//constructor of its abstract parent.

public class MyMarker : MarkerBase
{
public MyMarker(string req_in) : base(req_in){}
protected override int getMarkerID(){return 0;}
}


2) It is really confused that the class constructor is private. It means
that the class never be instantiated. If the class will never be created,
why do we need it?

The answer is a little mysterious: The class can be created only once by itself,
so-called singlton design pattern.

In some resource-related applications, we want to have only single instance for some classes. For example, if we have implemented a class to access a specific database, we want certainly the application has only an unique instance of this class. Otherwise, if multipe instances may write and read the same database, it is hard to control the synchronization. It is the reason why a singlton class has a private construct, which can be called only by itself once and prevent the class being created for several times by the other classes.

See the c++ class below. The class class manages accessement of a sqlite3 database.

class DBReader
{
public:
void insertRecord(const char* sql_in);
void select(const char* sql_in);
private:
sqlite3 * db_;

//for singleton design pattern
public:
static DBReader* getInstance();
private:
static DBReader* pDBReader_;
DBReader();
void databaseError();
};
DBReader* DBReader::pDBReader_ = NULL;
DBReader* DBReader::getInstance()
{
if(pDBReader_ == NULL)
{
pDBReader_ = new DBReader();
}
return pDBReader_;
}
DBReader::DBReader()
:db_(NULL)
{
// Open the database
sqlite3_open("coki.db", &db_);
if( SQLITE_OK!=sqlite3_errcode(db_) )
{
databaseError();
return;
}
}
...

int main()
{
....
//DBReader::getInstance() is the only
//way to get access database.

DBReader::getInstance()-> insertRecoard(sSQL_CM1);
DBReader::getInstance()-> select(sSQL_CM2);
return 0;

2009-09-30

Change Timezone in Debian

>dpkg-reconfigure tzdata
Then follow the step

2009-09-28

Fix size of QWidget

To fix the size of QWidget:


//Label for image
QLabel * oLabelImageCenter = new QLabel;
oLabelImageCenter->setBackgroundRole(QPalette::Base);
oLabelImageCenter->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
oLabelImageCenter->setScaledContents(true);
oLabelImageCenter->setFixedSize(200, 160);

2009-09-26

colorgcc

Colorgcc is a perl script that makes the error and warning message of gcc be highlighted by different color. Nice tool from Johannes Schlüter.

>wget http://schlueters.de/colorgcc.1.3.2.txt
>mv colorgcc.1.3.2.txt colorgcc
>mkdir /usr/local/bin/colorgcc
>mv colorgcc /usr/local/bin/colorgcc
>cd /usr/local/bin/colorgcc
>ln -s ./colorgcc g++
>ln -s ./colorgcc gcc
>export PATH=/usr/local/bin/colorgcc:$PATH

2009-09-22

Compile with Qt State Machine Framework

1) You need to download Qt State machine Framework
2) >tar xvzf $(QtStateMachine).tar.gz
3) In your .pro file add a line:

include($(QtStateMachineInstalledPath)/src/qtstatemachine.pri)

4)> qmake then make

Color Highlight in VIM

"A color editor like Vim can improve the productivity of programmers by 2 to 3 times!!"

>apt-get install vim
Add following lines into ~/.vimrc



" Set syntax highlighting to always on
syntax enable

" Set the background to dark and the colorscheme to murphy
set background=dark

" Set automatic filetype detection to on
filetype on



Change Qt Widget Background

Qt Widget's Background is changed by setPalette(QPalette);
The "Qt Tutorial 8 - Preparing for Battle" is changed: add a button to change the background color of ConnonField.
========
main.cpp:
========

MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)
{
QPushButton *quit = new QPushButton(tr("Quit"));
quit->setFont(QFont("Times", 18, QFont::Bold));

QPushButton *change = new QPushButton(tr("Change"));

connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));

LCDRange *angle = new LCDRange;
angle->setRange(5, 70);

CannonField *cannonField = new CannonField;

connect(angle, SIGNAL(valueChanged(int)),
cannonField, SLOT(setAngle(int)));
connect(cannonField, SIGNAL(angleChanged(int)),
angle, SLOT(setValue(int)));
connect(change, SIGNAL(clicked()),
cannonField, SLOT(changeBackground()));

...
}


===========
cannonfield.cpp
============
...
void CannonField::changeBackground()
{
setPalette(QPalette(QColor(0, 250, 200)));
update();

}
...



2009-09-21

Fullscreen Qt widget

If your Qt executable is the single application running at your embedded system. It makes sense that your Qt widget is border-less and full-screen.
Max modifies the example in Qt tutorial 4:

class MyWidget : public QWidget
{
public:
MyWidget(QWidget *parent = 0);
};

MyWidget::MyWidget(QWidget *parent)
: QWidget(parent, Qt::FramelessWindowHint)
{
//setFixedSize(200, 120);

QPushButton *quit = new QPushButton("Quit", this);
quit->setGeometry(62, 40, 75, 30);
quit->setFont(QFont("Times", 18, QFont::Bold));

connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
}

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyWidget widget;
//widget.show();
widget.showFullScreen ();
return app.exec();
}

Compile the code using Embedded Qt and run the binary among qvfb (See "Program and Test Qt Embedded Code on PC - virtual framebuffer"). The following snapshot is at 240x320 PDA configuration.

Use Class Declaration in C++ Header File

A good C++ programmer always seeks to let his header files as slim as possible. The following header file is a bad example, in which an unnecessary header file is included.

#ifndef MYCLASS_H
#define MYCLASS_H

#include <SuperTime>

//bad, slow down the compilation
#include "Number.h"

//good. class declaration is sufficient for a pointer variable
//class Number;

class MyTime : public SuperTime
{

public:
MyTime(SuperTime *parent = 0);
int value() const;
void setValue(int value);

void valueChanged(int newValue);
private:
Number *number;
};

#endif // MYCLASS_H


This makes the compilation of big projects much slower, because the compiler usually spends most of its time parsing header files, not the actual source code. As suggested in the comments, use a class declaration instead including a header file. The final binary files are same as before, but this trick alone can often speed up compilations by a factor of two or more. Belows are the example of declaration of the template class and class with namespace:





template < class L > List;
namespace card {
class MainBrowser;
}

2009-09-11

State Machine in Qt

Qt provides a two classes to implements state machines.
QtStateMachine offers the basic APIs for state machine mechanism, while QtScriptedStateMachine is a subclass of QtStateMachine and adds the missing parts to support SCXML. Max tried to implement the following state machine. The code is not yet tested, ;) Hope it works!


//selection state groups
QtState *pStateSelection = new QtState();
QtState *pStateSearch = new QtState(pStateSelection);
QtState *pStateBrowse = new QtState(pStateSelection);
pStateSelection->setInitialState(pStateBrowse);

//processing state groups
QtState *pStateProcessing = new QtState();
QtState *pStateMaterial = new QtState(pStateProcessing);
QtState *pStateProcedure = new QtState(pStateProcessing);
pStateProcessing->setInitialState(pStateMaterial);

//transitions from "Selection" state
pStateSelection->addTransition(buttonStart, SIGNAL(clicked()), pStateProcessing);

//transitions from "Browse" state
pStateBrowse->addTransition(buttonSearch, SIGNAL(clicked()), pStateSearch);

//transitions from "Search" state
pStateSearch->addTransition(buttonOK, SIGNAL(clicked()), pStateBrowse);
pStateSearch->addTransition(buttonCancel, SIGNAL(clicked()), pStateBrowse);

//transitions from "Processing" state
pStateProcessing->addTransition(buttonFinish, SIGNAL(clicked()), pStateSelection);
pStateProcessing->addTransition(buttonCancel, SIGNAL(clicked()), pStateSelection);

//transitions from "Material" state
pStateMaterial->addTransition(buttonProcess, SIGNAL(clicked()), pStateProcedure);

//transitions from "Procedure" state
pStateProcedure->addTransition(buttonMaterial, SIGNAL(clicked()), pStateMaterial);

//start the state-machine
QtStateMachine oMachine;
oMachine.addState(pStateSelection);
oMachine.addState(pStateProcessing);
aMachine.setInitialState(pStateSelection);

oMachine.start();

Reference:

2009-09-10

Create Sqlite Database by SQL Script.

Sqlite supports c/c++, Tcl and sql interfaces. Max wrote some sql scripts to create and initialize a single-table sqlite DB. Put the following three files in the same fold and execute createDB.sh.

1) createDB.sql (create a DB)

CREATE TABLE tb_master
(
Id integer PRIMARY KEY,
Name text NOT NULL UNIQUE,
Creator text,
Group_name varchar(20),
Time_stamp integer,
Snapshot blob,
Thumbnail blob,
Ingredient text,
Workflow text
);

2) demoData.sql (insert demo data)


INSERT INTO tb_master
VALUES
(
1,
'Applepipe',
'Max',
'Cake',
10,
'ddd',
'ddd',
'dddd',
'ssss'
);
INSERT INTO tb_master
VALUES
(
2,
'Chinaball',
'Jasmin',
'Soup',
11,
'ddd',
'ddd',
'dddd',
'ssss'
);



3) createDB.sh (main shell script)

#!/bin/sh
# This is a script to create a sqlite3 database "test.db"

#local variables
DB=test.db
CREATE_SCRIPT=createDB.sql
DATA_SCRIPT=demoData.sql

#remove database file if it exists.
if [ -f $DB ]
then
echo remove $DB
rm -rf $DB
fi


#create a database with sql script
echo create $DB
sqlite3 $DB < $CREATE_SCRIPT

#initialize with testing data
echo insert records
sqlite3 $DB < $DATA_SCRIPT

2009-09-09

Compile c/c++ code with sqlite3 library.

1) Install sqlite3 library.
  • >wget http://www.sqlite.org/sqlite-amalgamation-3.6.17.tar.gz
  • >tar xvfz qlite-amalgamation-3.6.17.tar.gz
  • >cd sqlite-3.6.17
  • >./configure
  • >make
  • >make install

The library libsqlite3.la now is installed to /usr/bin/...

2) Compile as following. Try the test code.
  • >gcc -o test test.c -lpthread -ldl -lsqlite3

2009-09-08

First impression of SQLite3

"SQLite is not designed to replace Oracle. It is designed to replace fopen()."

What a clear signal! SQLite's target is not a "enterprise database engine" but a samll, simple but smart database for applications.

Key features
  1. Embedded devices and applications
  2. Zero-Configuration
  3. Single Database File
  4. Stable Cross-Platform Database File
  5. C/C++ API
  6. SQL Compatibility
  7. 5 Datatypes In SQLite Version 3: NULL, INTEGER,REAL,TEXT,BLOB
  8. License in public domain (total free in product)
    References

    Putty in chinese

    A good article to configure Putty to see Chinese.

    Override assigment operators in C#

    A C++ class can implement assignment operators to
    1) assign itself, or
    2) convert the other class to itself.
    See the example.

    Unlike C++, C# does not support override of assignment operator. C# uses "implicit" key word to replace the assignment operator. See the example here.

    2009-09-07

    Program and Test Qt Embedded Code on PC - virtual framebuffer


    "Qt for Embedded Linux applications write directly to the framebuffer, eliminating the need for the X Window System and saving memory. For development and debugging purposes, a virtual framebuffer can be used, allowing Qt for Embedded Linux programs to be developed on a desktop machine, without switching between consoles and X11." (Source: http://doc.trolltech.com)

    0) You need a linux host, I have debian Lenny at home.
    1) Download Qt for X11. The Library source (*.tar.gz), not the SDK (*.bin).
    2) Installing Qt/X11. You may meet following error message during ./configure.

    You might need to modify the include and library search paths by editing QMAKE_INCDIR_X11 and QMAKE_LIBDIR_X11 in /home/lolveley/bin/qt-x11-opensource-src-4.5.1/mkspecs/linux-g++.

    The reason is the some dependencies are missing. Try this:
    • > apt-get build-dep qt4-qmake

    3) Qt for Embedded Linux library must be configured and compiled with the -qvfb option

    • > ./configure -qvfb
    • > make
    • >make install

    4) Compile and run tool qvfb (Qt virtual framebuffer) as a normal Qt for X11 application.
    • >cd path/to/Qt/tools/qvfb
    • >make
    • >make install
    If you encounter the error "/usr/bin/ld: cannot find -lXtst", you need install "libxtst-dev".

    5) Running embedded applications using the virtual framebuffer. Note: try the examples compiled with embedded Qt, not X11. Otherwise, you may encounter the error like "qvfb: cannot connect to X server". See example here.


    Reference .


    2009-09-04

    Create a ISO file in linux

    How to create a iso file?
    Forget about Nero, forget about MagicISO. These windows software just waste time and money. In Linux everything is just a line of command.

    >dd if=/dev/cdrom of=2440.iso
    5597332+0 records in
    5597332+0 records out
    2865833984 bytes (2.9 GB) copied, 430.944 s, 6.7 MB/s

    Maybe you want to mount this iso file
    > mkdir /dev/2440
    >mount -o loop 2440.iso /dev/2440/

    Or you want to mount the iso file at system startup, then add one line into /etc/fstab
    /$(yourpath)/2440.iso /mnt/2440 iso9660 ro,loop,auto 0 0

    2009-08-30

    "Acquiring network address" problem of wireless LAN

    Max's laptop has a problem of wireless connection, status is stuck always at endless "Acquiring network address". The reason lies on the client adaptor doesn't support the encryption method used in router. Solution is found here
    1. Change SSID in rounter to create a new profile.
    2. Use basic WEP 64bit ASCII encryption.
    3. now wireless works.

    2009-08-21

    apt-get install without debian CD

    For a fresh Debain installed from a CD, if someone wants to use apt-get install some packages, you may get the following error:

    'Debian GNU/Linux 5.0.2a _Lenny_ - Official i386 CD Binary-1 20090817-00:24'
    in the drive '/cdrom/' and press enter

    if you have taken out the debian CD for a long time.
    It is because that by default CD installation, apt-get will always check if your desired packages can be found in cdrom at first. Solution is simple, comment out the first item in your /etc/apt/sources.list

    #deb cdrom:[Debian GNU/Linux 5.0.2a _Lenny_ - Official i386 CD Binary-1 20090817-00:24]/ lenny main

    2009-08-20

    Setup SVN+SSL server at home

    Max finally setup a svn server at home.

    0) Install Debian Lenny
    1) DynDNS dynamical update your IP to dns
    2) Set Port forwarding on router, open 80 (HTTP) and 443 (HTTPS)
    3) Install apache + ssl. Some workaround about missing script.
    4) If you get following message when you restart "/etc/init.d/apache restart". You need to read this artical
    ># /etc/init.d/apache2 restart
    Restarting web server: apache2apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName

    5) Install and setup svn.

    2009-08-14

    Upload your DHCP IP to FTP server

    1) create ip_ftp.bat
    ====ip_ftp.bat ==========

    @echo off
    curl.exe http://whatismyip.com/automation/n09230945NL.asp > ip.txt
    ftp.exe -s:ftp.txt.bat
    2) create ftp.txt.bat
    ==== ftp.txt.bat ==========
    open $ftpserver
    $ftpuser
    $password
    put "ip.txt"
    bye
    3) download curl.exe to the same fold
    4) Run ip_ftp.bat
    5) Check if upload success by "curl.exe $server/ip.txt" (your IP will be shown)
    6) Put your script into scheduled tasks

    Some useful tips about x-window

    1) Where to check, if xwindow fails? Answer
    2) How to install xwindow? Answer
    3) How tow switch start level ? Textual or Desktop? Answer

    2009-08-13

    Extract DHCP dynamic IP

    A previous article has explained how to extract static IP using a batch. But if your computer has a dynamic IP assigned by DHCP server, how can you get your IP? ipconfig? let's see.



    Look! You just got an useless local IP 192.168.x.x.
    • Where is your current WAN IP? Click here. Now you got a your real IP, at right now.
    • Why this happens? See the explanation here. The reason is your router. It determines the IP in WAN, but you or your code can only get it a LAN IP from it.
    • How let your script get the WAN IP? Try this! "curl http://whatismyip.com/automation/n09230945NL.asp". Of course, you need to install the curl at first.
    • How to let your code get WAN IP? Use libcurl.

    Qt - signals and slots

    Max is used to be a hardcore supporter of fox-toolkit for C++ GUI developement. Fox is a good, free and cross-system library. But Max always has some kinds feeling that Fox-toolkit may miss something important. Until today Max read something about Qt, another open source GUI library, he came to realize that fox-toolkit may somehow be short of good communications between different components. Interaction between Fox GUI components is possible but not straight forward. In contrast to Fox-toolkit, Qt uses a smart way - signals and slots - to let different component to talk to each other.

    See the introduction of "Signals and Slots".



    From the design pattern point of view, "Signals and Slots" in a certain sense follows the idea of "Command Pattern". The basic idea is to let two objects to work together, but they don't need to know each other. It sounds a little wired, but it can significantly simplify the design, coding and maintaining. With help of this mechanism, components can be better encapsulated and full decoupled to each other. The connection between objects is built up by a simple QObject::connect() function calls. You can connect as many signals as you want to a single slot, and a signal can be connected to as many slots as you need.

    The other common methods for the interaction between GUI objects:
    • Callback function
    • Event
    • Data binder.


    Reference:

    batch file to extract static IP

    If you installed VMware in your windows computer, more IPs will be displayed by ipconfig. How to seperate your static IP from VM IP? Good news: all vm IP start with 192.168. See the following batch:




    @echo off

    IPCONFIG |FIND "IP" | FIND /V "192.168" > %temp%\TEMPIP.txt
    FOR /F "tokens=2 delims=:" %%a in (%temp%\TEMPIP.txt) do set IP=%%a
    del %temp%\TEMPIP.txt
    set IP=%IP:~1%
    echo %IP% >%temp%\ip.txt
    echo The current IP address is "%IP%"

    2009-08-11

    DHCP at home

    DHCP is short for Dynamic Host Configuration Protocol. Most of house computers access the internet as DHCP clients. For example, as Max starts his house computer, as a DHCP client, it sends request to DHCP server (owned by ISP) and get a response with a dynamical configuration information of network:
    • IP Address
    • Subnet Mask
    • Default Gateway
    • DNS server
    • ...
    The most important is IP address. DHCP client will never get a static IP for a long term. For example, T-online (ISP) automatically recycles all the IPs and assigns a new IP to your computer (DHCP client) in 24 hours. Actually, all the DHCP server has somehow been configured that client IP will be reassigned within a certain time span and IP ranges. What is DHCP good for? Because static IP is valuable resource of www, while DHCP is enable to more efficiently reuse the IP resource.

    Just have a fun. If some marketing people of ISP keep bothering you with some blabla.., just ask him this question:

    "Could you provide me a static IP with this price?"

    He will shut up immediately. Trust me.

    2009-08-10

    How to switch between diff gcc version?

    You don't need to uninstall or reinstall anything in Debian. Take an example, you want to compile some code with gcc 4.3 und gcc 4.1 and compare the performance.

    As root:
    1) Install both of them
    • >apt-get install gcc 4.1
    • >apt-get install gcc 4.3
    2) You could find both gcc exist at /usr/bin
    • >ls gcc*
    3) Assume you want to set gcc 4.3 as default c compiler.
    • >cd /usr/bin
    • >ln -s gcc-4.3 gcc (create a symbolic link)
    • >export CC=/usr/bin/gcc (set variable)
    • Now you can complie you code now (e.g make)
    4) If you want to use gcc 4.1, do the same thing as above.

    In the most case, it works well.

    2009-08-09

    google code hosting

    Max is looking for a cost-free way to share the code with partner in Shanghai. Someone in the forum says: "If you start an open source project, try SourceForge or Google Code Hosting." SourceForge is well-known, it still has 24 million unique visitors, 2 million downloads a day and 125,000 active projects. While Google Code Hosting is something brand new, from last week. Some features are not yet offered. Even though, Max's first trial come out positive feedback.

    Here is a sample of google code project. Have you see it? It has everything already! Version control with svn, source browser, issue tracking, wiki, project block, member management, auto document. See FAQ to get know more about this new stuff.

    Max likes google team, these google guy make complicated thing simple, make simple thing classic. It was one of his dreams to be a member of google team in one day. Ok, forget about it. Too emotional! Be cold.

    Private Project is not yet availalbe in Google Code Hosting.
    For something good, we need to be patient. Let's wait.


    References

    Buildroot for AT91SAM9261_EK (II)

    The first try fails. Too bad!
    Building was blocked by some funny miniperl issues. It looks not so simple.

    ext/util/make_ext: line 122: ../../miniperl: No such file or directory Warning: No Makefile!

    Reverse gcc compile:
    • gcc 4.3 => gcc 4.1
    • g++ 4.3 => g++ 4.1
    Max tried to change the configuration in following way. Maybe it works.
    Target Architecture (arm)
    Target Architecture Variant (arm926t)
    Target ABI (OABI)
    The rest settings use default ones.


    After about 30 minutes, it seems that building success. At least no error message come out. See the root.
    user@debian:~/buildroot$ ls -l
    total 116
    drwxr-xr-x 3 user user 4096 2009-08-09 14:06 binaries
    drwxr-xr-x 9 user user 4096 2009-08-09 15:00 build_arm
    -rw-r--r-- 1 user user 7190 2009-08-09 13:18 CHANGES
    -rw-r--r-- 1 user user 10673 2009-08-09 13:18 Config.in
    -rw-r--r-- 1 user user 17987 2009-08-09 13:18 COPYING
    drwxr-xr-x 2 user user 4096 2009-08-09 15:00 dl
    drwxr-xr-x 3 user user 4096 2009-08-09 13:18 docs
    -rw-r--r-- 1 user user 17396 2009-08-09 13:18 Makefile
    drwxr-xr-x 303 user user 12288 2009-08-09 13:18 package
    drwxr-xr-x 2 user user 4096 2009-08-09 13:18 project
    drwxr-xr-x 3 user user 4096 2009-08-09 14:06 project_build_arm
    drwxr-xr-x 3 user user 4096 2009-08-09 13:18 scripts
    drwxr-xr-x 21 user user 4096 2009-08-09 13:18 target
    -rw-r--r-- 1 user user 806 2009-08-09 13:18 TODO
    drwxr-xr-x 13 user user 4096 2009-08-09 13:18 toolchain
    drwxr-xr-x 18 user user 4096 2009-08-09 14:43 toolchain_build_arm
    Strange!

    After some tries, Max located the problem. Building fails due to "EABI", a feature of targeting toolchain to optimize the floating point computation. See the following test.
    • gcc 4.3.1 + EBAI => Fail
    • gcc 4.1.1 + EBAI => Fail
    • gcc 4.3.1 + OBAI => Success
    • gcc 4.1.1 + OBAI => Success
    Reference:

    2009-08-08

    Etch Lenny Sid

    Max installed Debian Lenny Server in last week. Since then he saw different Debian name in the internet, like Debian Etch, Debian Sid. He wondered what those funny "nicknames" mean? The answer is a big surprise:
    • Etch: old stable
    • Lenny: stable
    • squeeze: testing
    • Sid: unstable
    He is using a stable Debian system right now. Klasse!

    Buildroot for AT91SAM9261_EK

    It is the first time for Max to play Buildroot. Hopefully, it's not the last time.
    The target system is an evaluation board of ATMEL "AT91SAM9261_EK". Buildroot tools will generate following things for the target system.
    • Customizing the target filesystem
    • Customizing the Busybox
    • Customizing the uClibc
    • Customizing the packages
    • HelloWorld Project
    • ....
    In a word, a brand new system for target board.

    About download and install the Buildroot tools, please check here.
    1) Start from ${buildroot}
    > make menuconfig

    2) Configuration.
    Max took the most default setting and customized the configuration as following (who knows, let's just have a try!) . In the end, a .config file will be generated at ${buildroot}


    Target Architecture (arm)
    Target Architecture Variant (arm926t)
    Target ABI (EABI) See the reason here.

    Target Options:
    Project options:
    Project name (HelloWorld)
    hostname (syn_at9261_0)
    banner(Welcome to HelloWorld)

    Generic serial port config:

    Serial port to run a getty on (ttyS0)
    Baudrate to use (115200)


    ToolChain
    [*] Build/install c++ compiler and libstdc++?
    [*] Use ARM Vector Floating Point unit

    Package Selection for the target
    [*] make
    Graphic libraries and applications (graphic/text)
    [*] Qt
    Target filesystem options
    [*] Das U-Boot Boot Monitor --->
    board name (at91sam9263-ek)



    3) Build it and finish.
    • >make
    Ok!Ok! I lied. It is not so easy. Usually you need do something more. You need to download some necessary packages. Can you handle it yourself? Tell me "yes, yes, yes". Only one nasty thing you may encounter is the failures of some sanity tests. See this page for the solution. The most problems occurs in the first 2 minutes. Afterwords, you can take a coffee and chat with your friends.

    Till now, the building has not yet finish. Max's host system is debian Lenny at VM. It will take sometime. To be continued....

    2009-08-06

    About toolchain

    What is Toolchain?

    Toolchain, more precisely, cross-compilation toolchain is a set of tools to build binary files for your target system. Let me explain in this way, you have coded a c program on a PC with Debian 5.0 system and x86 CPU (host system). Now you want to build to the c file to an executable and let it run in a board with ARM processor (target system). Cross-compilationToolchain will help you to build your binary file for the specific target system, based on your current host system.

    What does a Toolchain have?
    • Compiler (gcc),
    • linker and assembler (binutils),
    • C standard library (uclib)

    How to get a Toolchain?

    Usually you can get toolchain from the board provider. Or build your own using Buildroot.
    See the artical.

    What do you need to know before build a Toolchain?

    To be continued...

    Predicate Delegation

    C#2.0 has introduced several interesting grammars into simple c++ style coding. "Predicate Delegation" is one of them. From the point of linguistic semantics, a predicate is an expression that can be true of something. In the C#, predicate delegation is a reference of function, whose return value is true or false. Why do we need it? Because predicate delegation works like a filter and make search operation among a collection (List, IEnumerable) simpler and clearer. Let me paste the example from here

    Here is a common c type function to return odd numbers from an array.


    int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int[] odds = GetOdds(numbers);
    private static int[] GetOdds(int[] numbers)
    {
    int[] odds = new int[numbers.Length];
    int counter = 0;
    for (int i = 0; i < numbers.Length; i++)
    {
    if ((numbers[i] % 2) != 0)
    {
    odds[counter++] = numbers[i];
    }
    }
    return odds;
    }
    Using Predicate Delegation the above program can be simplified as
    int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };        
    int[] odds = Array.FindAll<int>(numbers, IsOdd);

    private static bool IsOdd(int number)
    {
    return ((number % 2) != 0);
    }
    Powerful! Isn't it?

    use sudo

    sudo is the command that allows you run some commands using other login, without switch user at first. Of cousre, you need to tip the corresponding password. For exmple
    • >sudo less /var/log/boot
    To see the boot log, you need to be root. But sometimes even the correct password is given, you still got the following error message.

    [sudo] password for user:
    user is not in the sudoers file. This incident will be reported.

    Error message is self-exlained. You need to edit sudoers file, which is located at "/etc/sudoers". As root, you can edit the file by
    • >vis /etc/sudoers
    • Add "user ALL=(ALL) ALL" into it
    Now sudo should work. /etc/sudoers is very powerful to manange which user can run which program. See more tricks in "sudoers file".

    2009-08-05

    Putty connets to local VM

    On the windows host, Max prefers to use Putty console instead of directly using VM windows to play the local Linux VM. Everyone know it. Since Putty uses SSH protocol to connect to server, it is logical that we have to install SSH daemon on the Linux VM Guest at first.


    1) Install SSH package
    >apt-get install openssh-server

    2) Start SSH Daemon
    >/etc/init.d/ssh restart

    3) Get IP of guest
    >ifconfig

    4) Start Putty from Windows Host and connect to the Guest IP


    Share folder of Debian VM

    VM guest and host share data by hgfs service.
    Eniviroment:
    • Host: WindowsXP
    • Guest: Debian 5.0 Lenny Server
    • VMware: VMware player 2.5.2
    1) Install vm tools in Debian VM. Or directly download a Vmware Tools installed Appliance.
    2) Check the boot log, if VMTools deamon is started.
    2) Edit *.vmx, add following text in the end.

    isolation.tools.hgfs.disable = "FALSE"
    sharedFolder0.present = "TRUE"
    sharedFolder0.enabled = "TRUE"
    sharedFolder0.readAccess = "TRUE"
    sharedFolder0.writeAccess = "TRUE"
    sharedFolder0.hostPath = "D:\work\share\"
    sharedFolder0.guestName = "win-share"
    sharedFolder0.expiration = "never"
    sharedFolder.maxNum = "1"

    3) Enable the share fold by menu:
    VMware Player->Share folders->Always enable

    share folder is found at /mnt/hgfs/${sharedFolder0.guestName}

    boot log

    How to check see the boot log? Simple!
    • >vim /etc/default/bootlogd
    • >BOOTLOGD_ENABLE=Yes
    • >reboot
    • >less /var/log/boot
    Actually you can find more logs in /var/log.

    2009-08-04

    Install VMware Tool in Debian VM

    VMware Tool is important not only for performance but also for sharing folder between host and guest. Be default, VMware tool won't be installed for VMware Player, only available for VMware Workstation. However, VMware tool doesn't require any cost licences for installation. With some tricks, VMware Player can also use VMware Tools. Someone has explained how to do it in the case of "Linux Host/ Window Guest". In the following, we are going to talk about how to install the VMware tool in the case "Windows Host/Linux Guest".
    • Host: WindowsXP SP2
    • Guest: Debian 5.0 Lenny Server
    • VMPlayer: 2.5.2
    1) Download "VMware Server 2". Pick up tar image, not the rpm and exe.

    2) Extract vmware-server-distrib/lib/isoimages/linux.iso from the tar.gz file and copy to a usb stick.
    • tar xvzf VMware-server-*.tar.gz vmware-server-distrib/lib/isoimages/linux.iso
    3) Mount usb stick in Vmware player.
    • Devices->${USB_STICK}->Connect.
    • >mkdir /media/usb
    • >mount -t vfat /dev/sdb1 /media/usb
    4) Mount linux.iso in Debian guest and fetch VMwareTools-???-.tar.gz
    • > su
    • > mkdir /tmp/vmware_tools
    • > mount -o loop linux.iso /tmp/vmware_tools
    • > cp /tmp/vmware_tools/VMwareTools-*-.tar.gz /tmp/
    5) Extract the VMwareTools-*-.tar.gz
    • >tar xvzf VMwareTools-*-.tar.gz
    6) Install Vmware Tools. Choose the default setting. If some packages (make, psmisc, gcc, linux-header) are missing, you need to update or install by apt-get.
    • > /tmp/vmware-tools-distrib/vmware-install.pl
    Reference:

    7) Reboot
    1. Installing VMware Tools on Debian Lenny 5.0.2 with gnome destop on ESX server 3.5 update 4
    2. VMware Tools failed to build vmmemtcl module
    3. proxy problem of apt-get update
    4. The path “/usr/src/linux/include” is not an existing directory

    2009-08-03

    gconftool - preferences setting

    As Max seeked to setting Proxy for his Debian VM, he found an interesting configuration tool in GNOME, "gconftool", which is used to manage all kinds of appliation preferences, i.e, proxy server, desktop and so on. He decided to spend sometime to learn it.

    The cool thing is that " if someone changes a setting by gconftool, it instantly updates in all the applications that interested in this setting" . Simple but powerful, thousand times better than nasty Windows Registry. Take the example of set proxy server in article "Make Debian work better" Let's see how it work:

    • > gconftool -s /system/http_proxy/use_http_proxy -t bool true
    • > gconftool -s /system/http_proxy/host -t string ${PROXYSERVER}
    • > gconftool -s /system/http_proxy/port -t int ${PORT}
    • > gconftool -s /system/http_proxy/use_same_proxy -t bool true
    • > gconf -s /system/proxy/mode -t string manual

    No news is good news! At the time, if you open System->preference->Network Proxy, you would find all the settings have been updated, without logout or restart. More explaination in detials can be found in Victor's blog .

    Where are these preference value saved? Here you are:

    >cat .gconf/system/http_proxy/%gconf.xml


    You see, so-called repository is nothing but a just well-structured xml data. More precisely, the repository is not single xml but a series of xml in different storage locations (Configuration sources). You can search a preference in repository as

    > gconftool -g /system/http_proxy/port
    81

    Or recursively show all preference in the path

    > gconftool -R /system/http_proxy

    use_http_proxy = true
    use_authentication = false
    host = ${PROXYSERVER}
    authentication_user =
    ignore_hosts = [localhost,127.0.0.0/8]
    use_same_proxy = true
    authentication_password =
    port = 81

    By default, GConf searches the xml files in the following order:

    • xml:readonly:/etc/gconf/gconf.xml.mandatory (w:root)
    • include "$(HOME)/.gconf.path"
    • xml:readwrite:$(HOME)/.gconf (The above setting is save here)
    • xml:readonly:/etc/gconf/gconf.xml.defaults (w:root)