Nokia发布Qt大使计划

这个可能不算是很新的消息,很久以前就听人提过。不过这个计划现在才算是正式上线了!

官方主页在此:http://qt.nokia.com/qt-in-use/ambassadors/qtambassador/

简单来说,有点像前段时间推的Qt Certificate的性质, 只是certificate是针对个人的, 而这个是针对项目的。 对于Nokia本活动旨在网罗一批优秀的Qt project, 可以很好的展示和宣传Qt的酷炫功能。 对于参与的个人来说最大的好处是多了更多宣传自己的渠道, 还有可能得到官方的赞助。 可惜俺编程的水平很烂,没有能拿得出手的东西,要不然我也是show一show了。

大家如果想了解更多的信息请上官网。 另外还有一篇blog介绍这个dd的, 在此(需要youtube翻墙):

http://blog.qt.nokia.com/2010/07/20/call-for-ambassadors-qt-ambassador-program-launches/

by shiroki Tags: ,
Posted on July 30th, 2010 in 新闻类 | No Comments »

在Nokia Qt SDK中开发Maemo应用

这是一个CuteQt参与的第一个有声博客:) 欢迎收听

by 臭虫 Tags: , ,
Posted on July 29th, 2010 in Linux技术, Qt技术 | 2 Comments »

利用QtMobility中的Location API获得位置信息

因为QtMobility是独立于Qt的一个模块,如果想在代码中使用QtMobility则需在.pro文件中加入下面的代码
CONFIG += mobility
MOBILITY = location bearer

第一行将QtMobility进行了使能。
第二句则将定位功能和网络连接管理(某些定位方法需要网络支持)加入编译。

除此之外,如果是Symbian系统还需为工程增加相应的几个签名能力,在.pro中加入下面内容
symbian {
TARGET.CAPABILITY += NetworkServices Location ReadUserData
}

要取得位置信息,则需要有一个位置信息提供源QGeoPositionInfoSource,该信息源可以通过下面函数获得
QGeoPositionInfoSource *source = QGeoPositionInfoSource::createDefaultSource(this);
每当位置信息发生变化时,QGeoPositionInfoSource都会发送一个位置更新的信号SIGNAL(positionUpdated(QGeoPositionInfo)),QGeoPositionInfo中包含了经纬度和精确度等一些信息,我们只需将该信号关联到我们的slot函数中,对数据做进一步处理即可。
connect(source, SIGNAL(positionUpdated(QGeoPositionInfo)),this, SLOT(positionUpdated(QGeoPositionInfo)));

这里是我的一个非常简单源码geoinfo,将获得的坐标信息显示在标签上,在N97上测试成功。

要保证测试成功,需要在N97上做的一点设置。
1. 如果在室外的话,不用做改动,一会就能获得数据。
2. 如果在室内做测试,需要在另外一个叫”定位“的应用中,将定位方法中的”A-GPS”和”GPS”禁止掉,只保留”使用网络定位“,则很快能够获得数据。

by 臭虫 Tags: , ,
Posted on July 28th, 2010 in Qt技术, s60 | No Comments »

解决Fc*相关的undefined reference链接错误

笔者最近在CentOS上编译Qt时发现了一个奇怪的链接错误, 搜索了一下发现这个问题在Redhat系列的OS里非常普遍, 包括CentOS5, RHEL4/5都有类似的问题。 典型的错误信息是(RHEL5上的):
/opt/qtsdk-2009.01/qt/lib/libQtGui.so: undefined reference to `FcFreeTypeQueryFace’
collect2: ld returned 1 exit status

像笔者使用的CentOS4, 出的错误信息就更多了, 不过也无外乎Fc开头的一系列函数。
检查了系统, fontconfig相关的库和头文件都安装好了, 按说不应该出这样的问题。 经过研究, 发现问题出在fontconfig的版本上。 原来Qt里使用到FC比较新的特性, 有些函数要在高版本的fontconfig里才能找到, 而Redhat系列的系统向来是更新慢得出了名的。 像CentOS4里的fontconfig居然还是1.0.4版, 而RHEL5里用的是fontconfig 2.1.x。 `FcFreeTypeQueryFace’ 这个函数是在2.4.2版本才引入fontconfig的。

