QT应用设计——HexoBlogClient

CSDN仅用于增加百度收录权重,排版未优化,日常不维护。请访问:www.hceng.cn 查看、评论。
本博文对应地址: https://hceng.cn/2017/10/12/QT应用设计——HexoBlogClient/#more

本文主要记录采用QT开发的hexo博客管理客户端——HexoBlogClient。

0.初衷

做嵌入式这行,如果做界面,几乎只有两个选择:Qt和Android。
所以感觉学习下Qt还是很有必要的,顺便回忆点C++。

国庆节前打了鸡血一样疯狂的学了一周Qt,学了后想做个简单的东西练练手。
所做的东西一定要是能解决我的某些痛点的,这样才会让我动力去做。

思来想去,每次写博客,需要打开Git Bash,输入创建命令、构建、本地预览、发布、备份……
虽说之前GitHub+Hexo搭建及优化——5-5脚本自动化中采用了bat脚本一键完成清理、构建、发布这些操作,但每次要打开Git Bash,进入指定路径,输入脚本运行,还是挺麻烦的。

So,搞个博客客户端一键操作似乎更方便点 = =

1.设计思路

写博客,我一般的完整步骤是:

新建博客->编辑博客->如果有图片需上传到图床、有代码需上传到GitHub->清理原来博客的生成的静态页面->生成新的静态页面->本地预览->根据预览效果继续编辑->满意后再次清理、生成静态页面->发布博客(GitHub和Coding)->备份本地的所有源文件到Coding私有库->访问博客查看。

因此博客客户端首先应该很流畅的实现上面的工作流,其次才是锦上添花的添加其它功能。

a:本地界面

  • a1:打开这个客户端,首先这个页面应该显示出我的文章列表;
  • a2:实现新建博客文章编辑博客文章等对文章的常用操作;
  • a3:实现常用的清理生成预览发布备份等功能;

b:图床界面

  • b1:博客文章采用的Markdwon格式,图片需要先保存到图床,然后引用链接。现在的图床方案是上传到七牛。
  • b2:在这个界面,需要将图片 通过拖拽/资源管理器 的方式上传到七牛空间,并且按照当前的日期,指定路径格式,如:image/blog/170915/1.jpg;
  • b3:返回链接地址
  • b4:能够管理已上传的图片(比如跳转到七牛的存储空间);

c:代码界面

  • c1:显示出本地代码,通过拖拽/资源管理器 的方式增减/编辑代码
  • c2:上传到GitHub;
  • c3:打开GitHub、Coding;

d:设置界面

  • d1:设置相关的路径,比如博客路径;
  • d2:设置图床的配置文件

e:关于界面

  • e1:版本、版权信息
  • e2:主页跳转
  • e3:获取指定文件;

f:其它

  • f1:修改应用图标

2.程序代码设计

创建好Qt工程后,工程项目下会有四类文件:pro工程文件头文件源文件界面文件
直接打开界面文件的mainwindow.ui,在上面拖动控件,实现界面的设计,再在源文件mainwindow.cpp编辑代码,完成功能的设计。

2.1 修改应用程序图标

先做个简单的,修改应用程序的图标。
图标显示有两个,一个是打开程序后,在程序左上角显示的图标,一个是在资源管理显示代表该程序的图标。

首先要准备个ico图片文件,然后把图片加入到工程项目中。
在项目中,点击该工程,右键,添加新文件。
选择Qt的Qt Resource File,名字写image,之后就会在工程项目生成一个资源文件:image.qrc。
再选中image.qrc右键,添加现有文件,选择准备的hexoblogclient.ico图标,这样就将图标添加进了工程。

  • a:修改程序左上角图标
    修改源代码mainwindow.cpp,设置打开程序后左上角的图标和显示的文字:
    {% codeblock lang:c%}
    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);

    this->setWindowIcon(QIcon("?/image/hexoblogclient.ico"));//设置图标
    this->setWindowTitle(“HexoBlogClient”);//设置名字
    }
    {% endcodeblock %}

  • b:修改应用程序图标
    在工程目录下创建一个appicon.rc文件,文件内容如下:

IDI_ICON1   ICON    DISCARDABLE "image/hexoblogclient.ico"

再在HexoBlogClient.pro文件添加如下代码:

RC_FILE += \
    appicon.rc

此时重新编译,应用程序图标也变成了ico图案。

2.2 本地界面

  • 界面设计
  1. 使用tabWidget控件作为每个界面的容器;
  2. 使用treeView控件显示文章列表;
  3. 使用pushButton控件作为按键;
  4. 使用label控件显示当前文章总数和时间;

