基于于berkeleydb+qt的智能语音电话薄管理系统

/****************************************************************************

文档作者:罗国辉

软件代码:罗国辉,廖少龙

本文目地:指导大家掌握几点:1.QT编程入门,2.espeak语言库的使用与编程入门,3。berkeleydb使用与编程入门,4.linux C编程,5,嵌入式开发流程

****************************************************************************/

摘  要

        智能语音电话薄管理系统是一个可运行在几乎所有视窗操作系统(包括嵌入式操作系统)的通讯录软件,采用了语音合成技术,能够智能播报相关信息。它以qtopia作GUI开发(包括其中的输入法开发),以Berkeley db作为数据库,并加入了改进的TTS语音库,能够实现对常用联系人的资料管理,包括:添加,查询,修改,删除联系人信息等主要功能。以一种创新的角度实现了嵌入式设备上的信息管理系统,由此,可以很好的实现移动设备上的信息管理,具有很大的实际意义。

 

关键词:Arm;Linux;QT; qtopia;QT/E;TTS;Berkeley DB;电话薄; 智能语音

Abstract

Intelligent voice management system of phone book is a run on almost all GUI operating system (including the embedded operating system), Address Book software, using voice synthesis technology to read the relevant intelligence information. It uses QT for GUI development (including the input method development), Berkeley db as a database, and joined the improvement of the TTS voice, to achieve the common contact information management, including: add, query, modify and delete links Information, and other major features. It was an innovative perspective to achieve the embedded devices on the information management system, which can achieve very good on mobile devices for information management, and it has great practical significance.

 

Keywords:Arm;Linux;QT;qtopia;QT/E;TTS;BerkeleyDB;phonebook;ntelligent voice

 

 

目 录

第1章 绪论

1.1 目前基于嵌入式设备的信息管理系统现状

1.2 软件开发背景

 

第2章 系统方案

2.1软件整体设计方案

2.2 搭建主机-宿机开发环境

2.3 建立tools Chain交叉编译环境

2.4 搭建qtopia交叉编译开发环境

2.5 构建Berkeley db 交叉编译开发环境

2.6 创建TTS语音库

2.7 移植软件依赖库与依赖文件

 

第3章功能与指标

3.1 软件主要功能

3.2 软件设计主要指标

 

第4章 实现原理

4.1 基于qtopia的设计

4.2基于 berkeley db(以下简称DB)的设计

4.3基于TTS语音库的设计

 

第5章 硬件连接框图

 

第6章 软件流程

6.1开发环境搭建

6.1.1 构建Kdevelop IDE综合开发环境

6.1.2 构建Qt Designer  GUI开发环境

6.1.3 建立BerKeley DB编译环境

6.1.4 创建TTS智能语音库

6.2建立开发工程

6.3 编译工程

6.4软件设计简要分析

6.4.1界面设计

6.4.2类结构设计  

6.4.3类定义与个别函数介绍     

6.4.4多线程编程方式

6.5关联窗口信号与相应槽   

6.6数据插入表格方法     

6.7清除表格数据分类处理

6.8编码处理

第7章系统测试方案

7.1 基于PC机的设计方案测试

7.2 基于ARM宿机的设计方案测试

第8章测试设备

第9章测试数据

第10章结果分析

10.1 基于PC机的软件结果分析

10.2 基于ARM的软件结果分析

第11章实现功能

第12章特色

第13章 使用指南

参考文献

 

1章 绪论

1.1 目前基于嵌入式设备的信息管理系统现状

目前嵌入式设备上的信息管理软件大部分是基于QT和其插件sqlite来设计的,这样对于数据库的移植不是很方便,而且很繁杂,而berkeley db是一种简洁的与平台无关的嵌入式数据库,只要生成一个数据库,在无需任何依赖库的情况下运行。极大的方便了管理系统的移植,提高了数据处理速度。为QT+berkeley db的设计模式向移动设备移植做出了率先实验。

 

1.2 软件开发背景  

       Berkeley db是一种极其简洁的嵌入式数据库,而且平台无关,稳定性极强,在开发QT的过程中有了用berkeley db + qt来开发一个信息管理软件的想法,在开发过程中发现其应用很好。为了适应现在消费者对移动设备上的语音的要求,再加入了TTS语音。这样,一个完整的创新的信息管理软件就应运而生。

 

2章 系统方案

2.1软件整体设计方案   

§软件开发基础库:

•(1)                图形库: qtopia

•(2)                数据库:Berkeley DB

•(3)                语音库:智能语音 TTS库

§软件开发环境

(1)IDE软件开发环境

◆ Linux+Kdevelop(Qdevelop)+Qtdesigner

◆ windows+Qdevelop+Qtdesigner

(2)文本编辑开发

◆    Linux+Vim(Emacs或记事本)+GCC

◆    windows+ UltraEdit(或记事本)+GCC

§软件运行环境:

  • (1) 系统:Linux/window/嵌入式系统
  • (2) 依赖库:

◆    qtopia图形库。

◆    数据库:Berkeley DB。

◆    语音库:音频I/O处理库,TTS朗读语音库。

 

2.2 搭建主机-宿机开发环境

§串口连接

      PC与arm串口连接,在linux下面用minicom进行终端操作。

§网络连接

      PC与arm用网线连接,用ftp或者nfs进行文件传输或者文件共享。

§输入设备连接

      用ps2或者USB键盘和鼠标连接,实现文字输入与操作。

2.3建立tools Chain交叉编译环境   

可以下载源码自己编译,或者用eldk工具建立完整的开发工具链,也可以直接用我们做好的环境(tools/toolsChain/arm-Linux-gcc-3.4.1.tar.bz2)。

◆ tar jxvf arm-Linux-gcc-3.4.1.tar.bz2

默认解压到/usr/local/arm/3.4.1/bin/

2.4 搭建qtopia交叉编译开发环境   

◆ tar zxvf qtopia-core-opensource-src-4.3.3.tar.gz

◆ cd qtopia-core-opensource-src-4.3.3/mkspecs/qws/Linux-arm-g++