相关的release文档: http://fontconfig.org/release/ChangeLog-2.4.2

解决的方法当然是升级fontconfig, 可以拿来fontconfig的源码包重新编译。 下载地址是:
http://fontconfig.org/release/

用新的版本覆盖掉老版本就ok了。

by shiroki Tags: , , ,
Posted on July 26th, 2010 in Linux技术, Qt技术 | No Comments »

Qt程序只运行一个实例

在我的这篇文章中使Qt程序只运行一个实例,通过QSharedMemory来实现进程间通讯,使用这种方式来是Qt程序只运行一个实例。有一天测试部的MM告诉我,她在测试的时候,程序crash掉了,再次运行程序,程序不能继续运行。

程序不能运行,显然是共享内存没有释放引起的,但是程序crash后为什么共享内存不能释放呢?于是打开Qt助手看到QSharedMemory是这样解释的:

Unix: QSharedMemory "owns" the shared memory segment. When the last thread or process that has an instance of QSharedMemory attached to a particular shared memory segment detaches from the segment by destroying its instance of QSharedMemory, the Unix kernel release the shared memory segment. But if that last thread or process crashes without running the QSharedMemory destructor, the shared memory segment survives the crash.

怎么可以这样?555…看来Nokia提供的QtSingleApplicationsolution的方法还是蛮好的。真是杯具丫,只好换QtSingleApplication,下面就介绍一下我把QSingleApplication整合到自己的应用程序中去的方法一:

1.首先从http://qt.nokia.com的网站把QtSingleApplication的源代码qtsingleapplication-2.6_1-opensource.zip下载下来,然后解压缩。假设解压缩到路径:

E:\qtsingleapplication-2.6_1-opensource

2. 编写程序代码如下:

#include <QLabel>
#include <QWidget>
#include <QMessageBox>
#include <QApplication>
#include "E:\qtsingleapplication-2.6_1-opensource\src\QtSingleApplication"

int main(int argc,char* argv[])
{
    QtSingleApplication app(argc,argv);
    if (app.isRunning())
    {
        QMessageBox::information(0, "test",
                    "An instance has already been running.");
        return 0;
    }
    QLabel label("<h2>test</h2>");
    label.show();
    return app.exec();
}

3.编译

qmake –project

qmake

nmake

链接器报告我们链接错误,链接不到QtSingleApplication的构造函数和isRunning()函数。错误很明显,编译的时候找到了QtSingleApplication的定义,但是链接器链接不到二进制符号。

4.打开刚刚生成的pro文件,加入

include(E:\qtsingleapplication-2.6_1-opensource\src\qtsingleapplication.pri)

然后qmake&nmake

这样我们的单实例程序就可以运行了,并且在linux下,当程序crash掉的时候不会存在类似sharedmemory不释放的问题。

注意:QtSingleApplication依赖于QtNetWork模块,因为其进程间通讯是通过socket来实现的,所以我们在发布程序的时候不要忘记带上QtNetWork4.dll

上面的方法虽然可以编译生成单实例程序,但是并不是我想要的最终的解决方案。因为不可能要求我的同事都下载下QtSingleApplication来,然后照着上面的说明来做,更何况大家放置QtSingleApplication的路径也不可能一样(当然可以通过make&make install把QtSingleApplication安装到Qt的路径下),总是觉得这样做会给大家带来麻烦,索性直接把QtSingleApplication的代码编译到我的工程里去算了,QtSingleApplication随着工程一起就不会存在上面描述的问题了。下面介绍方法二

介绍一下把QtSingleApplication代码编译到程序中的方法:

1. 在当前程序路径下新建文件夹qtsingleapplication和qtlockedfile。

将qtlocalpeer.cpp、qtlocalpeer.h、qtsingleapplication.cpp、qtsingleapplication.h、qtsinglecoreapplication.cpp、qtsinglecoreapplication.h拷贝到qtsingleapplication文件夹下;

将qtlockedfile.cpp、qtlockedfile.h、qtlockedfile_unix.cpp、qtlockedfile_win.cpp拷贝到qtlockedfile文件夹下

