说明
Qt官方的制作文档非常详细,而且可以搜索文件内容,格式为*.qch,如果直接双击打开的话实际上是sqlite3数据库文件。开发OpenCV时需要查找函数资料,在线和离线的不太方便。所以,我打算制作一个参考文档快速批量制作软件。
qch文件制作是先将参考文档按照目录制作*.qhp文件,如何使用Qt自带软件qhelpgenerator生成qch文件。
qhp格式为XML,示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <?xml version="1.0" encoding="GB2312"?> <QtHelpProject version="1.0"> <namespace>bookmisClient.myhelp</namespace> <virtualFolder>doc</virtualFolder> <filterSection> <toc> <section title="首页" ref="./demoHtml/index.html"> <section title="用户登录" ref="./demoHtml/userlogon.html"></section> <section title="书籍查询" ref="./demoHtml/bookquery.html"></section> <section title="续借书籍" ref="./demoHtml/Renewal.html"></section> <section title="系统管理" ref="./demoHtml/systemmanage.html"></section> <section title="日志管理" ref="./demoHtml/log.html"></section> <section title="关于" ref="./demoHtml/about.html"></section> </section> </toc> <keywords> <keyword name = "登录" ref="./demoHtml/userlogon.html"></keyword> <keyword name = "续借" ref="./demoHtml/Renewal.html"></keyword> <keyword name = "日志" ref="./demoHtml/log.html"></keyword> </keywords> <files> <file>demoHtml/*.html</file> <file>image/*.png</file> </files> </filterSection> </QtHelpProject>
|
重要的有三部分,files部分就是把文件按照目录方式添加进来。keyword部分是关键词部分,用于搜索。section部分是Qt assistant打开是显示的目录结构。title和name部分可以直接使用文件名,而且只能是HTML文件。
那么文件开发流程是:
1、创建XML格式数据并驻留内存
2、遍历文件夹,对于每个文件转到3
3、提取每个文件的相对于基本目录的路径
4、提取文件名(不包括格式后缀)
5、如果是HTML文件,则添加keyword、section、files模块数据
6、如果不是HTML格式,只添加files模块数据
7、遍历完成,保存数据到文件*.qhp
8、执行qprocess语句qhelpgenerator a.qhp -o b.qch
9、执行完毕
然后就可以使用qch格式文件了。
代码写完之后,发现就是简单的XML格式开发。
开发与解析
首先创建一个空白的Qt widget项目。
Url栏显示需要制作帮助文档的文件目录,通过Folder按钮获取
1 2 3 4
| basePath = QFileDialog::getExistingDirectory(this,tr("Open"),fileFullPath); if(basePath.isEmpty()) return; ui->lineUrl->setText(basePath); ui->lineResultPath->setText(basePath);
|
Result栏显示*.qch格式文件存放位置,上一步是文件夹(比如:/home/jackey/opencv/4.3.0/
),我们需要指定文件名(比如:/home/jackey/opencv/4.3.0/opencv.qch
)。可以直接输入,也可以通过Open按钮选择
1 2 3 4 5
| ui->lineResultPath->clear(); QString resultPath = QFileDialog::getOpenFileName(this,tr("Open"),fileFullPath); if(resultPath.isEmpty()) return; resultFullPath = resultPath; ui->lineResultPath->setText(resultPath);
|
namespace栏是指定之前提到的XML模板文件<namespace></namespace>
中间的文字,填什么就是什么)。
下面的文本框是日志部分,用于输出每个阶段的运行结果。
根据之前的开发流程,先遍历文件夹里面的所有文件,如果是HTML格式就添加keyword字段和section字段,同时将遍历的所有格式文件都添加到files字段中。
在正式获取文件夹中文件之前,应该先有XML格式的文件,如何按照规则写入数据就可以了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| bool MainWindow::initXML() { QDomProcessingInstruction instruction; instruction=doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\""); doc.appendChild(instruction);
QDomElement root = doc.createElement("QtHelpProject"); root.setAttribute("version","1.0"); doc.appendChild(root);
QDomElement ns=doc.createElement("namespace"); QDomText text=doc.createTextNode(ui->lineNamespace->text()); ns.appendChild(text); root.appendChild(ns);
QDomElement vf = doc.createElement("virtualFolder"); QDomText vfText = doc.createTextNode("doc"); vf.appendChild(vfText); root.appendChild(vf);
QDomElement fs = doc.createElement("filterSection"); QDomElement toc = doc.createElement("toc");
fs.appendChild(toc); QDomElement kw = doc.createElement("keywords");
fs.appendChild(kw); QDomElement files = doc.createElement("files");
fs.appendChild(files); root.appendChild(fs);
log("The basic structure is completed!");
return true; }
|
此XML初始化函数执行完毕后,可以得到一个没有数据只是个模板的qhp文件。
执行结果如下
1 2 3 4 5 6 7 8 9 10
| <?xml version="1.0" encoding="GB2312"?> <QtHelpProject version="1.0"> <namespace>从界面获取</namespace> <virtualFolder>从界面获取</virtualFolder> <filterSection> <toc></toc> <keywords></keywords> <files></files> </filterSection> </QtHelpProject>
|
这是一个基本框架,只要把数据填入,就可以生成qch格式文件了。
递归获取文件夹下文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| void MainWindow::findAllFiles(QString dirPath) { if(dirPath.isEmpty()) return; QDir dir(dirPath); QFileInfoList fileInfoList = dir.entryInfoList(); foreach(QFileInfo fileInfo , fileInfoList){ if(fileInfo.fileName() == "."||fileInfo.fileName()==".."){ continue; } else if(fileInfo.isDir()){ findAllFiles(fileInfo.filePath()); dirCnt++; } else if(fileInfo.isFile()){ bool isValid = false; if(fileInfo.suffix()=="html") isValid=true; QString crtFilePath = fileInfo.filePath(); QString content = crtFilePath.remove(basePath+QDir::separator()); QString title = fileInfo.fileName().split(".").at(0); QString name=title; addFilesNode(isValid,title,name,content); fileCnt++; } } }
|
将填入数据的XML格式文件写入qhp格式文件中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| bool MainWindow::save2file(QString dstPath) { if(dstPath.isEmpty()) throw "There must has dstination file path!"; QFile file(dstPath); if(!file.open(QFile::WriteOnly)){ file.close(); return false; }
QTextStream writeOut(&file); doc.save(writeOut,4); file.close();
log("All data has been saved!"); return true; }
|
然后调用qhelpgenerator进行编译
1 2 3 4 5 6 7 8 9 10 11
| bool MainWindow::generateQch() { QString cmd = QString("qhelpgenerator %1 -o %2") .arg(resultFullPath) .arg(dstFullPath); QProcess pro; pro.start(cmd,QProcess::ReadWrite); pro.waitForFinished(); log(pro.readAllStandardOutput()); return true; }
|
就会生成qch格式文件了。
编译运行
编译,运行,选择文档的父目录,然后生成。
TODO
只是简单的遍历文件夹,无法生成树形结构的参考文档。
参考资料