经过了一个小程序的练手,应该写点实用的东西了。学校里上网需要使用drcom客户端进行登录。虽然sourceforge有一个linux的drcom客户端的开源项目,但是这是一个基于命令行的程序,开始用起来不是很方便。
对drcom-1.4.7的分析:
drcom分为drcomc,drcomd和一个内核模块。没有看过linux内核的编程,内核模块直接略过。drcomd是这个程序的守护程序,负责接收drcomc发送过去的指令,并向服务器提交相应的指令。drcomc是客户端程序,通过命令行参数,向drcomc发送登录、注销和修改密码的指令。两者之间通过UNIX的进程间内部socket进行通信。
最早写drcom的GUI是针对drcom-1.3.7的,那时候自己电脑的内核还是2.6.22的,于是就根据那个版本的drcom写了一个实现drcomc功能的GUI。现在针对drcom-1.4.7的GUI,也仅仅实现了drcomc的功能,所以还不是很方便。但是相比较前面的版本,稍微多加了一点人性化的功能。
首先,加入了修改drcom.conf文件的功能,能够方便的在一个对话框中可视化的修改配置内容。因为drcom-1.4.7中,多加了一个device的选项,以前的mac选项都变成可选的了,但是对于自己修改过mac地址的人来说,mac选项还是必要的,否则drcomd将会使用从设备中读取到的mac地址来连接服务器。因此,通过Qt4的QNetworkInterface类,得到电脑上每一个网络设备的mac地址。
相关代码:foreach(QNetworkInterface interface, QNetworkInterface::allInterfaces())
{
NIC->addItem(interface.name());
}
使用QNetworkInterface的静态函数allInterfaces(),取得电脑上所有的网络设备(包括本地回路)。然后使用Qt的foreach宏,遍历整个列表,将每个设备名添加到NIC中(一个comboBox的对象)。
interface = QNetworkInterface::interfaceFromName(interfaceName);
if(interface.isValid())
{
localMAC->setText(tr("MAC地址:") + interface.hardwareAddress());
}
每次下拉框(comboBox)被改动之后,调用该函数,判断网络接口名是否正确,并读取该网络接口名的mac地址(hardwareAddress)。
配置的设置窗口(没有使用root权限,无法读取/etc/drcom.conf文件)
由于学校的网费充值是通过专门的充值网页进行的,为了方便充值(也借鉴了windows版的drcom),在菜单栏中增加了充值网页这个按钮(Action)。
Qt4.4新增加了对webkit的支持,这使得显示网页变得非常容易:
首先加载显示网页所需的头文件:#include
然后声明一个QWebView的指针,然后加载(QWebView::load())需要打开的地址,最后调用显示函数(QWebView::show()):
QWebView *view = new QWebView(0);
view->load(QUrl("http://xx.xx.xx/"));
view->show();
这里只是简单的显示网页,没有实现一些浏览器的基本功能(比如自动完成表单),因此只需要简单使用QWebView类就可以了,不需要使用其他webkit的类。相关的类还有: QWebFrame(用于控制网页的框架),QWebHistory(操作网页的历史),QWebPage(网页相关)等。
不过,需要注意的是,Qt默认不会加载QtWebkit的链接库,如果需要使用该链接库,需要在.pro文件中添加QT += webkit ,这样才能让qmake在生成Makefile文件的时候,加入对webkit链接库的连接。
使用QtWebkit加载的充值网页
上次的显示网页模块感觉做的不是很人性话,明明可以直接从本地得到用户名和密码,但是却没有能够好好利用这些内容,让用户多输入了这些信息。
为了实现自动填充网页中的表单,找了很长时间。刚开始,没有什么概念,就利用刚刚学到的html知识,直接从QWebView->QWebFrame->QWebFrame,然后从webFrame中提取网页表单中的相关元素,修改网页的源代码之后重新显示。
QString html = parentFrame->toHtml(); //得到html源代码
int pos = html.indexOf("\"name\""); //搜索代码中的"name"字符串(包含引号)
pos = html.indexOf(">",pos); //搜索该输入框的结尾
html.insert(pos," value='xxx' "); //添加value的值
parentFrame->setHtml(html,parentFrame->url());//使用新的html显示,并指定根路径为原URL
这样的方法是可以实现在表单中预填充字符的,但是由于重新调用了setHtml()函数重新加载网页,重新加载完毕后,webView还是会发射loadFinished(bool)信号的。因此,在这个函数中,需要使用一个标记来确定是否是第二次加载网页。(为了提取html,必须将loadFinished(bool)信号连接到自定义的槽,否则在未加载完网页之前调用toHtml()不能得到网页的html代码)。
在网上搜索了关于webkit处理Javascript之后,了解到QWebFrame中还有一个evaluateJavascript()函数,该函数的参数是QString,会将传入的字符串当作Javascript代码进行解析。因此,可以对网页的frame使用该函数,添加Javascript代码,就能很轻松的操作表单了。
parentFrame->evaluateJavascript("document.LOGIN.name.value='xxx'");
view->show();
使用这个函数非常方便,不需要写脚本的标记符,也不用加上“;”(正因为这样,好像不能执行多条Javascript语句)。
终于又为那个程序多加了一个功能,现在只差控制守护进程的功能了。