2. 修改pro文件:

win32 {

SOURCES += qtlockedfile/qtlockedfile_win.cpp

}

unix {

SOURCES +=qtlockedfile/qtlockedfile_unix.cpp

}

SOURCES += test.cpp \

qtsingleapplication/qtlocalpeer.cpp \

qtsingleapplication/qtsingleapplication.cpp \

qtsingleapplication/qtsinglecoreapplication.cpp \

qtlockedfile/qtlockedfile.cpp

HEADERS += qtsingleapplication/qtlocalpeer.h \

qtsingleapplication/qtsingleapplication.h \

qtsingleapplication/qtsinglecoreapplication.h \

qtlockedfile/qtlockedfile.h

修改刚才编写的cpp文件,将原来的include文件的路径改为相对路径。

#include "qtsingleapplication/qtsingleapplication.h"

3. 这时,运行一下qmake、nmake,出现了一大堆链接错误,仔细一看,原来是QtNetWork中的函数,昏倒,刚才还在上面提醒大家要在发布的时候包含QtNetwork4.dll,就在这里忘记包含了QtNetwork。打开pro文件,加上一句QT +=network,然后qmake、nmake恭喜,现在没有问题了。运行一下,确实是我们需要的结果。

或许你也会嫌这种方法麻烦,每次都需要改pro文件,还要包含这么多头文件和源文件,当然,我们还可以把qtsingleapplication编译成一个lib文件,在使用的时候,只需要include头文件,链接的时候把lib添加上就可以了。这个方法和方法二差不多,不同的地方在于编译静态库要在pro中使用下面参数:

TEMPLATE = lib

CONFIG +=static

相信你一定能编译出并且使用lib文件。

上面提供了使用QtSingleApplication使用的几种方法,大家可以根据自己的实际情况选择最适合自己的。

by tingsking Tags:
Posted on July 16th, 2010 in Qt技术 | 1 Comment »

QPlainTextEdit获得当前光标行的行号

QTextDocument的结构之复杂是不用不知道, 一用吓一跳。 连获得光标行号这么个简单问题都要拐上七八个弯。
下面是一个比较标准的解决方案:
//get the current line number
QTextCursor tc = edit->textCursor();//当前行的光标
QTextLayout* lo = tc.block().layout();
//get the relative position in the block
int pos = tc.position() – tc.block().position();//当前光标在本block内的相对位置
int line = lo->lineForTextPosition(pos).lineNumber() + tc.block().firstLineNumber();//用block的text layout计算光标在本block的行号, 需要传入光标相对于block的位置
qWarning() << line;

还有一个有点土的方法, 但代码稍微少点, 就是计算"\n"出现的次数代替行数, 当然有可能某些情况下会出bug, 请酌情使用:
int position = edit->textCursor().position();

qDebug() << edit->toPlainText().left(position).count(“\n”);

感觉这部分API设计得很乱, 非常不符合Qt的API设计intuitive的理念, 很需要改进。

by shiroki Tags: , , ,
Posted on July 8th, 2010 in C++, Qt技术 | No Comments »

计算和绘制QPlainTextEdit的行号

在Qt的example里有个例子叫做codeeditor:
http://doc.qt.nokia.com/4.6/widgets-codeeditor.html
codeeditor screenshot

该例子演示QPlainTextEdit类的用法, 其中有个有用的功能是在编辑器的左边margin的位置显示行号。 查看它的代码就会发现, 它用的时候遍历QTextBlock的方法确定行号, 这样就带来一个问题, 也就是实际上显示的所谓“行号”其实是段落号。 这在大多数情况下没什么问题, 但遇到某些bt用户非要狂按“Shift+Enter”问题就来了。

Qt的文档中可以找到对“Shift+Enter”和“Enter”行为的准确定义:

InsertParagraphSeparator Enter Enter Enter Enter (none)
InsertLineSeparator Shift+Enter Meta+Enter Shift+Enter Shift+Enter (none)

所以按下“Shift+Enter”和按下“Enter”结果是不同的。 这种不同从外表看不出来, 但和codeeditor中实现显示行号的代码结合一下, 就明白无误了。