◆ vi qmake.conf

◆ 由于没有设置相应环境变量,故用绝对路径,在arm-Linux- 前面加上路径/usr/local/arm/3.4.1/bin/

◆cd ../../../   回到源代码根目录

◆./configure -embedded arm -xplatform qws/linux-arm-g++ -depths  8,16,32 -no-qt3support

◆ 配置QT/E

① 在文件qtopia-core-opensource-src-4.3.3/src/gui/embedded/qmouselinuxtp_qws.h中加入

    #define QT_QWS_IPAQ

    #define QT_QWS_IPAQ_RAW

    ② 在文件qmouselinuxtp_qws.cpp里把/dev/h3600_ts替换为自己板子的设备文件,我的板子的设备为/dev/h3600_tsraw,正好与qmouselinuxtp_qws.cpp中使用的设备中一致,就不用改了。

注意:

步骤2中如果只定义了#define QT_QWS_IPAQ则使用的是/dev/h3600_ts,如果两个都定义了则使用的是/dev/h3600_tsraw

③ 配置完成后运行gmake进行编译,编译过程中可能会出现无法找到头文件zlib.h问题,则按①,②所述修改相应文件即可。

④  编译完成后运行 make install进行安装, qtopia-core-opensource-src-4.3.3将被安装到/usr/local/Trolltech/QtopiaCore-4.3.3-arm。

◆ 环境测试

①建立NFS共享目录mkdir /mnt/sharelib

②将local/Trolltech/QtopiaCore -4.3.3-arm全部拷到开发板的NFS启动目录或者作一个ln。

③开启pc主机的nfs服务

    Service portmap start

    Service nfs start

④ 挂载

Mount -t nfs -o nolock 10.10.19.27:/mnt/sharelib /usr

注意:

由于我们前面安装是默认路径,所以我们需要把所需要的库都挂载到/usr默认路径下。若出现: Cannot find font definition file /usr/local/Trolltech/QtopiaCore-4.3.3-arm?则是路径不对,可以按上面方法挂载。

   ⑤在开发板上设置环境变量

#export set HOME=/root

#export set QTDIR=/usr/local/Trolltech/QtopiaCore-4.3.3-arm

#export set QPEDIR=/usr/local/Trolltech/QtopiaCore-4.3.3-arm

#export set QWS_KEYBOARD="USB:/dev/input/event1"

#export set QWS_MOUSE_PROTO="LinuxTP:/dev/h3600_tsraw"

#export set PATH=$QPEDIR/bin:$PATH

#export set LD_LIBRARY_PATH=$QTDIR/lib:$QPEDIR/lib       

    ⑥        

#cd /usr/local/Trolltech/QtopiaCore-4.3.3-arm/examples/mainwindows/application

#./application -qws       

如果可以看到显示屏上出现了一个窗口,说明我们的环境已经搭建好了。

  • ⑦ 接下来,我们就要移植我们自己编译的一个 helloword 例子程序。来进一步验证环境是否处理好了。

测试程序:

 

#include <QtGui/QApplication>

#include <QtGui/QWidget>

#include <QtGui/QLabel>

#include <QtCore/QTextCodec>

#include <QFont>

int main(int argc,char *argv[])

{

    QApplication app(argc,argv);

    QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));

    QWidget *pWidget=new QWidget;

    QLabel label(pWidget);

    QFont font;

    font.setPointSize(12);

    font.setFamily("wenquanyi");

    app.setFont( font );

    label.setText(QObject::tr("您好"));

    pWidget->show();

    return app.exec();

}

 

注意:程序里面必须设置相应字体与编码,否则中文无法显示。

编译: qmake -project

qmake

make

生成可执行文件,拷贝到NFS共享目录/mnt/sharelib下面,按上面介绍方法挂载NFS目录到开发板/usr目录。执行正确,说明QT的开发环境与运行环境都已经完全配好了。

 

2.5 构建Berkeley db 交叉编译开发环境 

◆ 安装

从DB的官方站点http://www.sleepycat.com/下载最新的软件包db-4.6.18.tar.gz解压到工作目录,进入该目录。

#../dist/configure  CC=/usr/local/arm/3.4.1/bin/arm-linux-gcc AR=/usr/local/arm/3.4.1/bin/arm-linux-ar STRIP=/usr/local/arm/3.4.1/bin/arm-linux-strip --host=arm

#make

#make install

Berkeley db缺省把库和头文件默认安装在目录/usr/local/BerkeleyDB.4.6/下

◆移植和测试

如下测试程序实现对BDB的基本操作测试:

#include <db.h>

#include <stdio.h>

#include <stdlib.h>

#include <pthread.h>

void init_DBT(DBT *key,DBT *data)

{

        memset(key,0,sizeof(DBT));

        memset(data,0,sizeof(DBT));

}

void main(void)

{

        DB *dbp;

        DBT key,data;

        u_int32_t flags;

        int ret;

        char *fruit="apple";

        int number=15;

        typedef struct customer

        {

                int c_id;

                char name[10];

                char address[20];

                int age;

        }CUSTOMER;

        CUSTOMER cust;

        int key_cust_c_id=1;

        cust.c_id=1;

        strcpy(cust.name,"peter");

        strcpy(cust.address,"Chian");

        cust.age=32;

        ret=db_create(&dbp,NULL,0);

        flags=DB_CREATE;

        ret=dbp->open(dbp,NULL,"single.db",NULL,DB_BTREE,flags,0);

        init_DBT(&key,&data);

        key.data=fruit;

        key.size=strlen(fruit)+1;

        data.data=&number;

        data.size=sizeof(int);

        ret=dbp->put(dbp,NULL,&key,&data,DB_NOOVERWRITE);

        init_DBT(&key,&data);

        key.data=fruit;

        key.size=strlen(fruit)+1;

        ret=dbp->get(dbp,NULL,&key,&data,0);

        printf("The number = %d/n", *(int*)(data.data));

        if(dbp!=NULL)

                dbp->close(dbp,0);

}

编译:

/usr/local/arm/3.4.1/bin/arm-linux-gcc -o dbtest22 dbtest22.c -I/usr/local/BerkeleyDB.4.3/include/ -L/usr/local/BerkeleyDB.4.3/lib/ -ldb -lpthread

最后把生成的dbtest22 移植到ARM板子上去。运行有如下结果:

[/usr]./dbtest22

The number = 15

说明我们的Berkeley DB能够很正确的移植到目标板上去了。

2.6 创建TTS语音库

  • ◆ 交叉编译audio I/O library
  • (1) 下载:portaudio_v18_1.zip
  • (2) Unzip portaudio_v18_1.zip
  • (3) cd portaudio_v18_1
  • (4) ./configure CC=/usr/local/arm/3.4.1/bin/arm-linux-gcc AR=/usr/local/arm/3.4.1/bin/arm-linux-ar STRIP=/usr/local/arm/3.4.1/bin/arm-linux-strip --host=arm
  • (5) make
  • (6) make install

执行完以上操作后,portaudio 的audio I/O library将被安装到/usr/local/lib和/usr/local/include/。

  • ◆ 交叉编译TTS语音库

(1)下载:espeak-1.37-source.zip

       (2)unzip espeak-1.37-source.zip

       (3)cd espeak-1.37-source/src

(4)cp portaudio18.h  portaudio.h.

注意: The "TTS" program uses the PortAudio sound interface library.  There are two

versions, V18 and V19 and their APIs are different.  Our Linux distributions

use V18 .

•(4)                修改Makefile

指定编译时所需要的库和头文件并指明编译环境:

CXX=/usr/local/arm/3.4.1/bin/arm-linux-g++

LIB_AUDIO=-L/usr/local/lib -lportaudio

(5) make

(6) make install

  • ◆ 移植相应的库和espeak-data到目标板上

从源代码包里可以看出相应文件默认安装路径:

PREFIX=/usr

BINDIR=$(PREFIX)/bin

INCDIR=$(PREFIX)/include/espeak

LIBDIR=$(PREFIX)/lib

DATADIR=$(PREFIX)/share/espeak-data

把/share/espeak-data和生成的语音动态库libespeak.so*以及测试程序espeak 拷贝到NFS共享目录/mnt/sharelib下面,把相应的库和QT的库放在一起,按前面所提到的方法挂载到目标板上的/usr目录。

 

  • ◆ 测试

设置环境变量。执行我们写好的Shell脚本arminit 即可。脚本内容如下:

#!/bin/sh

ln -s /dev/sound/dsp /dev/dsp

export set QTDIR=/usr/local/Trolltech/QtopiaCore-4.3.3-arm

export set QPEDIR=/usr/local/Trolltech/QtopiaCore-4.3.3-arm

export set PATH=$QPEDIR/bin:$PATH

export set LD_LIBRARY_PATH=$QTDIR/lib:$QPEDIR/lib

export set QWS_KEYBOARD="USB:/dev/input/event1"

export set QWS_MOUSE_PROTO="LinuxTP:/dev/h3600_tsraw"

export set PA_RECOMMENDED_OUTPUT_DEVICE="sound:/dev/pa_devs"

 

espeak -v en helloworld

espeak -v zh 你好

中英文发音都很正常。

注意: 程序里设置的默认音频设备是/dev/dsp,所以必须作一个ln。

2.7 移植软件依赖库与依赖文件(直接拷贝我们做好的文件解压缩即可)

◆把Qtopia库拷贝到/mnt/sharelib/下,挂载后即为/usr/local/Trolltech/QtopiaCore-4.3.3-arm/lib。

◆把portaudio库与TTS语音库拷贝到/mnt/sharelib/目录下,挂载后即存在于/usr/local/Trolltech/QtopiaCore-4.3.3-arm/lib目录下。

◆移植espeak-data到 /usr/share/espeak-data/目录。

 

 

3章功能与指标

 

3.1 软件主要功能   

◆ 智能语音电话薄管理系统可运行在几乎所有视窗操作系统,包括嵌入式操作系统。

◆    采用了语音合成技术,能够智能播报相关信息。

◆    以qtopia作GUI开发(包括其中的输入法开发)。

◆    以Berkeley db作为数据库。

能够实现对常用联系人的资料管理,主要包括:添加,查询,修改,删除联系人信息等主要功能,操作均可用语音提示,由于时间仓促,语音识别部分还未添加上。

3.2 软件设计主要指标

◆    能够成功运行QT程序界面。

◆    能够对联系人信息做添加,查询,修改,删除等常用操作。

◆    能够语音朗读。

 

4章 实现原理

4.1 基于qtopia的设计   

Qt/Embedded的底层图形引擎基于framebuffer。Framebuffer是在Linux内核架构版本2.2以后推出的标准显示设备驱动接口。采用mmap系统调用,可以将framebuffer的显示缓存映射为可连续访问的一段内存储针。由于目前比较高级的ARM体系的嵌入式CPU中大多集成了LCD控制模块,LCD控制模块一般采用双DMA控制器组成的专用DMA通道。其中一个DMA可以自动从一个数据结构队列中取出并装入新的参数,直到整个队列中的DMA操作都已完成为止。另外一个DMA与画面缓冲区相关,这部分由两个DMA控制器交替执行,并每次都自动按照预定的规则改变参数。虽然使用了双DMA,但这两个DMA控制器的交替使用对于CPU来说是不可见的。CPU所获得的只是由两个DMA组成的一个"通道"而已。

Framebuffer驱动程序的实现分为两个方面:一方面是对LCD及其相关部分的初始化,包括画在缓冲区的创建和对DMA通道的设置;另外一方面是对画面缓冲区的读写,具体到代码为read、write、lseek等系统调用接口。至于将画面缓冲区的内容输出到LCD显示屏上,则由硬件自动完成。对于软件来说是透明的。当对于DMA通道和画面缓冲区设置完成后,DMA开始正常工作,并将缓冲区中的内容不断发送到LCD上。这个过程是基于DMA对于LCD的不断刷新的。基于该特性,framebuffer驱动程序必须将画面缓冲区的存储空间(物理空间)重新映射到一个不加高缓存和写缓存的虚拟地址区间中,这样能才保证应用程序通过mmap将该缓存映射到用户空间后,对于该画面缓存的写操作能够实时的体现在LCD上。

