Saturday, March 31, 2012

An overview of Qt Quick 1.1 Components

I'm recently redesign the UI of PomodoroApp, and testing Qt Quick. I read through the tutorials and resources below:

  • Qt Essentials - Qt Quick for C++ Developers: 8 excellent slides for you to getting started with Qt Quick, and understand most of the features

  • QML Elements: Detailed description for grouped lists of QML elements as part of Qt Quick.

  • Some samples from Qt demo/examples declarative folders. You can build and run those features and see what QML can do.

While my purpose is to have a smooth and beautiful UI for my app on *desktop*, both Windows, Mac and Ubuntu. I may need to spend more time to learn QML and create basic elements for desktop widgets. Then I found some existing QML components here. I played for a while. Here is the screenshot for colibri, beautiful and has covered most of frequently used components.

[caption id="attachment_60" align="aligncenter" width="300" caption="Qt Quick QML Component "colibri""]Qt Quick QML Component "colibri"[/caption]

How to make debian package (.deb) with scripts

When I port my qt projects to Ubuntu/Debian Linux systems, I provided the compiled debian package, a deb file for users. I use a GUI debian package creator to make a deb package. Today when I browser qt-components, I got this bash script that can create deb file easily:


#!/bin/sh
MAKE='make -j4'

cd `dirname $0`

rm -rf debian
mkdir debian
cd debian

mkdir -p "usr/share/applications"

desktop_file_meenotes="usr/share/applications/meenotes.desktop"
echo "[Desktop Entry]" > "$desktop_file_meenotes"
echo "Version=1.0" >> "$desktop_file_meenotes"
echo "Name=MeeNotes" >> "$desktop_file_meenotes"
echo "GenericName=MeeNotes" >> "$desktop_file_meenotes"
echo "Comment=MeeNotes" >> "$desktop_file_meenotes"
echo "Exec=/opt/meenotes/MeeNotes" >> "$desktop_file_meenotes"
echo "Terminal=false" >> "$desktop_file_meenotes"
echo "Type=Application" >> "$desktop_file_meenotes"
mkdir -p DEBIAN

control_file="DEBIAN/control"

echo "Package: meenotes" > "$control_file"
echo "Version: 1.0" >> "$control_file"
echo "Architecture: all" >> "$control_file"
echo "Maintainer: Qt developers" >> "$control_file"
echo "Description: Qt components MeeNotes" >> "$control_file"

[ ! -f "../Makefile" ] && (cd ..; qmake)
(export INSTALL_ROOT=`pwd`; $MAKE install)

mkdir -p opt/meenotes

cp -ar ../MeeNotes opt/meenotes/
cp -ar ../resource opt/meenotes/resource

cd ..
dpkg-deb --build debian
mv debian.deb meenotes.deb

Monday, March 12, 2012

Practice on C++11(2): tuple, rvalue, auto, lambda

Continue with my previous post about rvalue, auto, lambda, decltype, My second practice is to create a list of objects without knowing too much details. I'll give also 2 styles of code for comparing:

1. Traditional C++ style:

[cpp]
// definition of getTaskList:
// void getTaskLists( std::vector<int>& ids, std::vector<QString>& names );
std::vector<int> ids;
std::vector<QString> names;
PDatabaseManager::instance()->getTaskLists( ids, names );
Q_ASSERT( ids.size() == names.size() );

PLists lists;
for( size_t i = 0; i < ids.size(); ++i )
{
lists.push_back( PListPtr( new PListSqlite( ids[i], names[i] ) ) );
}
[/cpp]


2. C++11 style, also, leverage algorithms instead of write code by yourself:

[cpp]
// definition of getTaskList:
// std::vector< std::tuple<int, QString> > getTaskLists();
auto&& rawlists = PDatabaseManager::instance()->getTaskLists();

PLists lists;
std::for_each( rawlists.begin(), rawlists.end(), [&]( const std::tuple<int, QString>& i ) {
lists.push_back( PListPtr( new PListSqlite( std::get<0>( i ), std::get<1>( i ) ) ) );
} );
[/cpp]


The new style looks more elegant and clean.

Practice on C++11(1): rvalue, auto, lambda, decltype

I learned C++ programming language when I was a sophomore in the year 1998, and I started to use C++ on commercial software since 2001. I'm insist in using C++ for most of my projects just because I'm a skilled programmer. I have ever read books for C++98, and articles/presentations/papers for C++0x, but never really used it on my project. Recently I watched the keynotes of Bjarne Stroustrup and Herb Sutter on GoingNative 2012, I was motivated change my mind from traditional C++ mindset to C++11. The project of company still using Visual Studio 2008 as the compiler, I practiced C++11 on a side project in my spare time.

Here is my first practice which leveraged: rvalue, auto, lambda, decltype:

This function is in my unit test, the purpose is to check if there a line in the canvas with specified start and end point.

1. Traditional Style(not compiled, just write here for comparing with C++11 style)
[cpp]
bool hasLine( const QPointF& start, const QPointF& end )
{
std::vector<DGraphicsItem*> items = canvas.items();
for( std::vector<DGraphicsItem*>::const_iterator i = items.constBegin();
i != items.constEnd(); ++i )
{
DGraphicsItemLine* pLine = dynamic_cast<DGraphicsItemLine*>( p );
if ( !pLine ) continue;
if ( pLine-->startPoint() == start && pLine-->endPoint() == end ) return true;
}
return false;
}
[/cpp]

2. C++11 style
[cpp]
bool hasLine( const QPointF& start, const QPointF& end )
{
auto&& items = canvas.items();
return std::find_if( items.constBegin(), items.constEnd(),
[&]( DGraphicsItem* p ) -> bool
{
auto pLine = dynamic_cast<decltype(m_pLine)>( p );
return pLine && pLine->startPoint() == start && pLine->endPoint() == end;
} ) != items.constEnd();
}
[/cpp]

I like the new features in C++11 very much, and it's very impressive for me that my first C++11 style code works gracefully!
You may wonder why I use decltype here. The reason is, when I write other test cases, I may copy the code and make some modifications, if I have the type DGraphicsItemLine here, it's easy for me to miss changing the type. Furthermore, I hope I can get some templates or abstraction so that I can reuse the code in future.