Qt版Word文字处理软件

微软公司的Office Word软件是一个通用的功能强大的字处理软件,本项目采用Qt5参照Word开发一个类似的文字处理软件,并添加了如多窗口同时处理等功能。

计划本软件的开发分为下几个阶段进行。

(1)界面设计开发。

包括主窗口程序框架的建立,菜单设计,工具栏设计,工具按钮和状态栏的帮助提示文本,多个文档子窗口的管理和控制等。

(2)文本编辑功能实现。

主要包括文件的建立、打开和保存,文本的剪切、复制和粘贴,操作撤销和恢复等这些最基本的文档编辑功能。

(3)排版美化功能实现。

包括字体选择,字形、字号和文字颜色的设置,文档段落标号和编号的添加,段落对齐方式设置等功能实现。

(4)其他功能的添加

如子窗口背景可显示图片,在进行文字编辑是可自动播放舒缓的音乐等趣味功能。

(5)后期的维护与修饰

  1. 界面设计开发

       菜单系统包括主菜单、菜单项和子菜单三级。部分采用在.ui文件中设计,部分通过代码手动设计(格式与窗口)。

效果图:

菜单运行显示效果示例:

菜单功能项图标:

2.文本编辑功能实现

代码包含第一阶段界面开发:

关于ui文件的使用:

效果图: 

3.排版美化功能实现。

在实现功能的基础上我们增加了背景界面背景美化

 效果图:

 

 4.其他功能的添加

在帮助菜单栏中添加了一个音乐播放的按钮

效果图:

 

代码如下

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include"newwindow.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class QMdiArea;
class EditWindow;
class sound;
class QComboBox;
class QFrontComboBox;
class QFontComboBox;
class QMdiSubWindow;
class QSignalMapper;
class FontSize;
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);

    void createActionsandMenus();//创建一级菜单
    void createActions();  //创建二级菜单
    void createToolBars();//创建工具栏

    void paintEvent(QPaintEvent *);
    QMdiSubWindow *isAlreadyOpen(const QString &fileName);//与fileOPen()配合  判断文件是否已经打开
    ~MainWindow();

private:

    Ui::MainWindow *ui;
    QMdiArea*mdiArea;//为了创建多窗体应用程序框架
    QMenu *formatMenu,*fontMenu,*alignMenu; //字体菜单指针
    QMenu *windowMenu;   //窗口菜单指针
    QAction *helpAct;
    QAction *bold,*italic,*underline,*color;        //字体二级菜单指针
    QAction *leftAlign,*center,*rightAlign,*justify;//段落二级菜单指针
    QAction *closeAct,*closeAllAct,*tileAct ,*cascadeAct ,*nextAct ,*previousAct,*separatorAct;//窗口二级菜单指针
    QToolBar *fileToolBar,*editToolBar,*formatToolBar,*comboToolBar;
    QComboBox*comboStyle,*comboSize;
    QFrontComboBox *comboFront;
    QFontComboBox *comboFont;
    EditWindow *activeEditwindow();//用来寻找活动窗口
    QSignalMapper *windowMapper;
    newWindow *win;
    FontSize * mycombo;
protected:
    void closeEvent(QCloseEvent *event);
private slots:
    void setFunctionState();
    void fileNew();
    void fileOpen();
    void fileSave();
    void fileSaveAs();
    void filePrint();
    void undo();
    void redo();
    void cut();
    void copy();
    void paste();
    void Bold();
    void Italic();
    void Underline();
    void Align(QAction *a);
    void textStyle(int styleIndex);
    void textFamily(const QString &f);
    void textSize(const QString &p);
    void Color();
    void enableText();
    void createStatusBar();
    void setActiveSubWindow(QWidget *window);
    void openNewWindow();
    void updateWindowMenu();

    //    void colorChanged(const QColor &c);



};
#endif // MAINWINDOW_H

mainwindow.cpp