在Qt/Embedded中,Qscreen类为抽象出的底层显示设备基类,其中声明了对于显示设备的基本描述和操作方式,如打开、关闭、获得显示能力、创建GFX操作对象等。另外一个重要的基类是QGfx类。该类抽象出对于显示设备的具体操作接口(图形设备环境),如选择画刷、画线、画矩形、alpha操作等。以上两个基类是Qt/Embedded图形引擎的底层抽象。其中所有具体函数基本都是虚函数,Qt/Embedded对于具体的显示设备,如Linux的framebuffer、Qt Virtual Framebuffer做的抽象接口类全都由此继承并重载基类中的虚函数实现。

对于基本的framebuffer设备,Qt/Embedded用QlinuxFbScreen来处理。针对具体显示硬件(如Mach卡、Voodoo卡)的加速特性,Qt/Embedded从QlinuxFbScreen和图形设备环境模板类QgfxRaster继承出相应子类,并针对相应硬件重载相关虚函数。

Qt/Embedded在体系上为C/S结构,任何一个Qt/Embedded程序都可以作为系统中唯一的一个GUI Server存在。当应用程序首次以系统GUI Server的方式加载时,将建立QWSServer实体。此时调用QWSServer::openDisplay()函数创建窗体,在QWSServer::openDisplay()中对QWSDisplay::Data中的init()加以调用;根据QgfxDriverFactory实体中的定义(QLinuxFbScreen)设置关键的Qscreen指针qt_screen并调用connect()打开显示设备(dev/fb0)。在QWSServer中所有对于显示设备的调用都由qt_screen发起。至此完成了Qt/Embedded中QWSServer的图形发生引擎的创建。当系统中建立好GUI Server后,其它需要运行的Qt/Embedded程序在加载后采用共享内存及有名管道的进程通信方式,以同步访问模式获得对共享资源framebuffer设备的访问权。

4.2基于 berkeley db(以下简称DB)的设计

DB的设计思想是简单、小巧、可靠、高性能。如果说一些主流数据库系统是大而全的话,那么DB就可称为小而精。DB提供了一系列应用程序接口(API),调用本身很简单,应用程序和DB所提供的库在一起编译成为可执行程序。这种方式从两方面极大提高了DB的效率。第一:DB库和应用程序运行在同一个地址空间,没有客户端程序和数据库服务器之间昂贵的网络通讯开销,也没有本地主机进程之间的通讯;第二:不需要对SQL代码解码,对数据的访问直截了当。

DB对需要管理的数据看法很简单,DB数据库包含若干条记录,每一个记录由关键字和数据(KEY/VALUE)构成。数据可以是简单的数据类型,也可以是复杂的数据类型,例如C语言中结构。DB对数据类型不做任何解释, 完全由程序员自行处理,典型的C语言指针的"自由"风格。如果把记录看成一个有n个字段的表,那么第1个字段为表的主键,第2--n个字段对应了其它数据。DB应用程序通常使用多个DB数据库,从某种意义上看,也就是关系数据库中的多个表。DB库非常紧凑,不超过500K,但可以管理大至256T的数据量。

DB的设计充分体现了UNIX的基于工具的哲学,即若干简单工具的组合可以实现强大的功能。DB的每一个基础功能模块都被设计为独立的,也即意味着其使用领域并不局限于DB本身。例如加锁子系统可以用于非DB应用程序的通用操作,内存共享缓冲池子系统可以用于在内存中基于页面的文件缓冲。

 

4.3基于TTS语音库的设计   

We use the opensource software to speech the texts,Speak produces good quality English speech and other Languages speech. It uses a different synthesis method from other open source TTS engines, and sounds quite different. It's perhaps not as natural or "smooth", but I find the articulation clearer and easier to listen to for long periods.

A shared library version is also available.

  • Includes different Voices, whose characteristics can be altered.
  • Can produce speech output as a WAV file.
  • SSML (Speech Synthesis Markup Language) is supported (not complete), and also HTML.
  • Compact size. The program and its data, including several languages, totals about 700 kbytes.
  • Can translate text to phoneme codes, so it could be adapted as a front end for another speech synthesis engine.
  • Potential for other languages. Several are included in varying stages of progress. Help from native speakers for these or other languages is welcomed.
  • Development tools available for producing and tuning phoneme data.
  • Written in C++.

It works well as a "Talker" with the KDE text to speech system (KTTS), as an alternative to Festival for example. As such, it can speak text which has been selected into the clipboard, or directly from the Konqueror browser or the Kate editor. A Gnome Speech driver is now available.

 

5章 硬件框图

  • ◆ 系统框图

 系统框图

 

 

◆ 硬件连线图

 硬件实物图

 

6章 软件流程

开发本软件代码需要:C/C++语言 + linux开发知识 + QT4开发知识 + Berkeley DB基本知识+TTS基本语音朗读知识。

 

6.1开发环境搭建

6.1.1 构建Kdevelop IDE综合开发环境

KDevelop项目诞生于1998年,其最初的目的是为KDE提供一套功能强大的集成开发环境。此后,KDevelop采用GPL进行发布,它支持多种编程语言,如:C/C++,Ada, Java, Pascal, Fortran, PHP, Perl, Shell, Python, Ruby,SQL等。截至作者写本文时,KDevelop的稳定版本为3.5.2,读者可以到以下官方网站下载

http://www.kdevelop.org/index.html?filename=3.5/download.html

KDevelop的源码安装与rpm包安装比较麻烦,需要事先安装好一系列的依赖软件,值得庆幸的是一般linux操作系统安装时都可以选择安装上kdevelop,则不必自己动手。当然,如果你安装系统时没有安装上kdevelop又不想处理软件包之间的依赖关系,就可以通过yum方式或者apt方式安装过。