解决的方法比较曲折(当然可能有更好的方法等着大家去探索), 除了要遍历每个block, 还要用QTextBlock的方法去遍历每个QTextLine。 另外一个让人头疼的地方是还要计算出每行的y坐标, 好在合适的地方画上这个行号。 多说无益, 代码说话:


QTextBlock block = document()->begin();
int top = 0;
QTextCursor cursor(block);
cursor.setPosition(0);//move to the beginning of the document
qWarning() << document()->lineCount() << document()->blockCount();
int linenum = 0;
while(linenum < document()->lineCount())
{
for( int i = 0 ; i < block.lineCount(); i ++)
{
QTextLine line = block.layout()->lineAt(i);
//qWarning() << line.rect().toRect() << "x,y:" << line.x() << line.y();
int dx = blockBoundingGeometry(block).x();
int dy = blockBoundingGeometry(block).y();
//qWarning()<< "block offset:" << dx << dy << "content offset:" << contentOffset();
top = line.rect().translated(contentOffset()).translated( dx,dy).y();
painter.setPen(Qt::black);
painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),
Qt::AlignRight, QString::number( linenum +1));
linenum ++;
}
block = block.next();
if(!block.isValid())
{
break;
}
}

by shiroki Tags: , , ,
Posted on July 6th, 2010 in C++, Qt技术 | 4 Comments »

Qt MySQL数据库编程

今天在Linux下测试了Mysql数据库与Qt结合的应用练习,Qt经常要与数据库打交道,如Oracle(甲骨文公司数据库巨人)、 SQL(中大型数据库)、mySQL(小型关系型数据库管理系统)、Access(小到办公软件的office数据库access)。经常使用的客户端数 据库驱动有ODBC、MySQL、SQLite等。现在重点介绍MySQL,默认的情况是没有安装MySQL的驱动的,只用一个SQLite嵌入式数据库 可以编写以下代码显示数据库驱动。

#include <QApplication>
#include <QDebug>
#include <QtSql>
int main(int argc,char *argv[])
{
QApplication app(argc,argv);
qDebug()<<”Available drivers:”; //输出有效的数据库驱动
QStringList drivers = QSqlDatabase::drivers(); //用字符列表的形式将SQL数据库设备驱动列出来
foreach(QString drivers,drivers); //foreach语句为数组或对象集合中的每个元素重复一个嵌入语句组,foreach语句用于循环访问集合以获取所需信息。
qDebug()<<”\t”<<drivers;
return app.exec();
}

QtSql是数据库类的集合,要使用到因此要添加模块头文件#include ,创建工程文件时也要选中Sql库,或在*.pro中的编译入口input下方添加QT += sql
QMYSQL和QMYSQL3先前是没有的,编译安装QMYSQL驱动后就有,怎么安装?

Read the rest of this entry »

by chenboqiang Tags: ,
Posted on July 2nd, 2010 in Linux技术, Qt技术 | 6 Comments »

Nokia Qt SDK的远程编译功能

什么是远程编译