#include<QString>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QtWidgets>
#include"editwindow.h"
#include<QFileDialog>
#include<QPainter>
#include<QPrintDialog>
#include"fontsize.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //主窗口基础配置
    setWindowIcon(QIcon(":/images/logo.jpg"));
    move(200,150);
    resize(800,500);
    setWindowTitle(QString("QT Version Word"));

    //创建多窗体应用程序框架
    mdiArea=new QMdiArea;
    mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);//设置子窗口过多时主窗口出现滚动条
    mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    setCentralWidget(mdiArea);//将子窗口设置为中心窗口部件
    connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)),this, SLOT(setFunctionState()));

    createActionsandMenus();
    createToolBars();//创建工具栏
    statusBar()->showMessage(tr("就绪"));
    setFunctionState();//初始按钮不可用

    windowMapper=new QSignalMapper(this);//为窗口->子窗口列表 设置信号映射
    connect(windowMapper, SIGNAL(mapped(QWidget*)),this, SLOT(setActiveSubWindow(QWidget*)));//mapped函数执行

}
void MainWindow::createActionsandMenus(){
    //文件 一级菜单栏已通过设计师界面设置
    //编辑 一级菜单栏已通过设计师界面设置


    //文件 二级菜单栏已通过设计师界面设置
    connect(ui->actionnew, SIGNAL(triggered()), this, SLOT(fileNew()));//点击新建创建窗口
    ui->actionnew->setShortcuts(QKeySequence::New);
    connect(ui->actionopen, SIGNAL(triggered()), this, SLOT(fileOpen()));//点击打开 打开文件
    ui->actionopen->setShortcuts(QKeySequence::Open);
    connect(ui->actionsave, SIGNAL(triggered()), this, SLOT(fileSave()));//点击保存保存文件
    ui->actionsave->setShortcuts(QKeySequence::Save);
    connect(ui->actionsaveAs, SIGNAL(triggered()), this, SLOT(fileSaveAs()));//
    ui->actionsaveAs->setShortcuts(QKeySequence::SaveAs);
    connect(ui->actionprint, SIGNAL(triggered()), this, SLOT(filePrint()));//
    ui->actionprint->setShortcuts(QKeySequence::Print);
    connect(ui->actionexit, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));//QApplication自带函数


    //编辑 二级菜单栏已通过设计师界面设置
    connect(ui->actionundo, SIGNAL(triggered()), this, SLOT(undo()));//撤回
    ui->actionundo->setShortcut(QKeySequence::Undo);
    connect(ui->actionredo, SIGNAL(triggered()), this, SLOT(redo()));//重做
    ui->actionredo->setShortcut(QKeySequence::Redo);
    connect(ui->actioncut, SIGNAL(triggered()), this, SLOT(cut()));// 剪切
    ui->actioncut->setShortcuts(QKeySequence::Cut);
    connect(ui->actioncopy, SIGNAL(triggered()), this, SLOT(copy()));//复制
    ui->actioncopy->setShortcuts(QKeySequence::Copy);
    connect(ui->actionpaste, SIGNAL(triggered()), this, SLOT(paste()));//粘贴
    ui->actionpaste->setShortcuts(QKeySequence::Paste);



    //格式 二级菜单栏设置
    formatMenu = ui->menubar->addMenu("格式");
    fontMenu = formatMenu->addMenu(QString("字体"));   //字体 子菜单
    alignMenu = formatMenu->addMenu(QString("段落"));   //段落 子菜单
    bold = new QAction(QIcon(":/images/textbold.png"),QString("加粗"), this);
    bold->setCheckable(true);
    bold->setShortcut(Qt::CTRL + Qt::Key_B);
    bold->setToolTip("加粗");
    bold->setStatusTip(QString("将所选文字加粗"));
    QFont boldfront;
    boldfront.setBold(true);
    bold->setFont(boldfront);
    fontMenu->addAction(bold);
    connect(bold, SIGNAL(triggered()), this, SLOT(Bold()));

    italic = new QAction(QIcon( ":/images/textitalic.png"),QString("倾斜"), this);
    italic->setCheckable(true);
    italic->setShortcut(Qt::CTRL + Qt::Key_I);
    italic->setToolTip("倾斜");
    italic->setStatusTip(QString("将所选文字用斜体显示"));
    QFont italicfront;
    italicfront.setItalic(true);
    italic->setFont(italicfront);
    fontMenu->addAction(italic);
    connect(italic, SIGNAL(triggered()), this, SLOT(Italic()));

    underline = new QAction(QIcon( ":/images/textunder.png"),QString("下划线"), this);
    underline->setCheckable(true);
    underline->setShortcut(Qt::CTRL + Qt::Key_U);
    underline->setToolTip("下划线");
    underline->setStatusTip(QString("给所选文字加下划线"));
    QFont underlinefront;
    underlinefront.setUnderline(true);
    underline->setFont(underlinefront);
    fontMenu->addAction(underline);
    connect(underline, SIGNAL(triggered()), this, SLOT(Underline()));

    //利用动作组使得格式->段落下的动作只能选择一个
    QActionGroup *grp = new QActionGroup(this);
    connect(grp, SIGNAL(triggered(QAction*)), this, SLOT(Align(QAction*)));

    leftAlign = new QAction(QIcon(":/images/textleft.png"),QString("左对齐"), grp);
    leftAlign->setShortcut(Qt::CTRL + Qt::Key_L);
    leftAlign->setCheckable(true);
    leftAlign->setToolTip("左对齐");
    leftAlign->setStatusTip(QString("将文字左对齐"));
    alignMenu->addAction(leftAlign);

    center = new QAction(QIcon( ":/images/textcenter.png"),QString("居中"), grp);
    center->setShortcut(Qt::CTRL + Qt::Key_E);
    center->setCheckable(true);
    center->setToolTip("居中");
    center->setStatusTip(QString("将文字居中对齐"));
    alignMenu->addAction(center);

    rightAlign = new QAction(QIcon(":/images/textright.png"),QString("右对齐"), grp);
    rightAlign->setShortcut(Qt::CTRL + Qt::Key_R);
    rightAlign->setCheckable(true);
    rightAlign->setToolTip("右对齐");
    rightAlign->setStatusTip(QString("将文字右对齐"));
    alignMenu->addAction(rightAlign);

    justify = new QAction(QIcon( ":/images/textjustify.png"),QString("两端对齐"), grp);
    justify->setShortcut(Qt::CTRL + Qt::Key_J);
    justify->setCheckable(true);
    justify->setToolTip("两端对齐");
    justify->setStatusTip(QString("将文字左右两端同时对齐,在文档有多行时才会起作用"));
    alignMenu->addAction(justify);


    QPixmap pix(16, 16);
    pix.fill(Qt::red);
    color = new QAction(QIcon( ":/images/color.jpg"),QString("颜色..."), this);
    color->setToolTip("颜色");
    color->setStatusTip(QString("设置文字颜色"));
    formatMenu->addAction(color);
    connect(color, SIGNAL(triggered()), this, SLOT(Color()));


    //窗口 二级菜单栏设置
    //窗口 一级菜单栏设置
    windowMenu = ui->menubar->addMenu("窗口");
    closeAct = new QAction(tr("关闭(&O)"), this);
    closeAct->setStatusTip("关闭当前子窗口");
    connect(closeAct, SIGNAL(triggered()),mdiArea, SLOT(closeActiveSubWindow()));

    closeAllAct =new QAction(tr("关闭所有(&A)"), this);
    closeAllAct->setStatusTip("关闭所有子窗口");
    connect(closeAllAct, SIGNAL(triggered()),mdiArea, SLOT(closeAllSubWindows()));
    windowMenu->addSeparator();

    tileAct = new QAction(tr("平铺(&T)"), this);
    tileAct->setStatusTip("平铺子窗口");
    connect(tileAct, SIGNAL(triggered()), mdiArea, SLOT(tileSubWindows()));

    cascadeAct = new QAction(tr("层叠(&C)"), this);
    cascadeAct->setStatusTip("层叠子窗口");
    connect(cascadeAct, SIGNAL(triggered()), mdiArea, SLOT(cascadeSubWindows()));
    windowMenu->addSeparator();

    nextAct = new QAction(tr("下一个(&X)"), this);
    nextAct->setShortcuts(QKeySequence::NextChild);
    nextAct->setStatusTip("切换到下一个子窗口");
    connect(nextAct, SIGNAL(triggered()),mdiArea, SLOT(activateNextSubWindow()));

    previousAct =new QAction(tr("前一个(&V)"), this);
    previousAct->setShortcuts(QKeySequence::PreviousChild);
    previousAct->setStatusTip("切换到上一个子窗口");
    connect(previousAct, SIGNAL(triggered()),mdiArea, SLOT(activatePreviousSubWindow()));
    separatorAct = new QAction(this);
    separatorAct->setSeparator(true);


    updateWindowMenu();
    connect(windowMenu, SIGNAL(aboutToShow()), this, SLOT(updateWindowMenu()));


    menuBar()->addSeparator();
    helpAct = ui->menubar->addAction("帮助");
    connect(helpAct,SIGNAL(triggered()),this,SLOT(openNewWindow()));
}
void MainWindow::createToolBars(){//  创建工具栏
    fileToolBar=addToolBar(QString("文件"));
    fileToolBar->addAction(ui->actionnew);
    fileToolBar->addAction(ui->actionopen);
    fileToolBar->addAction(ui->actionsave);
    fileToolBar->addSeparator();
    fileToolBar->addAction(ui->actionprint);

    editToolBar=addToolBar(QString("编辑"));
    editToolBar->addAction(ui->actionundo);
    editToolBar->addAction(ui->actionredo);
    editToolBar->addSeparator();
    editToolBar->addAction(ui->actioncut);
    editToolBar->addAction(ui->actioncopy);
    editToolBar->addAction(ui->actionpaste);

    formatToolBar = addToolBar(tr("格式"));
    formatToolBar->addAction(bold);
    formatToolBar->addAction(italic);
    formatToolBar->addAction(underline);
    formatToolBar->addSeparator();
    formatToolBar->addAction(leftAlign);
    formatToolBar->addAction(center);
    formatToolBar->addAction(rightAlign);
    formatToolBar->addAction(justify);
    formatToolBar->addSeparator();
    formatToolBar->addAction(color);

    addToolBarBreak(Qt::TopToolBarArea);    //使这个工具条在界面上另起一行显示
    comboToolBar = addToolBar(tr("组合选择"));
    comboStyle = new QComboBox();
    comboToolBar->addWidget(comboStyle);
//    comboStyle->addItem("标准");
    comboStyle->addItem("项目符号 (●)");
    comboStyle->addItem("项目符号 (○)");
    comboStyle->addItem("项目符号 (■)");
    comboStyle->addItem("编号 (⒈⒉⒊)");
    comboStyle->addItem("编号 ( a.b.c.)");
    comboStyle->addItem("编号 ( A.B.C.)");
    comboStyle->addItem("编号 (ⅰ.ⅱ.ⅲ.)");
    comboStyle->addItem("编号 (Ⅰ.Ⅱ.Ⅲ.)");
    comboStyle->setStatusTip("段落加标号或编号");
    connect(comboStyle, SIGNAL(activated(int)), this, SLOT(textStyle(int)));

    comboFont = new QFontComboBox();
    comboToolBar->addWidget(comboFont);
    comboFont->setStatusTip("更改字体");
    connect(comboFont, SIGNAL(activated(QString)), this, SLOT(textFamily(QString)));

    comboSize = new QComboBox();
    comboToolBar->addWidget(comboSize);
    comboSize->setEditable(true);
    comboSize->setStatusTip("更改字号");

    QFontDatabase db;
    foreach(int size, db.standardSizes())
        comboSize->addItem(QString::number(size));

    connect(comboSize, SIGNAL(activated(QString)), this, SLOT(textSize(QString)));
    comboSize->setCurrentIndex(comboSize->findText(QString::number(QApplication::font().pointSize())));


//自定义控件
    mycombo = new FontSize;
    comboToolBar->addWidget(mycombo);
    connect(mycombo->comboBox, SIGNAL(activated(QString)), this, SLOT(textSize(QString)));
    mycombo->comboBox->setCurrentIndex(comboSize->findText(QString::number(QApplication::font().pointSize())));


         mycombo->comboBox->setCurrentIndex(comboSize->currentIndex());

}