6.1.2 构建Qt Designer  GUI开发环境

Qt Designer是一个功能强大的GUI界面开发工具,它是挪威Trolltech公司的Qt图形软件包的一个组成部分。Qt Designer开发的快速应用程序,界面美观、性能优越,且具有优良的跨平台特性,支持几乎所有的平台。Qt Designer可以单独使用,也可以与微软的Visual Studio和Linux下的KDevelop集成在一起使用,具有快速预览界面、自动布局管理、扩展定制控件和自动生成代码等特点。其特有的信号/槽(Signals/Slots)机制可以进行事件处理和对象之间的消息传递,是Qt Designer的一个重要的特性。截至作者写本文档时,Qt的开源版本为4.4.0,读者可以到以下官方网站下载源代码:

http://wftp.tu-chemnitz.de/pub/Qt/qt/source/qt-x11-opensource-src-4.4.0.tar.gz

下载后,通过以下命令进行解压缩和安装:

# cd qt-x11-opensource-src-4.4.0

# ./configure

# make

# make install

 

QT默认安装在/usr/local/Trolltech/Qt-4.4.0目录。编译完后,源代码不要删除,在以后需要调试到源代码时还可以使用。

安装可能需要比较长的时间。现在的Linux发行版一般带有Qt Designer,例如笔者的

Fedora 8就自带Qt Designer 3,可以通过yum升级到Qt Designer 4,但是经作者测试yum  qt4会造成系统X11不稳定。推荐用源代码安装。

在Windows下,像Visual C++这样的开发工具已经包括了编辑器、编译器以及调试器等一系列的工具,它们是一个独立的整体。而在Linux下,KDevelop只是一个集成开发

环境,当它要生成项目配置文件时需要调用GNU工具autoconf和antomake,当它编

译程序时需要调用GCC或其他编译器,同时还有其他的GNU工具联合工作,它们是整

个Linux操作系统的一部分,这与Windows下的开发工具是有区别的。因此,我们需要

事先安装好这些工具。

安装好QT4后,为了更方便地使用QT,我们需要配置好环境变量。可以在用户的shell启动文件中设置相应环境变量。如果用户使用的shell是bash,则可以在.bash_profile中加入:

export QTDIR=/usr/local/Trolltech/Qt-4.4.0

export PATH=$QTDIR/bin:$PATH

export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH

 

6.1.3 建立BerKeley DB编译环境

这里是PC主机的上的BDB编译,安装它用以对比测试。对于具体交叉编译方法见前文所述,在此不再累述。

从DB的官方站点http://www.sleepycat.com/下载最新的软件包db-4.6.21.tar.gz,解压到工作目录,进入该目录,依次执行下列三条命令即可。

../dist/configure

make

make install

 

执行make uninstall,则可卸载已安装的DB软件。

DB缺省把库和头文件安装在目录/usr/local/BerkeleyDB.4.6/下,使用gcc test.c -ggdb -I/usr/local/BerkeleyDB.4.6/include/ -L/usr/local/BerkeleyDB.4.6/lib/ -ldb -lpthread就可正确编译程序。BDB4.0和平共处。4.6的库是不兼容的。例如打开数据库函数DB->open(),在4.0版本中入参为6个,而在4.6版中则为7个(可自行比较两个库的头文件db.h中DB->open函数的定义)。因为在DB相关的应用程序中,open函数基本上都是要执行的,所以如果函数和版本不匹配,编译肯定会出错。当然,编译完成后,可以使用命令ldd查看库的依赖关系。

6.1.4 创建TTS智能语音库

具体编译方法见前面所述。

PortAudio - portable cross-platform Audio API 网站下载音频I/O口支持动态库。

http://www.portaudio.com/

到以下网站下载程序接口实现作为开发基础

http://espeak.sourceforge.net/

6.2建立开发工程

在linux系统中,可以有多种方法实现工程程序编辑,此处将介绍利用IDE开发环境KDevelop工具建立开发工程。

•(1)               首先打开KDevelop后,选择菜单"工程"|"新建工程"。

•(2)               在"新建新工程"对话框的"所有工程"选项卡中,选择"C++|QMake project|Basic Qt4 Application "选择或者输入存放位置,输入应用程序名称,单击"下一步"按钮,如图4.2.1

 图4.2.1

 

如图4.2.1

•(3)               设置"工程选项",在此处输入QT4的qmake和QT设计器的绝对路径,单击"下一步"按钮,如图4.2.2。

 图4.2.2

 

图4.2.2

•(4)               在".h文件的模板"选项中,可以设置头文件.h的格式。

•(5)               最后单击"完成"按钮,KDevelop会自动生成一个标准C++主程序。

•(6)               然后根据自己需要在右边的qmake管理器里添加头文件和源文件。

到此,KDevelop中已建立了一个KDevelop工程。也就完成了QT的基本开发环境构建。

 

6.3 编译工程

(1)qmake -project

(2)qmake

(3)make

(4)./phonebook(运行)

由于bdb与TTS的头文件与库需要加进来,故需要修改Makefile文件:

添加 -ggdb -I/usr/local/BerkeleyDB.4.6/include/到include头文件处(INCPATH后面)(注意格式)

添加 -L/usr/local/BerkeleyDB.4.6/lib/ -ldb -lpthread到LIBS后面。

添加 -lstdc++ -L .到LIBS后面

注意:

这里编译的都是用于pc机上测试的程序,故对于适用于arm上运行的程序移植方法见前面所述。

 

6.4软件设计简要分析 

为了减轻开发负担,本软件采用qt designer设计界面,然后用KDevelop加入设计好的.ui文件,在KDevelop里实现工程设计。

 

6.4.1界面设计

由于QT designer提供很好的操作环境,这里就不详细介绍界面制作,只对个别问题作简单说明。

(1)使用容器将主窗口与各个分窗口都装入不同的容器,用关闭与打开窗口的方式实现窗口间切换,将主窗口放入frame_1容器,将添加联系人页面放入addFrame 容器,将修改页面放入Mframe容器。这样就可以通过容器激活方法setVisible激活某一窗口,实现窗口切换。