效果如下:

  • 功能设计
    实例化一个QFileSystemModel类,筛选出*.md文件,指定文件路径,隐藏其它Column(也就是只显示文件名,不显示大小、日期等信息),然后以日期为标准,降序排列,最后将信息显示到treeView上。
    {% codeblock lang:c %}
    QFileSystemModel *model1 = new QFileSystemModel();
    model1->setRootPath(“E:/hceng blog/blog/source/_posts”);

    QStringList nameFilter1;
    nameFilter1 << “*.md”;
    model1->setNameFilterDisables(false);
    model1->setNameFilters(nameFilter1);//筛选文件类型
    ui->treeView1->setModel(model1);
    ui->treeView1->setRootIndex(model1->index(“E:/hceng blog/blog/source/_posts”));//指定路径
    ui->treeView1->setColumnHidden(1,true);//隐藏显示
    ui->treeView1->setColumnHidden(2,true);
    ui->treeView1->setColumnHidden(3,true);

    ui->treeView1->setSortingEnabled(true);//使能排序
    ui->treeView1->sortByColumn(3, Qt::DescendingOrder);//以时间作为依据排序;升序:Qt::AscendingOrder 降序:Qt::DescendingOrder
    {% endcodeblock %}

接下来是8个功能按键,很多是直接调用的bat脚本实现功能的。

首先是“新建”按钮,获取输入的标题,然后判断是否为空以及是否按下“确定”,这里直接创建了个新的Markdwon文件,然后写入基本的模板格式。
{% codeblock lang:c %}
void MainWindow::on_pushButton11_clicked()
{
bool ok;
QString text = QInputDialog::getText(this, tr(“新建博客”),tr(“请输入标题:”), QLineEdit::Normal,NULL, &ok);

if ( ok && !text.isEmpty() )
{
    /*
        ---
        title: "格式"
        date:2017-10-11 15:11:33
        tags:
             - xx
        toc: true
        ---
        summary
        <!-- more -->
     */

    QDateTime time = QDateTime::currentDateTime();
    QString strTime = time.toString("yyyy-MM-dd hh:mm:ss ");
    QFile namefile("E:\\hceng blog\\blog\\source\\_posts\\"+text+".md");
    //qDebug()<<strTime;
    if (!namefile.open(QIODevice::WriteOnly | QIODevice::Truncate))
        return;
    QTextStream out(&namefile);
    out<<"---"<<'\n'<<"title: \""+text+"\""<<'\n'<<"date: "<<strTime<<'\n';
    out<<"tags: "<<'\n'<<"     - xx"<<'\n'<<"toc: true"<<'\n'<<"---"<<'\n';
    out<<"summary"<<'\n'<<"<!-- more -->"<<'\n';
    namefile.close();
}
else if(ok && text.isEmpty() )
{
    QMessageBox::information(this,"信息","请输入标题.");
}
else
{
    return;
}

}
{% endcodeblock %}

然后是“编辑”按键,先获得当前treeView选择的文件,再通过桌面服务使用默认程序打开该文件。
{% codeblock lang:c %}
void MainWindow::on_pushButton12_clicked()
{
QString currentFilePath = model1->filePath(ui->treeView1->currentIndex());
if (!currentFilePath.isEmpty())
{
qDebug()<<“file://”+currentFilePath;
QDesktopServices::openUrl(QUrl(“file:///”+currentFilePath));
//QDesktopServices::openUrl(QUrl(“file:///E:/hceng blog/blog/source/_posts/测试文章.md”));
}
}
{% endcodeblock %}

清理&重构”按键调用的脚本执行,等同执行的hexo c & hexo g,最后使用QMessageBox显示截取的部分数据;调用cmd.exe的时候,在纠结使用startDetached还是start,前者是完全独立的启动,后者类似调用。执行脚本需要一定时间,通常都是数秒以上,使用start会出现未响应的情况,但如果使用startDetached可能会多次按该按键,导致启动多次,不知道什么时候完成。最后还是选的start

{% codeblock lang:c %}
void MainWindow::on_pushButton13_clicked()
{
ui->pushButton13->setText(“请等待……”);

QTime dieTime = QTime::currentTime().addMSecs(100);//延时0.1s
while( QTime::currentTime() < dieTime )
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);

QProcess *process=new QProcess(this);
//process->startDetached("cmd.exe", QStringList() << "/c" << "D:\\git\\qt\\HexoBlogClient\\bat\\clean_creat.bat");
process->start("cmd.exe", QStringList() << "/c" << "D:\\git\\qt\\HexoBlogClient\\bat\\clean_creat.bat");
process->waitForFinished();

ui->pushButton13->setText("清理&&重构");

QString strTemp=QString::fromLocal8Bit(process->readAllStandardOutput());
//strTemp = strTemp.section('O',-1,-1);
strTemp = strTemp.section('l',-2,-1);
qDebug()<<strTemp;

QMessageBox testMassage;
testMassage.setText(strTemp);
testMassage.exec();

}
{% endcodeblock %}

预览/停止”按键也是调用的脚本的命令:hexo s,关闭的时候通过读取进程列表,关闭指定端口的进程。实测中,有一定概率误关掉整个浏览器。
{% codeblock lang:c %}
void MainWindow::on_pushButton14_clicked()
{
if(pushButton14Flag == 0)
{
QProcess *process=new QProcess(this);
process->start(“cmd.exe”, QStringList() << “/c” << “D:\git\qt\HexoBlogClient\bat\view.bat”);
process->waitForFinished();

    /*
    QTime dieTime = QTime::currentTime().addMSecs(1000);//延时1s
    while( QTime::currentTime() < dieTime )
    QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
    */
    QDesktopServices::openUrl(QUrl("http://localhost:4000/"));
    ui->pushButton14->setText("停止");
    pushButton14Flag = 1;
}
else
{
    QProcess *process=new QProcess(this);
    process->start("cmd.exe", QStringList() << "/c" << "D:\\git\\qt\\HexoBlogClient\\bat\\stop_view.bat");
    process->waitForFinished();
    ui->pushButton14->setText("预览");
    pushButton14Flag = 0;
}

}
{% endcodeblock %}

发布”也比较花时间,也是调用脚本的命令:hexo d
{% codeblock lang:c %}
void MainWindow::on_pushButton15_clicked()
{
ui->pushButton15->setText(“请等待……”);

QTime dieTime = QTime::currentTime().addMSecs(100);//延时0.1s
while( QTime::currentTime() < dieTime )
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);

QProcess *process=new QProcess(this);
process->start("cmd.exe", QStringList() << "/c" << "D:\\git\\qt\\HexoBlogClient\\bat\\deploy.bat");
process->waitForFinished();

ui->pushButton15->setText("发布");

}
{% endcodeblock %}