void MainWindow::createStatusBar()
{
    statusBar()->showMessage(tr("就绪"));
}


void MainWindow::setFunctionState(){//根据文档状态调整动作是否可用
    //至少有一个子文档打开着的情况
    bool hasMyChild = (activeEditwindow()!=0);

    ui->actionsave->setEnabled(hasMyChild);
    ui->actionsaveAs->setEnabled(hasMyChild);
    ui->actionprint->setEnabled(hasMyChild);


    ui->actionpaste->setEnabled(hasMyChild);

    closeAct->setEnabled(hasMyChild);
    closeAllAct->setEnabled(hasMyChild);
    tileAct->setEnabled(hasMyChild);
    cascadeAct->setEnabled(hasMyChild);
    nextAct->setEnabled(hasMyChild);
    previousAct->setEnabled(hasMyChild);
    //    separatorAct->setVisible(hasMyChild);
    //文档打开着并且其中有内容被选中的情况
    //    bool hasSelection = (activeEditwindow() && activeEditwindow()->textCursor().hasSelection());

    ui->actioncut->setEnabled(hasMyChild);
    ui->actioncopy->setEnabled(hasMyChild);

    bold->setEnabled(hasMyChild);
    italic->setEnabled(hasMyChild);
    underline->setEnabled(hasMyChild);
    leftAlign->setEnabled(hasMyChild);
    center->setEnabled(hasMyChild);
    rightAlign->setEnabled(hasMyChild);
    justify->setEnabled(hasMyChild);
    color->setEnabled(hasMyChild);
}