例如:关闭修改与添加容器,以显示主窗口,即可按如下方式设置:

       Mframe->setVisible(false);    

       frame_1->setVisible(true);

       menubar->setEnabled(true);

(2).工具栏需要加入toolTip,当鼠标滑向某一个控件时,则提示操作。

(3)对于控件大小与窗口比例控制,则可以加入一些弹弹簧spacer

(4)对于文本输入控件TextEdit,需要加入Scroll Bar以实现滚动条(直接拖动到TextEdit控件中即可)。

(5)对于icon图标文件,需要加入到资源,否则,程序位置改变后,则图标无法显示。    

 

6.4.2类结构设计  

主要是由两个类组成,CphoneBookwindow类是主要的操作与窗口类,而WorkThread类主要是用于语音朗读。

● 主窗口类:

(1)Base Class(基本窗口类是在qt DESIGNER里定义的)

Ui_phoneBookWindow --CPhonebookwindow

(2) Data Members

Data Members

(3) declaration

 

 

declaration

(4) declaration File

 

 

 

 declaration File

 

 

 

● WorkThread多线程类

(1) Base class

 

 

Base class

 

(2)Data members

)Data members

 

(3) declaration

declaration

 

(4) declaration File

 

declaration File

      

6.4.3类定义与个别函数介绍     

●主窗口类

class WorkThread;//申明多线程类

//主窗口类定义

//================================================

class CPhonebookwindow : public QMainWindow,

                     public Ui_phoneBookWindow

{

       Q_OBJECT

       public:

              CPhonebookwindow(QWidget* = 0);

       private slots:

              //

              void showAll();//显示所有记录的实现函数

              void showhelp();//帮助

              void showAllFind();//显示所有记录的分类判断函数

              void showAbout();//关于

              void doAdd();//添加

              void doFind();//查找

              void addClose();//添加记录窗口关闭

              void doAddPushBtn();//添加

              void doMend();//显示修改前的内容

              void inputMeClose();//添加窗口容器的设置

              void doDelete();//删除

              void mend();//修改

              void aa();//鼠标点击QTableWidget信号

              void vote();//鼠标取值分类处理标志设置

              void classcontacts();//分类显示

              void showContacts();//分类显示处理

       public:

              //berkeley db Parameters

              //===============================

              DB *dbp;//数据库句柄

              DBT key, data;//定义key/data健值对

              int ret;//操作结果判断

              DBC * cur;//游标

              u_int32_t flags;//数据库打开方式

              //标志位

              //===============================

              int mlen;//name长度

              char m[20];

              int morw,mcolumn;//行列数

              bool flagaa;//鼠标是否选择记录标志

              int h;//setRowCount的补丁参数

              int p;//语音开头控制标志

       private:

              WorkThread* threadVector;//定义线程类为主窗口类的一个私有成员

};

在这里我们定义线程类为主窗口类的一个私有成员,这样一来,主窗口类里的其它成员就可以很容易的访问多线程类中的成员。

● 多线程类

 

//多线程类定义

class WorkThread : public QThread

{

       protected:

              void run();//线程执行函数

       public:

              void strncpy0(char *dest, const char *source, int size);//自定义拷贝函数

              void espeakmain(char *playtext);//朗读函数

       public:

              struct customer phonebook;//实例化结构体数据结构

              int flagspeak;//读取内容选择标志位   

};

● 数据结构

//数据处理结构定义

//=========================

typedef struct customer

{

       char name[20];//姓名

       char phone[20];//电话

       char address[30];//地址

       char email[20];//邮件

       char beizhu[40];//备注

       char leibie[10];//类别

};

 

6.4.4多线程编程方式  

可以直接使用C/C++多线程编程,由于QT作了二次封装,使用起来更加方便,这里就直接使用Qthread类。实现方式非常简单,代码如上所写,只需要写一个相应的执行函数,当需要执行这一任务时,就调用Qthread的基类start()函数来启动线程执行函数run(),从而使得线程真正运行。

//线程执行函数,负责语音内容朗读选择

//=================================

 void WorkThread::run()

{

       char temp[30] = "";

       switch(flagspeak)

       {     //信息分类朗读

              //===============

              case 0:

                     strcpy(temp,"欢迎使用电话管理系统");

                     espeakmain(temp);

                     break;    

              case 1:

                     strcpy(temp,"请选择要删除,的,记录");

                     espeakmain(temp);

                     break;    

              case 2:

                     strcpy(temp,"请选择要修改,的,记录");

                     espeakmain(temp);

                     break;    

              case 3:

                     strcpy(temp,"请输入要查找的姓名");

                     espeakmain(temp);

                     break;    

              case 4:

                     strcpy(temp,"没有找到您要的记录");

                     espeakmain(temp);

                     break;    

              case 50:

                     strcpy(temp,"请输入姓名");

                     espeakmain(temp);

                     break;    

              case 51:

                     strcpy(temp,"请输入电话号码");

                     espeakmain(temp);

                     break;    

              case 52:

                     strcpy(temp,"请输入地址");

                     espeakmain(temp);

                     break;    

              case 53:

                     strcpy(temp,"请输入邮件");

                     espeakmain(temp);

                     break;    

              case 54:

                     strcpy(temp,"请输入备注");

                     espeakmain(temp);

                     break;    

              case 55:

                     strcpy(temp,"您要输入的名字已存在");

                     espeakmain(temp);

                     break;    

              case 6:

                     strcpy(temp,"删除成功");

                     espeakmain(temp);

                     break;    

              case 61:

                     strcpy(temp,"修改成功");

                     espeakmain(temp);

                     break;    

              case 62:

                     strcpy(temp,"添加成功");

                     espeakmain(temp);

                     break;    

              case 8:

                     strcpy(temp,"输入太长,请缩减");

                     espeakmain(temp);

                     break;    

              case 7:

                     char phone[] = "的电话是";

                     sprintf(temp,"%s,%s,%s",phonebook.name,phone,phonebook.phone);

                     espeakmain(temp);

                     break;

       }

 

}

 