备份”是将整个工程上传到Coding的私有库,原理还是git。
{% codeblock lang:c %}
void MainWindow::on_pushButton16_clicked()
{
ui->pushButton16->setText(“请等待……”);

QTime dieTime = QTime::currentTime().addMSecs(100);//延时0.1s
while( QTime::currentTime() < dieTime )
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);

QProcess *process=new QProcess(this);
process->start("cmd.exe", QStringList() << "/c" << "D:\\git\\qt\\HexoBlogClient\\bat\\bak.bat");
process->waitForFinished();

ui->pushButton16->setText("备份");

}
{% endcodeblock %}

发布&备份”是前面两个的结合。
{% codeblock lang:c %}
void MainWindow::on_pushButton17_clicked()
{
ui->pushButton17->setText(“请等待……”);

QTime dieTime = QTime::currentTime().addMSecs(100);//延时0.1s
while( QTime::currentTime() < dieTime )
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);

QProcess *process=new QProcess(this);
process->start("cmd.exe", QStringList() << "/c" << "D:\\git\\qt\\HexoBlogClient\\bat\\deploy_bak.bat");
process->waitForFinished();

ui->pushButton17->setText("发布&&备份");

}
{% endcodeblock %}

访问”就仅仅是打开博客链接,不用再在浏览器里翻了。
{% codeblock lang:c %}
void MainWindow::on_pushButton18_clicked()
{
QDesktopServices::openUrl(QUrl(“https://hceng.cn/”));
}
{% endcodeblock %}

最下面的统计文件数量和显示当前时间,是个定时任务,每秒都刷新这两个label
文件数量是获取博客文章路径的fileInfoList,然后获得文件数量,再转换成字符类型追加到label中。
{% codeblock lang:c %}
//timeshow
QTimer *timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(timerUpdate()));
timer->start(1000);
{% endcodeblock %}

{% codeblock lang:c %}
void MainWindow::timerUpdate(void)
{
QDateTime time = QDateTime::currentDateTime();
QString strTime = time.toString("yyyy-MM-dd dddd hh:mm:ss ");
ui->label1->setText(strTime);

QDir *dir=new QDir("E:/hceng blog/blog/source/_posts");
QStringList filter;
filter<<"*.md";
dir->setNameFilters(filter);
//QList<QFileInfo> *fileInfo=new QList<QFileInfo>(dir->entryInfoList(filter));
QFileInfoList fileInfoList=dir->entryInfoList(filter);//在qt中有typedef QList<QFileInfo> QFileInfoList;所以两者等价

QString fileCount = QString::number(fileInfoList.count(), 10);
QString strCount = "文章总数:";
strCount.append(fileCount);
ui->label2->setText(strCount);

}
{% endcodeblock %}

2.3 图床界面

2.4 代码界面

2.5 设置界面

2.6 关于界面

3.计划

最近有点忙/懒,图床部分,看了下,要研究下七牛的API,暂时没那个精力。
试着用了下客户端,还是比较满意的,不用打开资源管理器和git-bash了,上传图片和代码,还是和原来一样,觉得不流畅,后面有时间,有精力了再研究。
后面最想做的有两个:

  1. 实现配置文件的读取/写入;
  2. 获取服务器指定图片;

加上国庆,话说有半个月没摸驱动了,Qt暂停下,先玩玩驱动。
目前只完成了第一个主界面,后面的几乎没做,如果有志同道合的朋友可以交流下,一起完成。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值