void MainWindow::fileNew(){//新建文件的槽函数
    //后期进行封装
    EditWindow *child = new EditWindow;
    mdiArea->addSubWindow(child);
    connect(child, SIGNAL(copyAvailable(bool)),ui->actioncut, SLOT(setEnabled(bool)));
    connect(child, SIGNAL(copyAvailable(bool)),ui->actioncopy, SLOT(setEnabled(bool)));
    if(child ->newFile()){
        child->show();
        statusBar()->showMessage(QString("新建成功"), 2000);
        enableText();
    }
}
QMdiSubWindow *MainWindow::isAlreadyOpen(const QString &fileName){//寻找文件是否已在窗口中打开 是则返回此窗口的指针
    QString canonicalFilePath = QFileInfo(fileName).canonicalFilePath();//获取文件的规范路径
    //遍历编辑窗口
    foreach (QMdiSubWindow *window, mdiArea->subWindowList()) {
        EditWindow *myChild = qobject_cast<EditWindow *>(window->widget());
        if (myChild->curFileName == canonicalFilePath)
            return window;
    }
    return 0;
}
void MainWindow::fileOpen(){//打开磁盘中文件的槽函数
    QString fileName=QFileDialog::getOpenFileName(this,QString("打开现有文件"),QString(), tr("HTML 文档 (*.htm *.html);;所有文件 (*.*)"));
    if(!fileName.isEmpty()){//如果路径非空
        //先判断是否已经打开
        QMdiSubWindow * isExis = isAlreadyOpen(fileName);
        //已打开则将其设置为活动窗口
        if (isExis) {
            mdiArea->setActiveSubWindow(isExis);
            return;
        }
        //未打开则打开
        EditWindow *child = new EditWindow;
        mdiArea->addSubWindow(child);
        connect(child, SIGNAL(copyAvailable(bool)),ui->actioncut, SLOT(setEnabled(bool)));
        connect(child, SIGNAL(copyAvailable(bool)),ui->actioncopy, SLOT(setEnabled(bool)));
        if (child->openFile(fileName)) {
            statusBar()->showMessage(tr("文件已载入"), 2000);
            child->show();
            enableText();
        } else {
            child->close();
        }

    }
}
void MainWindow::fileSave(){ //保存文档
    if (activeEditwindow() && activeEditwindow()->save())
        statusBar()->showMessage(QString("保存成功"), 2000);
}
void MainWindow::fileSaveAs(){    //另存为
    if (activeEditwindow() && activeEditwindow()->saveAs())
        statusBar()->showMessage(QString("保存成功"), 2000);
}
void MainWindow::filePrint(){//打印
    QPrinter printer(QPrinter::HighResolution);
    QPrintDialog *printdialog = new QPrintDialog(&printer, this);
    printdialog->setWindowTitle(tr("打印文档"));
    if (printdialog->exec() == QDialog::Accepted)
        activeEditwindow()->print(&printer);
    delete printdialog;
}
void MainWindow::paintEvent(QPaintEvent *){
    QPixmap pix;
    pix.load(":/images/mountain.jpg");
    QPainter painter(this);
    painter.drawPixmap(0, 0, this->width(), this->height(), pix);
}