6.5关联窗口信号与相应槽 

在程序一启动,初始化时就需要关联相应的信号/槽。

信号和槽机制是QT的核心机制。信号和槽是一种高级接口,应用于对象之间的通信,它是QT的核心特性,也 是QT区别于其它工具包的重要地方。信号和槽是QT自行定义的一种通信机制,它独立于标准的C/C++语言,因此要正确的处理信号和槽,必须借助一个称为 moc(Meta Object Compiler)的QT工具,该工具是一个C++预处理程序,它为高层次的事件处理自动生成所需要的附加代码。

在 我们所熟知的很多GUI工具包中,窗口小部件(widget)都有一个回调函数用于响应它们能触发的每个动作,这个回调函数通常是一个指向某个函数的指 针。但是,在QT中信号和槽取代了这些凌乱的函数指针,使得我们编写这些通信程序更为简洁明了。 信号和槽能携带任意数量和任意类型的参数,他们是类型完全安全的,不会像回调函数那样产生core dumps。

所有从 QObject或其子类(例如Qwidget)派生的类都能够包含信号和槽。当对象改变其状态时,信号就由该对象发射(emit)出去,这就是对象所要做 的全部事情,它不知道另一端是谁在接收这个信号。这就是真正的信息封装,它确保对象被当作一个真正的软件组件来使用。槽用于接收信号,但它们是普通的对象 成员函数。一个槽并不知道是否有任何信号与自己相连接。而且,对象并不了解具体的通信机制。

你可以将很多信号与单个的槽进行连接,也可以将单个的信号与很多的槽进行连接,甚至于将一个信号与另外一个信号相连接也是可能的,这时无论第一个信号什么时候发射系统都将立刻发射第二个信号。总之,信号与槽构造了一个强大的部件编程机制。

//关联窗口信号与相应槽

//============================================================   

connect(actAdd,SIGNAL(triggered()),this,SLOT(doAdd()));

//操作菜单里的增加->增加槽函数

connect(checkpshBtn,SIGNAL(clicked()),this,SLOT(doFind()));

//工具栏上的查找按钮->查找槽函数

connect(actMaend,SIGNAL(triggered()),this,SLOT(doMend()));

//操作菜单中的修改->修改槽函数

connect(actDelete_2,SIGNAL(triggered()),this,SLOT(doDelete()));

//操作菜单中的删除->删除槽函数

connect(actExit,SIGNAL(triggered()),this,SLOT(close()));

//操作菜单中的退回->关闭程序槽函数

connect(cecalPushBtn_2,SIGNAL(clicked()),this,SLOT(addClose()));

//添加联系人窗口的取消按钮->关闭添加联系人窗口槽函数

connect(addPushBtn,SIGNAL(clicked()),this,SLOT(doAddPushBtn()));

//工具栏中的增加->增加联系人窗口槽函数

connect(MCaelButton_2,SIGNAL(clicked()),this,SLOT(inputMeClose()));

//修改前信息插入到修改信息编辑框槽函数

connect(tableWidget,SIGNAL(itemSelectionChanged()),this,SLOT(aa()));

//鼠标点击某一个表格,则设置相应标志位,用以判断是否选择了要操作的内容,并显示相应详细信息的槽函数

connect(MpushButton,SIGNAL(clicked()),this,SLOT(mend()));

//工具栏上的修改按钮->修改槽函数

connect(pushButton,SIGNAL(clicked()),this,SLOT(showAllFind()));

//工具栏上的查询所有信息按钮->查询所有信息槽函数

connect(pushButton_2,SIGNAL(clicked()),this,SLOT(doAdd()));

//工具栏上的添加信息按钮->添加联系人槽函数

connect(pushButton_3,SIGNAL(clicked()),this,SLOT(doMend()));

//工具栏上的修改信息按钮->修改联系人槽函数

connect(pushButton_4,SIGNAL(clicked()),this,SLOT(doDelete()));

//工具栏上的删除信息按钮->删除联系人槽函数

connect(actAbout,SIGNAL(triggered()),this,SLOT(showAbout()));

//帮助菜单中的关于->关于槽函数

connect(actUse,SIGNAL(triggered()),this,SLOT(showhelp()));

//帮助菜单中的帮助->帮助槽函数

connect(actspeak,SIGNAL(triggered()),this,SLOT(vote()));

//操作菜单中的语音开关->语音开关槽函数

connect(leibieboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(classcontacts()));

//工具栏上的显示不同类别的所有信息

 

6.6语音朗读线程启动方式 

if(p==1)//如果开关状态为开,则语音提示

       {

                     threadVector->flagspeak = x;//这里的x就是对应不同的语音选项

                     threadVector->start();

}

 

6.6数据插入表格方法 

真正插入就是用setItem方法实现

QTableWidgetItem *name_2=new QTableWidgetItem(QString::fromUtf8(threadVector->phonebook.name));

QTableWidgetItem *phone_2=new QTableWidgetItem(QString::fromUtf8(threadVector->phonebook.phone));

QTableWidgetItem *address_2=new QTableWidgetItem(QString::fromUtf8(threadVector->phonebook.address));

QTableWidgetItem *email_2=new QTableWidgetItem(QString::fromUtf8(threadVector->phonebook.email));

QTableWidgetItem *beizhu_2=new QTableWidgetItem(QString::fromUtf8(threadVector->phonebook.beizhu));

QTableWidgetItem *leibie_2=new QTableWidgetItem(QString::fromUtf8(threadVector->phonebook.leibie));   

tableWidget->insertRow(row);//row为插入的行号

tableWidget->setItem(row,name_2);

tableWidget->setItem(row,1,phone_2);

tableWidget->setItem(row,2,address_2);

tableWidget->setItem(row,3,email_2);

tableWidget->setItem(row,4,beizhu_2);

tableWidget->setItem(row,5,leibie_2);    

 

6.7清除表格数据分类处理  (很重要,否则remove最后一行数据时往往出现异常)

 

