Launchy有道翻译插件开发
一直想做一个方便查词的工具。一开始想借助OSX下面最火的Alfred,做一个插件。结果以为赚便宜淘宝上50块钱买了一个family license,结果被无良奸商骗了。license没几天就失效了,投诉无门。后来发现一直在用的Windows快捷方式神器Launchy,也支持插件开发。于是,锁定目标,做一个Launchy的有道插件。
首先看Launchy插件开发官方页。人家写清楚了环境的版本要求:
For this setup, we require Visual Studio (preferably 2005 as that is what I use) and QT 4.3.3
后来就因为版本问题走了很多弯路。
功能概述
- 快速进入插件 - yd<tab>
- 从剪贴板取单词,或自行输入
- 查单词 - <tab>
- 执行任意结果项均打开单词的有道词典页面
QT环境安装
QT4 vs.QT5
目前QT的最新版本是5.6,所以直接走官方用网络安装的都是QT5。所以一开始,傻乎乎的准备把原先的插件框架写成QT5兼容。QT4到QT5做了大规模的变化,很多特性不兼容。下面是一些参考链接
- 官方指引
- Q_EXPORT_PLUGIN2 to Q_PLUGIN_METADATA
总之捣鼓了很久,最终放弃。
QT安装
QT有多种安装方式:
- 最简单的就是官网,通过网络方式安装,注意选community和open source。其他是要license fee的
- exe安装。以4.8.6为例,在QT archive的网站上可以下载官方用各种编译器编好的二进制安装包。
- 最灵活的安装方式就是编译安装了。去上面archive的网站下载源码。好处是可以编译出自己需要的编译器的版本。具体支持哪些编译平台看源码目录
<Qt>\4.6.0\mkspecs\
,下面列出了所有支持的开发平台。
有一点很有意思的是,在我折腾QT5的时候发现,QT5目前还不支持VS2015的编译平台,最高只支持到VS2013。
回到我们的需求上,可以看到,按照Launchy官方的指点,我们需要VS2005,以及对应的QT库,所以archive页上也没有现成的二进制安装包,只好自己编译。依然有官方指引。其实很容易,所谓会者不难。有几个地方要注意:
- 下载VS2005的时候一定要找靠谱的安装,否则像我一开始装的是个繁中版本,各种错误,让人很是郁闷。
- 一定要从VS的command prompt进去configue和compile。因为VS的command prompt会做很多环境配置。
- x86和x64是不同的command prompt
剩下来的按照官方的指引就可以了,简单看如下:
configure -platform win32-msvc2005
nmake
QT开发环境
官网安装的版本自带了QT Creator。所以一开始都是用他在折腾,感觉用起来还不错,没有VS那么臃肿。换到QT4.8.6以后,可能版本过低,开不起来,所以没办法要切到VS2005底下开发。然后又摸索了一阵,需要安装一个VS的QT插件。后来又是在版本上一番折腾,最终选定1.1.11,配合VS2005使用无压力。
Launchy插件开发
其实很简单,按照作者的推荐,版本一步不差,或者差的不远,都是可以跑起来的。最终版本VS2005+QT4.6.0+qt-vs-1.1.11。
中间试过VS2013,如果整个Launchy用2013编译,插件也用2013编译的话,是可以用的。但是这样移植性太差了,网上下载的Launchy就没法用了。
Launchy插件
简单说一下Launchy的插件结构,以便未来如果要进一步开发又得重新学习:
插件基于消息工作
case MSG_INIT:
init();
handled = true;
break;
case MSG_GET_LABELS: // 每个input可以打label,以后可以根据label来甄别属于哪个插件
getLabels((QList<InputData>*) wParam);
handled = true;
break;
case MSG_GET_ID:
getID((uint*) wParam);
handled = true;
break;
case MSG_GET_NAME:
getName((QString*) wParam);
handled = true;
break;
case MSG_GET_RESULTS:// 在这里为输入插入结果
getResults((QList<InputData>*) wParam, (QList<CatItem>*) lParam);
handled = true;
break;
case MSG_GET_CATALOG: // catalog是Launchy的数据库入口。对于插件数据量不大的话,可以忽略这个
getCatalog((QList<CatItem>*) wParam);
handled = true;
break;
case MSG_LAUNCH_ITEM: // 激发某个结果项,这里要注意InputData的top result
//qDebug()<<"Launch";
launchItem((QList<InputData>*) wParam, (CatItem*) lParam);
handled = true;
break;
case MSG_HAS_DIALOG:
// Set to true if you provide a gui
handled = false;
break;
case MSG_DO_DIALOG:
// This isn't called unless you return true to MSG_HAS_DIALOG
doDialog((QWidget*) wParam, (QWidget**) lParam);
break;
case MSG_END_DIALOG:
// This isn't called unless you return true to MSG_HAS_DIALOG
endDialog((bool) wParam);
break;
还有一些迷信活动
至今没理解是为什么,看下面的代码:
void mypluginPlugin::getLabels(QList<InputData>* id)
{
//此处省略一段代码...
if (id->first().hasLabel(HASH_myplugin))
{
id->first().setTopResult(CatItem("", id->last().getText(), HASH_myplugin, getIcon()));
}
}
加了这一段代码之后,就只出现跟插件有关的结果项,如果没有这一段代码,就会杂七杂八出现很多。所以我说InputData的top result很关键。
调试工具
因为我们是插件开发,没法在线调试,只能用qDebug()<<"proxy: "<<proxy;
打印调试语句。又没有命令行界面,只能借助一个微软的工具叫DebugView,在下面的地址下载。DebugView官方下载地址。
有了他就可以看调试信息输出了。
QT相关
QT调用python
其实就是C++调用python。网上搜到的一堆都大同小异。举个例子QT中 使用c++调用python。最后我失败了,编译成功,运行失败。原因,我总结了一下,其实和QT以及VS搭配使用时版本的问题类似。C++调用python的接口函数都是在python27.lib中定义的。这个lib使用的编译平台,要和你现在使用的编译平台一致。不过看起来蛮诱人的,不过不知道有多少可能能用得上。
QProcess
放弃python27.lib之后,就转到QProcess上来了。这个其实就是QT简单的调用命令行程序。但是这个变态的是一旦命令出错,什么信息也打不出来,别看他有readStandardError接口。在使用QProcess的时候,学习到以下几点:
- Windows底下在代码里要用中文必须在字符串前面加L,如
L"有道翻译"
。这样Windows才能识别到这个是WCHAR,Windows平台的双字节编码 - QT里面所有的QString都是unicode,如
QString::fromWCharArray(L"有道翻译)
QJson
本来打算找一个库来解析有道API返回的json数据,不过后来本着小而美的精神,放弃了解析整个json数据的企图,只单纯的解析多行字符串。不过还是看了一些资料,所以记下来万一以后用得上。
QJson是一个QT的开源库,在git hub上,需要下载源码自己编译。编出来会有一个.lib和一个.dll。分别放到C:\Qt\4.6.0\lib和C:\Qt\4.6.0\bin\底下,并在.pro文件里引用就可以用了。记得哦,与你的主程序用同一个编译平台。另外QT5已经默认内置json解析库了。
使用QJson的方法看官方文档
另外一种解析json数据的思路是用QT4内置的QScriptEngine。没深究过,但知道这个库是让QT更好地和JavaScript融合使用诞生的,具体可以看这个链接-QScriptEngine Printout to String as JSON