EditWindow *MainWindow::activeEditwindow()//找到当前活动的(被选中的)窗口
{
    if (QMdiSubWindow *activeSubWindow = mdiArea->activeSubWindow())
        return qobject_cast<EditWindow *>(activeSubWindow->widget());//类型转换
    return 0;
}

void MainWindow::undo()//撤销操作的槽函数
{
    if(activeEditwindow())
        activeEditwindow()->undo();
}

void MainWindow::redo()//重做的槽函数
{
    if(activeEditwindow())
        activeEditwindow()->redo();
}

void MainWindow::cut()//剪切的槽函数
{
    if (activeEditwindow())
        activeEditwindow()->cut();
}

void MainWindow::copy()//复制的槽函数
{
    if (activeEditwindow())
        activeEditwindow()->copy();
}

void MainWindow::paste()//粘贴的槽函数
{
    if (activeEditwindow())
        activeEditwindow()->paste();
}

void MainWindow::Bold()//字体加粗的槽函数
{
    QTextCharFormat bo;
    bo.setFontWeight(bold->isChecked() ? QFont::Bold : QFont::Normal);
    if(activeEditwindow())
        activeEditwindow()->WordFormat(bo);
}

void MainWindow::Italic()//字体倾斜的槽函数
{
    QTextCharFormat il;
    il.setFontItalic(italic->isChecked());
    if(activeEditwindow())
        activeEditwindow()->WordFormat(il);
}