远程编译是指在客户端将源代码提交到服务器,在服务器端进行编译,将编译好的可安装程序下载到本地。 这样做有几个好处

  • 很好的兼容性。服务器端由官方维护,开发环境能够保持和手机运行环境的一致性
  • 良好的可配置性。在客户端的开发者,只需配置一下服务器的编译平台,就能够生成不同的代码。
  • 跨平台开发。 开发者无论是Windows/Mac/Linux操作系统,只需提交代码,即可得到目标平台的代码。目前Mac/Linux还不提供Symbian的编译器,但是使用远程编译你也能很方便在Mac/Linux平台下开发Symbian应用。
  • 目前Nokia Qt SDK里已经集成了远程编译,本文将介绍在Nokia Qt SDK中如何使用远程编译。

    使用远程编译

    SDK 安装选项

    要使用远程编译,需要在安装Nokia Qt SDK的时候将远程编译功能给选上,在安装类型上选择 Custom

    在安装组件中,将Remote Compiler选上

    激活远程编译

    要使用远程编译功能,需要你拥有一个诺基亚论坛帐号,然后利用它进行授权使用,配置方法: 主菜单->Tools->Options->Projects->Remote compiler

    如果配置成功,上图中Logout字样会变亮。此时当你新建一个工程的时候你会看到多出来一些”Remote Compiler”的Qt版本

    如果是已经创建好的工程,也可以通过项目的编译选项添加”Remote Compiler”的支持

    在设置了Remote Compiler支持后,可以为远程支持设置不同的Qt平台.如Maemo/S60 3rd/S60 5th等

    执行编译则和在本地编译没什么区别,点击榔头编译按钮就可以。编译完成会生成 .sis(Symbian)或.deb(Maemo)文件。可以直接安装到手机上。

    注意

    如果你的网络需要代理才能访问Internet,那么同样在配置诺基亚论坛帐号授权时,需要在那里填入代理服务器的相关信息。

    by 臭虫 Tags: , , ,
    Posted on June 29th, 2010 in Qt技术, s60 | No Comments »

    Linux下minicom超级终端的安装及使用

    Minicom 的简单介绍及其使用方法

    文档整理作者:陈博强
    2010-06-23

    Minicom目录:
    <一>Minicom的简介
    <二>Minicom的安装
    <三>Minicom的串行端口的设置
    <四>Minicom的使用
    (1)minicom界面介绍
    (2)minicom的参数设置
    (3)minicom的测试

    <一>Minicom的简介

    Minicom先进系统(Minicom Advanced Systems)是一家Intel创投公司(Intel CapitalPortfolio),是针对带外服务器管理领域的数字和模拟KVM解决方案领先提供商。另外,Minicom同时也是针对数字告示领域的音视频和串口信号分配系统主导厂商。

    Minicom公司成立于1987年,总部位于以色列耶路撒冷,拥有一座3600平米的办公大楼,包括研发、市场、销售和物流等部门。此外Minicom在欧洲和美国具有区域总部,在英国、意大利、法国和德国和中国具有销售支持队伍。在2005年,Minicom收购了Replicom公司,作为专注于IP技术的研发中心。历经20年的发展以及遍及全球50多个国家的业务,Minicom的产品已经销售到上千个数据中心,无论小公司还是大型跨国企业。 Linux下的Minicom的功能与下的超级终端功能相似,适于在通过超级终端对设备的管理以及对嵌入操作系统的升级,现写出Minicom的使用手册:

    <二>Minicom的安装

    安装Red Hat Linux 9.0的自动带的minicom-2.00.0-12.i386.rpm安装包,将第一张镜像盘挂在到/mnt/cdrom临时文件系统的光盘挂载点。
    #mount /dev/cdrom /mnt/cdrom
    //挂载光盘设备
    #cd /mnt/cdrom/RedHat/RPMS/
    //切换到安装包目录
    #find minicom*
    //在当前目录查找以minicom开头的安装包
    #rpm –ivh minicom-2.00.0-12.i386.rpm
    //安装minicom超级终端软件,如果有依赖文件可先安装第三张镜像盘的辅助安装的依赖文件的安装包rpmdb-redhat-9-0.20030313.i386.rpm,执行rpm –ivh rpmdb-redhat-9-0.20030313.i386.rpm安装好后,然后切换到第一张镜像安装盘,安装minicom超级终端,用一下的命令rpm –ivh –aid minicom-2.00.0-12.i386.rpm.如果不想敲太多的代码,输入安装包的前几个字母,按Tab键进行补全命令。

    源码包方式:
    https://alioth.debian.org/frs/download.php/3195/minicom-2.4.tar.gz
    #tar –zxvf minicom-2.4.tar.gz
    //解压minicom安装包
    #cd minicom-2.4
    //切换到解压minicom-2.4目录
    #./configure
    //执行./configure检测编译所需的库函数及头文件,可以制定安装目录,如果不指定则默认安装包安装目录。最后生产Makefile文件
    #make
    //编译源代码
    #make install
    //安装编译后的软件。

    Read the rest of this entry »

    by chenboqiang Tags: , ,
    Posted on June 24th, 2010 in Linux技术 | 2 Comments »