QT6环境C++实现PDF合并(偷懒版)
市面上PDF合并软件很多,有在线的也有独立的程序。最近学习QTC++,借此机会实现一个简单的PDF合并程序进行练手。之所以说是偷懒版是因为PDF文件处理部分调用了强大的跨平台 PDF 处理工具:cpdf。此为小白练手项目,高手请轻喷哈。{:1_932:}
一、程序界面
二、功能介绍
1.添加文件:点击添加文件按钮可进行PDF文件导入,直接将多个PDF文件拖进来也可以。
2.清除按钮:点击清除按钮可删除当前光标选中PDF文件。
3.上移/下移:点击按钮可以调整合并后PDF所在页面。
4.合并:列表内PDF数量大于2则可以进行合并,点击合并按钮选择文件输出路径。
三、目录结构
PDF-merge
—CMakeLists.txt
—HeaderFile
——mainwindow.h
—Source File
——main.cpp
——mainwindow.cpp
—mainWindow.ui
—cpdf.exe
项目源码
CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(pdf-merge VERSION 0.1 LANGUAGES CXX)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
set(PROJECT_SOURCES
main.cpp
mainwindow.cpp
mainwindow.h
mainwindow.ui
)
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(pdf-merge
MANUAL_FINALIZATION
${PROJECT_SOURCES}
)
# Define target properties for Android with Qt 6 as:
# set_property(TARGET pdf-merge APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
# ${CMAKE_CURRENT_SOURCE_DIR}/android)
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
else()
if(ANDROID)
add_library(pdf-merge SHARED
${PROJECT_SOURCES}
)
# Define properties for Android with Qt 5 after find_package() calls as:
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
else()
add_executable(pdf-merge
${PROJECT_SOURCES}
)
endif()
endif()
target_link_libraries(pdf-merge PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
# If you are developing for iOS or macOS you should consider setting an
# explicit, fixed bundle identifier manually though.
if(${QT_VERSION} VERSION_LESS 6.1.0)
set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.pdf-merge)
endif()
set_target_properties(pdf-merge PROPERTIES
${BUNDLE_ID_OPTION}
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
include(GNUInstallDirs)
install(TARGETS pdf-merge
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
if(QT_VERSION_MAJOR EQUAL 6)
qt_finalize_executable(pdf-merge)
endif()
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDragEnterEvent>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
enum movetype{
movedown,
moveup
};
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void utilFileMove(movetype mt,qint8 currentnum);
private slots:
void on_merge_btn_clicked();
void on_fileOpen_btn_clicked();
void on_clear_btn_clicked();
void on_up_btn_clicked();
void on_down_btn_clicked();
private:
Ui::MainWindow *ui;
protected:
virtual void dragEnterEvent(QDragEnterEvent* event) override;
virtual void dropEvent(QDropEvent* event) override;
};
#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include "QProcess"
#include "QMessageBox"
#include "QFileDialog"
#include<QMimeData>
#include<QMimeDatabase>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
//点击合并按钮进行PDF文件合并
void MainWindow::on_merge_btn_clicked()
{
QProcess process;
QStringList arguments;
//获取listview中pdf路径的数量
//数量至少两个进行合并操作
qint8 pdfcount=ui->pdfPathView->count();
switch (pdfcount) {
case 0:
QMessageBox::information(this,"请先添加PDF","请先添加PDF再合并!");
break;
case 1:
QMessageBox::information(this,"PDF数量太少","至少添加两个PDF才能合并!");
break;
default:
QStringList filepaths;
for(qint8 i=0;i<pdfcount;i++){
//获取每一个pdf完整路径存入filepaths中
filepaths.append(ui->pdfPathView->item(i)->text());
}
//保存文件的完成路径
QString savePath = QFileDialog::getSaveFileName(this,"请选择保存路径及名称","","PDF文件(*.pdf)");
//路径不为空进行合并操作
if(!savePath.isEmpty()){
arguments<<filepaths<<"-o"<<savePath;
QProcess::startDetached("./cpdf.exe",arguments);
qDebug()<<"合并后文件为"<<savePath;
}
break;
}
}
void MainWindow::on_fileOpen_btn_clicked()
{
QStringList fileNames={};
fileNames= QFileDialog::getOpenFileNames(this, QStringLiteral("选择多文件对话框!"), "F:",QStringLiteral("PDF文件(*PDF)"));
ui->pdfPathView->addItems(fileNames);
}
void MainWindow::on_clear_btn_clicked()
{
//获取当前选中行
qint8 currentnum=ui->pdfPathView->currentRow();
//未选中currentnum值为:-1
if(currentnum==-1){
QMessageBox::information(this,"请选择","请选中文件再删除!");
//有选中行,currentnum值为对应序号
}else {
ui->pdfPathView->takeItem(currentnum);
}
qDebug()<<currentnum;
}
void MainWindow::on_up_btn_clicked()
{
movetype mt=moveup;
qint8 currentnum=ui->pdfPathView->currentRow();
if(currentnum!=0){
this->utilFileMove(mt,currentnum);
}
}
void MainWindow::on_down_btn_clicked()
{
movetype mt=movedown;
qint8 currentnum=ui->pdfPathView->currentRow();
qint8 listcount=ui->pdfPathView->count()-1;
if(currentnum-listcount!=0){
this->utilFileMove(mt,currentnum);
}
}
void MainWindow::utilFileMove(movetype mt,qint8 currentnum){
//当前信息
auto *citem = ui->pdfPathView->item(currentnum);
qDebug()<<currentnum;
QListWidgetItem *nextitem;
switch (mt) {
case movedown:
nextitem = ui->pdfPathView->item(currentnum+1);
break;
case moveup:
//前一条信息
nextitem = ui->pdfPathView->item(currentnum-1);
break;
default:
break;
}
auto itemtmp= citem->text();
citem->setText(nextitem->text());
nextitem->setText(itemtmp);
//当前选定移到前一个
ui->pdfPathView->setCurrentItem(nextitem);
}
void MainWindow::dragEnterEvent(QDragEnterEvent* event){
//允许主窗口接收文件
event->acceptProposedAction();
}
void MainWindow::dropEvent(QDropEvent* event){
QMimeDatabase db;
auto urllist=event->mimeData()->urls();
for(const QUrl &ur:urllist){
auto tp=db.mimeTypeForUrl(ur);
if(tp.name()=="application/pdf"){
ui->pdfPathView->addItem(ur.toString(QUrl::PreferLocalFile));
}else{
QMessageBox::information(this,"文件错误",ur.fileName()+": 非pdf格式文件,已剔除");
}
//qDebug()<<tp.name();
}
}