void MainWindow::Underline()//字体下划线的槽函数
{
    QTextCharFormat ul;
    ul.setFontUnderline(underline->isChecked());
    if(activeEditwindow())
        activeEditwindow()->WordFormat(ul);
}

void MainWindow::Align(QAction *a)//字体对齐的槽函数
{
    if(activeEditwindow())
    {
        if (a == leftAlign)
            activeEditwindow()->Align(1);
        else if (a == center)
            activeEditwindow()->Align(2);
        else if (a == rightAlign)
            activeEditwindow()->Align(3);
        else if (a == justify)
            activeEditwindow()->Align(4);
    }
}


void MainWindow::textFamily(const QString &f)//字体选择的槽函数
{
    QTextCharFormat tf;
    tf.setFontFamily(f);
    if(activeEditwindow())
        activeEditwindow()->WordFormat(tf);
}

void MainWindow::textSize(const QString &p)//字号选择的槽函数
{
    qreal pointSize = p.toFloat();
    if (p.toFloat() > 0) {
        QTextCharFormat fs;
        fs.setFontPointSize(pointSize);
        if(activeEditwindow())
            activeEditwindow()->WordFormat(fs);
        mycombo->comboBox->setCurrentIndex(comboSize->currentIndex());
        comboSize->setCurrentIndex(mycombo->comboBox->currentIndex());
    }
}

void MainWindow::Color()//设置字体颜色的槽函数
{
    if(activeEditwindow())
    {
        QColor clr = QColorDialog::getColor(activeEditwindow()->textColor(), this);
        if (!clr.isValid())
            return;
        QTextCharFormat co;
        co.setForeground(clr);
        activeEditwindow()->WordFormat(co);
        QPixmap pix(16, 16);//更改设置字体颜色的按钮的图标
        pix.fill(clr);
        color->setIcon(pix);
    }
}

void MainWindow::textStyle(int styleIndex)//实现为段落增加标号和编号的功能
{
    if(activeEditwindow())
    {
        activeEditwindow()->setStyle(styleIndex);
    }
}

void MainWindow::enableText()
{
    bold->setEnabled(true);
    italic->setEnabled(true);
    underline->setEnabled(true);
    leftAlign->setEnabled(true);
    center->setEnabled(true);
    rightAlign->setEnabled(true);
    justify->setEnabled(true);
    color->setEnabled(true);
}
void MainWindow::closeEvent(QCloseEvent *event)//重写关闭的函数
{
    mdiArea->closeAllSubWindows();
    if (mdiArea->currentSubWindow()) {
        event->ignore();
    } else {
        event->accept();
    }
}