if(ret==0)//如果从BDB中删除成功再在table中作remove操作

{

       if(p==1)//如果语音开关状态为开

       {

              threadVector->flagspeak = 6;//读取内容分类

              threadVector->start();//启动线程

       }                                

       if(allRowCount>1)//如果表格中有2行以上的数据则用removeRow()直接删除某一行即可

       {

              //qDebug()<<"row1"<<row;

              //qDebug()<<"row2"<<row;

              tableWidget->removeRow(row);

       }

       else

       {

              h=1;//setRowCount的补丁参数,防止鼠标取值事件导致删除异常

              tableWidget->clear();

              tableWidget->setRowCount(0);

              h=0;

              //tableWidget->horizontalHeaderItem(0)->setText(QString::fromUtf8("姓名"));

       }

}

 

6.8编码处理 

本程序全部采用utf-8编码,所有文字处理都需要作必要转换纺一

如:

strcpy(threadVector->phonebook.name,mendNameLineEdit->text().trimmed().toUtf8());

就可以将姓名输入框中内容取出并转换成utf-8格式

对于程序显示,还必须加入字体,否则中文无法正常显示。

 

7章系统测试方案

7.1 基于PC机的设计方案测试 

测试基于PC机版本的软件功能是否完善,主要包括对数据的操作,中文显示,语音朗读等等。

7.2 基于ARM宿机的设计方案测试 

       测试基于ARM版本的软件功能,对比PC主机的实现来测试ARM上软件运行状况。特别注意所需依赖库的交叉编译,与ARM平台系统结构的差异及音频驱动与音频引擎差异。

 

8章测试设备

对于PC主机软件的测试方法与一般软件一样,只是对arm 上的软件测试,需要特别为arm开发板准备输入设备,主要包括键盘和鼠标。还有一个局域网络。

 

9章测试数据   

所有的测试数据见使用指南一章。

 

软件界面

 

10章结果分析 

10.1 基于PC机的软件结果分析   

◆    对联系人信息常用操作功能实现很完善。

◆    由于QT对行的删除操作的类成员有一定的缺陷,会导致删除最后一行的bug,本软件在此基础上,作出了修正。

◆    语音朗读效果很好。

◆    显示界面友好简洁,速度很快,操作简单。

10.2 基于ARM的软件结果分析   

◆由于arm上面文件系统版本很旧,一些shell的处理很差,会导致一些异常。导致了语音对中文的朗读出现了异常。

◆由于arm上面的qt视窗界面很旧,无法满足我们软件运行的友好环境要求,所以运行效果受到影响,特别是对输入法的处理。

◆其它都很工作良好。

11章实现功能  

本软件主要用于对联系人的信息管理,由些可以很容易地扩展为一个多功能信息管理软件,而且是可跨平台的,适用于几乎所有的平台。具体的功能见第3章所述。

 

 

12章特色    

★ 采用了语音合成技术,能智能的语音播报。

★ 采用QT开发,可用于多操作系统(特别是嵌入式操作系统)。

★ 采用嵌入式数据库berkeley db实现了数据库的文件化。

 

13章 使用指南

主窗口如图3.0

 

软件效果图

 

图3.0

(1)添加联系人:

a.点击"操作"->"增加",即出现添加信息页面。

b.直接点击工具栏中的添加图标,即出现添加信息页面。

如图3.1:

 

添加联系人

图3.1.添加联系人窗口

(2)修改联系人:

a.用鼠标选中表格中的某一行,然后点击工具栏里的修改图标,即可出现信息修改页面。

b.用鼠标选中表格中的某一行,然后点击"操作"->"增加",即可出现信息修改页面。

如图3.2

 

修改联系人

 

图3.2修改联系人窗口

(3)删除联系人:

a.用鼠标选中表格中的某一行,然后点击工具栏里的删除图标,即可出现信息修改页面。

b.用鼠标选中表格中的某一行,然后点击"操作"->"删除",即可出现信息修改页面。

(4)查询特定记录:

在工具栏的查找输入框中输入您需要查找人的姓名,点击它右边的查找按钮即可完成信息查找。

(5)查询所有记录:

直接点击工具栏里的查找所有按钮即可。

(6)查看,复制详细信息:

a.通过左右拉条可以看到所有信息,双击某一表格,右键上下文或者CTRL+C复制信息。

b.点击某一个表格,将会在窗口下文显示该联系人的所有详细信息。

(7)语音控制:

点击"操作"->"语音(开/关)"即可实现语音的开关。

(8)显示某类联系人:

点击工具栏上的下拉列表即可选择要显示的联系人。

(9)注意事项:

将鼠标滑向工具栏上的控件时,即会出现操作提示。

 

 

参考文献

  • [1] 许信顺 贾智平编著, 嵌入式Linux应用编程,机械工业出版社, 2007 年1月
  • [2] 蔡志明等编著,精通Qt4编程,电子工业出版社,2008年1月
  • [3] 倪继利,Qt及linux 操作系统窗口设计,电子工业出版社,2006年4月
  • [4] 杜华,Linux编程技术详解,人民邮电出版社,2007年11月
  • [5] 施聪,嵌入式数据库系统Berkeley DB http://www.ibm.com/developerworks/cn/linux/l-embdb/index.html
  • [6] eSpeak text to speech ,http://espeak.sourceforge.net/
  • [7] 韦东山,嵌入式Linux应用开发完全手册,人民邮电出版社,2008年8月
  • [8] Karim Yaghmour , Building Embedded Linux Systems , 中国电力出版社, 2004 年12月
  • [9] 孙琼 , 嵌入式Linux应用程序开发详解, 人民邮电出版社, 2006 年7月
  • [10] 李亚锋;欧文盛,ARM嵌入式Linux系统开发从入门到精通, 清华大学出版社, 2007 年8月
  • [11] STANLEY B.LIPPMAN,JOSEE LAJOIE, C++ PRIMER (3RD)中文版,中国电力出版社,2005年2月
  • [12]谭浩强,C程序设计(第二版),清华大学出版社,1999年12月  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值