void MainWindow::setActiveSubWindow(QWidget *window)
{
    if (!window)
        return;
    mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow *>(window));
}
void MainWindow::updateWindowMenu()
{
    windowMenu->clear();//初始化清除
    windowMenu->addAction(closeAct);
    windowMenu->addAction(closeAllAct);
    windowMenu->addSeparator();
    windowMenu->addAction(tileAct);
    windowMenu->addAction(cascadeAct);
    windowMenu->addSeparator();
    windowMenu->addAction(nextAct);
    windowMenu->addAction(previousAct);
    windowMenu->addAction(separatorAct);

    QList<QMdiSubWindow *> windows = mdiArea->subWindowList();
    //当有窗口打开时显示分隔符
    separatorAct->setVisible(!windows.isEmpty());
    //显示当前打开着的文档子窗口项
    for (int i = 0; i < windows.size(); i++) {
        EditWindow *child = qobject_cast<EditWindow *>(windows.at(i)->widget());

        QString text;
        if (i < 9) {
            text = tr("&%1 %2").arg(i + 1).arg(child->easyCurrentFile());
        } else {
            text = tr("%1 %2").arg(i + 1).arg(child->easyCurrentFile());
        }
        //添加动作到菜单  设置动作可选
        QAction *action  = windowMenu->addAction(text);
        action->setCheckable(true);
        //设置当前活动窗口被选中
        action ->setChecked(child == activeEditwindow());
//触发时执行map函数发送mapped信号
        connect(action, SIGNAL(triggered()), windowMapper, SLOT(map()));
        windowMapper->setMapping(action, windows.at(i));
    }
    enableText();          //使得字体设置菜单可用
}
void MainWindow::openNewWindow()
{
    win = new newWindow();
    win->show();
}


MainWindow::~MainWindow()
{
    delete ui;
}

editwindow.h:

#ifndef EDITWINDOW_H
#define EDITWINDOW_H

#include <QTextEdit>
#include <QWidget>
#include<QString>
#include <QPrinter>
class EditWindow : public QTextEdit
{
    Q_OBJECT
public:
    EditWindow();
    QString curFileName;//当前窗口文件的名称
   void setCurrentFile(const QString &fileName);

    bool newFile();
    bool openFile(const QString &filePath);
    bool saveFile(QString fileName);
    bool  saveAs();
    bool save();
    QString easyCurrentFile();
    QString currentFile() { return curFileName; }
    void WordFormat(const QTextCharFormat &format);
    void Align(int align);
    void setStyle(int style);
protected:
    void closeEvent(QCloseEvent *event);
private:
     QString strippedName(const QString &fullFileName);
     bool maybeSave();

    bool isUntitled;
private slots:
    void documentWasModified();

};

#endif // EDITWINDOW_H

editwindow.cpp:

#include "editwindow.h"
#include<QtWidgets>
#include<QString>
#include<QTextEdit>
EditWindow::EditWindow()
{
    setAttribute(Qt::WA_DeleteOnClose);//设置关闭时自动删除这个类
    isUntitled = true;//默认未命名
}

QString EditWindow::strippedName(const QString &fullFileName)
{
    return QFileInfo(fullFileName).fileName();
}
QString EditWindow::easyCurrentFile()//提取简易文件名
{
    return strippedName(curFileName);
}

void EditWindow::setCurrentFile(const QString &fileName){
    curFileName = QFileInfo(fileName).canonicalFilePath();
    isUntitled = false;//设置文档为已保存状态
    document()->setModified(false);//文档设为未被修改状态
    setWindowModified(false);//窗口设为未被修改状态
    setWindowTitle(easyCurrentFile() + "[*]");
}

void EditWindow::documentWasModified()
{
    setWindowModified(document()->isModified());
}
bool EditWindow::newFile(){
    static int num=1;//窗口编号  设为全局变量
    curFileName=QString("文档"+QString::number(num++));
    setWindowTitle(curFileName+"[*]");
    connect(document(),SIGNAL(contentsChanged()),this,SLOT(documentWasModified()));
    return true;
}
bool EditWindow::openFile(const QString &filePath){//从filePath读取文件
    if (!filePath.isEmpty())
    {
        if (!QFile::exists(filePath))
            return false;
        QFile file(filePath);
        if (!file.open(QFile::ReadOnly))
            return false;

        QByteArray data = file.readAll();
        QTextCodec *codec = Qt::codecForHtml(data);
        QString str = codec->toUnicode(data);
        if (Qt::mightBeRichText(str)) {
            this->setHtml(str);
        } else {
            str = QString::fromLocal8Bit(data);
            this->setPlainText(str);
        }
        setCurrentFile(filePath);//设置文档及窗口
        connect(document(),SIGNAL(contentsChanged()),this,SLOT(documentWasModified()));
        return true;
    }
    return 0;
}

void EditWindow::closeEvent(QCloseEvent *event)
{
    if (maybeSave()) {
        event->accept();
    } else {
        event->ignore();
    }
}

bool EditWindow::maybeSave()
{
    if (!document()->isModified())
        return true;
    QMessageBox::StandardButton ret;
    ret = QMessageBox::warning(this, tr("My Qt-Version Word"),tr("文档'%1'已被修改,保存吗?").arg(easyCurrentFile()),QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
    if (ret == QMessageBox::Save)
        return save();
    else if (ret == QMessageBox::Cancel)
        return false;
    return true;
}

bool EditWindow::save()
{
    if (isUntitled) {
        return saveAs();
    } else {
        return saveFile(curFileName);
    }
}

bool EditWindow::saveFile(QString curFileName){
    if (isUntitled) {
        return saveAs();
    } else {
        if (!(curFileName.endsWith(".htm", Qt::CaseInsensitive) || curFileName.endsWith(".html", Qt::CaseInsensitive))) {
            curFileName += ".html"; // 默认保存为 HTML 文档
        }
        QTextDocumentWriter writer(curFileName);
        bool isok = writer.write(this->document());
        if (isok)
            setCurrentFile(curFileName);
        return isok;
    }
}
bool EditWindow::saveAs(){
    QString fileName = QFileDialog::getSaveFileName(this, tr("另存为"),curFileName,QString("HTML 文档 (*.htm *.html);;所有文件 (*.*)"));
    if (fileName.isEmpty())
        return false;
    else{
        if (!(fileName.endsWith(".htm", Qt::CaseInsensitive) || fileName.endsWith(".html", Qt::CaseInsensitive))) {
            fileName += ".html"; // 默认保存为 HTML 文档
        }
        QTextDocumentWriter writer(fileName);
        bool isok = writer.write(this->document());
        if (isok)
            setCurrentFile(fileName);
        return isok;
    }
}
void EditWindow::Align(int align)//段落文字对齐方式
{
    if (align == 1)
        this->setAlignment(Qt::AlignLeft | Qt::AlignAbsolute);
    else if (align == 2)
        this->setAlignment(Qt::AlignHCenter);
    else if (align == 3)
        this->setAlignment(Qt::AlignRight | Qt::AlignAbsolute);
    else if (align == 4)
        this->setAlignment(Qt::AlignJustify);
}


void EditWindow::WordFormat(const QTextCharFormat &format)//设置字体格式 颜色
{
    QTextCursor cursor = this->textCursor();
    if (!cursor.hasSelection())
        cursor.select(QTextCursor::WordUnderCursor);
    cursor.mergeCharFormat(format);
    this->mergeCurrentCharFormat(format);
}


void EditWindow::setStyle(int style)//设置文本标号
{
    QTextCursor cursor = this->textCursor();

    if (style != 0) {
        QTextListFormat::Style stylename = QTextListFormat::ListDisc;

        switch (style) {
        default:
        case 1:
            stylename = QTextListFormat::ListDisc;
            break;
        case 2:
            stylename = QTextListFormat::ListCircle;
            break;
        case 3:
            stylename = QTextListFormat::ListSquare;
            break;
        case 4:
            stylename = QTextListFormat::ListDecimal;
            break;
        case 5:
            stylename = QTextListFormat::ListLowerAlpha;
            break;
        case 6:
            stylename = QTextListFormat::ListUpperAlpha;
            break;
        case 7:
            stylename = QTextListFormat::ListLowerRoman;
            break;
        case 8:
            stylename = QTextListFormat::ListUpperRoman;
            break;
        }

        cursor.beginEditBlock();

        QTextBlockFormat blockFmt = cursor.blockFormat();

        QTextListFormat listFmt;

        if (cursor.currentList()) {
            listFmt = cursor.currentList()->format();
        } else {
            listFmt.setIndent(blockFmt.indent() + 1);
            blockFmt.setIndent(0);
            cursor.setBlockFormat(blockFmt);
        }

        listFmt.setStyle(stylename);

        cursor.createList(listFmt);

        cursor.endEditBlock();
    } else {
        QTextBlockFormat bfmt;
        bfmt.setObjectIndex(-1);
        cursor.mergeBlockFormat(bfmt);
    }
}

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值