第18章 【综合实例】MyWord字处理软件

一、成品界面展示与项目流程

运行程序后会出现主界面,顶端的菜单栏包括“文件”“编辑”“格式”“窗口”和“帮助”五个主菜单。 菜单栏下面是工具栏,包含了系统常用的功能按钮。工具栏有四个工具条,分别将一组相关功能按钮或控件组织在一起。 工具栏的第一行有三个工具条:第一个工具条包括新建、打开、保存、打印等文档管理功能;第二个工具条包括撤销、重做、剪切、复制和粘贴这些最基本的文本编辑功能;第三个工具条是各种较高级的文字字体格式设置按钮,包括加粗、倾斜、加下画线,还包括段落对齐及文本颜色设置等。 在工具栏的第二行的工具条中有三个组合选择框控件,用于为文档添加段落标号和编号,以及选择特殊字体和更改字号。利用该工具条可以完成更复杂的文档排版和字体美化工作。 此外,在图18.1中还给出了使用该软件制作出的三个文档示例。用Qt版MyWord字处理软件制作出的文档统一以HTML格式存盘,可使用Web浏览器打开观看效果,如图所示。

开发这个软件主要分为如下三个阶段进行。

(1)界面设计开发

界面设计开发内容包括菜单系统设计、工具栏设计、多窗体MDI程序框架的建立及多个文档子窗口的管理和控制等。

(2)文本编辑功能实现

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

(3)排版美化功能实现

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

二、界面设计开发

三、工程结构

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMessageBox>
#include "mychildwnd.h"
#include <QMdiSubWindow>
#include <QSignalMapper>
#include <QFileDialog>
#include <QCloseEvent>
#include <QColorDialog>
#include <QPrintDialog>
#include <QPrinter>
#include <QPrintPreviewDialog>


class MyChildWnd;
class QMdiSubWindow;
class QSignalMapper;

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void initMainWindow();//初始化
    void docNew();//新建文档
    void docOpen();//打开文档
    void docSave();//保存文档
    void docSaveAs();//文档另存为
    void docUndo();//撤销
    void docRedo();//重做
    void docCut();//剪切
    void docCopy();//复制
    void docPaste();//粘贴
    void textBold();//加粗
    void textItalic();//倾斜
    void textUnderline();//加下划线
    void textFamily(const QString &fmly);//字体
    void textSize(const QString &ps);//字号
    void textAlign(QAction *act);//对齐
    void textColor();//颜色
    void paraStyle(int sidx);//段落标号编号
    void docPrint();
    void docPrintPreview();
    void printPreview(QPrinter *);


private slots:
    void on_aboutAction_triggered();

    void on_aboutQtAction_triggered();

    void on_newAction_triggered();

    void refreshMenus();//刷新菜单槽函数

    void addSubWndListMenu();//往【窗口】菜单下添加子窗口菜单项列表

    void setActiveSubWindow(QWidget *wnd);

    void on_openAction_triggered();

    void on_saveAction_triggered();

    void on_saveAsAction_triggered();

    void on_undoAction_triggered();

    void on_redoAction_triggered();

    void on_cutAction_triggered();

    void on_copyAction_triggered();

    void on_pasteAction_triggered();

    void on_boldAction_triggered();

    void on_italicAction_triggered();

    void on_underlineAction_triggered();

    void on_fontComboBox_activated(const QString &arg1);

    void on_sizeComboBox_activated(const QString &arg1);

    void on_leftAlignAction_triggered();

    void on_centerAction_triggered();

    void on_rightAlignAction_triggered();

    void on_justifyAction_triggered();

    void on_colorAction_triggered();

    void on_styleComboBox_activated(int index);

    void on_printAction_triggered();

    void on_printPreviewAction_triggered();

    void on_closeAction_triggered();

    void on_closeAllAction_triggered();

    void on_tileAction_triggered();

    void on_cascadeAction_triggered();

    void on_nextAction_triggered();

    void on_previousAction_triggered();

protected:
    void closeEvent(QCloseEvent *event);
private:
    Ui::MainWindow *ui;
    void formatEnabled();//使格式菜单及其工具按钮可用
    MyChildWnd* activateChildWnd();//活动文档子窗口
    QSignalMapper* myWndMapper;//子窗口信号映射器
    QMdiSubWindow* findChildWnd(const QString &docName);
};

#endif // MAINWINDOW_H

 mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    initMainWindow();
}

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

void MainWindow::initMainWindow()
{
    //加载系统标准字号集
    QFontDatabase fontdb;
    foreach (int fontsize, fontdb.standardSizes())
    {
        ui->sizeComboBox->addItem(QString::number(fontsize));
    }
    ui->sizeComboBox->setCurrentIndex(ui->sizeComboBox->findText(QString::number
                                                                 (QApplication::font().pointSize())));
    //将【段落】菜单下的各对齐方式功能项加入同一个菜单项组,这样程序运行的任一时刻用户能且只能选中其中一项
    QActionGroup* alignGroup = new QActionGroup(this);
    alignGroup->addAction(ui->leftAlignAction);
    alignGroup->addAction(ui->centerAction);
    alignGroup->addAction(ui->rightAlignAction);
    alignGroup->addAction(ui->justifyAction);
    ui->leftAlignAction->setChecked(true);
    //多文档区域设置
    ui->mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);//滚动条在需要的时候出现
    ui->mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    refreshMenus();
    //当有活动文档子窗口时刷新菜单
    connect(ui->mdiArea,SIGNAL(subWindowActivated(QMdiSubWindow*)),this,SLOT(refreshMenus()));

    //添加子窗口菜单项列表
    myWndMapper = new QSignalMapper(this);//创建信号映射器
    connect(myWndMapper,SIGNAL(mapped(QWidget*)),this,SLOT(setActiveSubWindow(QWidget*)));
    addSubWndListMenu();
    connect(ui->menu_W,SIGNAL(aboutToHide()),this,SLOT(addSubWndListMenu()));
}

void MainWindow::on_aboutAction_triggered()
{
    QMessageBox::about(this,tr("关于"),tr("这是一个基于Qt5实现的字处理软件\r\n具备类似 微软 Office Word的功能。"));
}

void MainWindow::on_aboutQtAction_triggered()
{
    QMessageBox::aboutQt(NULL,"关于 Qt 5");
}

void MainWindow::on_closeAction_triggered()
{
    //对应窗口->关闭菜单项
    ui->mdiArea->closeActiveSubWindow();
}

void MainWindow::on_closeAllAction_triggered()
{
    //对应窗口->关闭所有菜单项
    ui->mdiArea->closeAllSubWindows();
}

void MainWindow::on_tileAction_triggered()
{
    //对应窗口->平铺所有窗口菜单项
    ui->mdiArea->tileSubWindows();
}

void MainWindow::on_cascadeAction_triggered()
{
    //对应窗口->层叠所有窗口菜单项
    ui->mdiArea->cascadeSubWindows();
}

void MainWindow::on_nextAction_triggered()
{
    //对应窗口->下一个菜单项
    ui->mdiArea->activateNextSubWindow();
}

void MainWindow::on_previousAction_triggered()
{
    //对应窗口->上一个菜单项
    ui->mdiArea->activatePreviousSubWindow();
}

void MainWindow::docNew()
{
    MyChildWnd* childWnd = new MyChildWnd;//创建MyChildWnd部件
    //向多文档区域添加子窗口,childWnd为中心部件
    ui->mdiArea->addSubWindow(childWnd);
    //根据QTextEdit类是否可以复制信号,设置剪切、复制动作是否可用
    connect(childWnd,SIGNAL(copyAvailable(bool)),ui->cutAction,SLOT(setEnabled(bool)));
    connect(childWnd,SIGNAL(copyAvailable(bool)),ui->copyAction,SLOT(setEnabled(bool)));
    childWnd->newDoc();
    childWnd->show();
    //使“格式”菜单下各菜单项及其对应的工具按钮变为可用
    formatEnabled();
}
void MainWindow::on_openAction_triggered()
{
    docOpen();
}

void MainWindow::docOpen()
{
    QString docname = QFileDialog::getOpenFileName(this,tr("打开"),QString(),
                                                   tr("HTML 文档 (*.htm *.html);;所有文件 (*.*)"));
    if(!docname.isEmpty())
    {
        QMdiSubWindow *exist = findChildWnd(docname);
        if(exist)
        {
            ui->mdiArea->setActiveSubWindow(exist);
            return;
        }
        MyChildWnd* childwnd = new MyChildWnd;
        ui->mdiArea->addSubWindow(childwnd);
        connect(childwnd,SIGNAL(copyAvailable(bool)),ui->cutAction,SLOT(setEnabled(bool)));
        connect(childwnd,SIGNAL(copyAvailable(bool)),ui->copyAction,SLOT(setEnabled(bool)));
        if(childwnd->loadDoc(docname))
        {
            statusBar()->showMessage(tr("文档已打开"),2000);
            childwnd->show();
            //使字体菜单下的功能可用
            formatEnabled();
        }
        else
        {
            childwnd->close();
        }
    }
}

void MainWindow::on_saveAction_triggered()
{
    docSave();
}

void MainWindow::docSave()
{
    if(activateChildWnd() && activateChildWnd()->saveDoc())
    {
        statusBar()->showMessage(tr("保存成功"),2000);
    }
}

void MainWindow::on_saveAsAction_triggered()
{
    docSaveAs();
}

void MainWindow::docSaveAs()
{
    if(activateChildWnd() && activateChildWnd()->saveAsDoc())
    {
        statusBar()->showMessage(tr("保存成功"), 2000);
    }
}

void MainWindow::on_undoAction_triggered()
{
    docUndo();
}

void MainWindow::on_redoAction_triggered()
{
    docRedo();
}

void MainWindow::on_cutAction_triggered()
{
    docCut();
}

void MainWindow::on_copyAction_triggered()
{
    docCopy();
}

void MainWindow::on_pasteAction_triggered()
{
    docPaste();
}

void MainWindow::docUndo()
{
    if(activateChildWnd())
        activateChildWnd()->undo();
}

void MainWindow::docRedo()
{
    if(activateChildWnd())
        activateChildWnd()->redo();
}

void MainWindow::docCut()
{
    if(activateChildWnd())
        activateChildWnd()->cut();
}

void MainWindow::docCopy()
{
    if(activateChildWnd())
        activateChildWnd()->copy();
}

void MainWindow::docPaste()
{
    if(activateChildWnd())
        activateChildWnd()->paste();
}

void MainWindow::on_boldAction_triggered()
{
    textBold();
}

void MainWindow::on_italicAction_triggered()
{
    textItalic();
}

void MainWindow::on_underlineAction_triggered()
{
    textUnderline();
}

void MainWindow::textBold()
{
    QTextCharFormat fmt;
    fmt.setFontWeight(ui->boldAction->isChecked() ? QFont::Bold :QFont::Normal);
    if(activateChildWnd())
        activateChildWnd()->setFormatOnSelectedWord(fmt);
}

void MainWindow::textItalic()
{
    QTextCharFormat fmt;
    fmt.setFontItalic(ui->italicAction->isChecked());
    if(activateChildWnd())
        activateChildWnd()->setFormatOnSelectedWord(fmt);
}

void MainWindow::textUnderline()
{
    QTextCharFormat fmt;
    fmt.setFontUnderline(ui->underlineAction->isChecked());
    if(activateChildWnd())
        activateChildWnd()->setFormatOnSelectedWord(fmt);
}

void MainWindow::on_fontComboBox_activated(const QString &arg1)
{
    textFamily(arg1);
}

void MainWindow::on_sizeComboBox_activated(const QString &arg1)
{
    textSize(arg1);
}

void MainWindow::textFamily(const QString &fmly)
{
    QTextCharFormat fmt;
    fmt.setFontFamily(fmly);
    if(activateChildWnd())
        activateChildWnd()->setFormatOnSelectedWord(fmt);
}

void MainWindow::textSize(const QString &ps)
{
    qreal pointSize = ps.toFloat();
    if(ps.toFloat() > 0)
    {
        QTextCharFormat fmt;
        fmt.setFontPointSize(pointSize);
        if(activateChildWnd())
            activateChildWnd()->setFormatOnSelectedWord(fmt);
    }
}

void MainWindow::on_leftAlignAction_triggered()
{
    textAlign(ui->leftAlignAction);
}

void MainWindow::on_centerAction_triggered()
{
    textAlign(ui->centerAction);
}

void MainWindow::on_rightAlignAction_triggered()
{
    textAlign(ui->rightAlignAction);
}

void MainWindow::on_justifyAction_triggered()
{
    textAlign(ui->justifyAction);
}

void MainWindow::textAlign(QAction *act)
{
    if(activateChildWnd())
    {
        if(act == ui->leftAlignAction)
            activateChildWnd()->setAlignOfDocumentText(1);
        else if(act == ui->centerAction)
            activateChildWnd()->setAlignOfDocumentText(2);
        else if(act == ui->rightAlignAction)
            activateChildWnd()->setAlignOfDocumentText(3);
        else if(act == ui->justifyAction)
            activateChildWnd()->setAlignOfDocumentText(4);
    }

}

void MainWindow::on_colorAction_triggered()
{
    textColor();
}

void MainWindow::textColor()
{
    if(activateChildWnd())
    {
        QColor color = QColorDialog::getColor(activateChildWnd()->textColor(),this);
        if(!color.isValid())
            return;
        QTextCharFormat fmt;
        fmt.setForeground(color);
        activateChildWnd()->setFormatOnSelectedWord(fmt);
        QPixmap pix(16,16);
        pix.fill(color);
        ui->colorAction->setIcon(pix);
    }
}

void MainWindow::on_styleComboBox_activated(int index)
{
    paraStyle(index);
}

void MainWindow::paraStyle(int sidx)
{
    if(activateChildWnd())
        activateChildWnd()->setParaStyle(sidx);
}

void MainWindow::on_printAction_triggered()
{
    docPrint();
}

void MainWindow::on_printPreviewAction_triggered()
{
    docPrintPreview();
}

void MainWindow::docPrint()
{
    QPrinter pter(QPrinter::HighResolution);
    QPrintDialog *pdlg = new QPrintDialog(&pter,this);
    if(activateChildWnd()->textCursor().hasSelection())
        pdlg->addEnabledOption(QAbstractPrintDialog::PrintSelection);
    pdlg->setWindowTitle("打印文档");
    if(pdlg->exec() == QDialog::Accepted)
    {
        activateChildWnd()->print(&pter);
    }
    delete pdlg;
}

void MainWindow::docPrintPreview()
{
    QPrinter pter(QPrinter::HighResolution);
    QPrintPreviewDialog pview(&pter,this);
    connect(&pview,SIGNAL(paintRequested(QPrinter*)),SLOT(printPreview(QPrinter*)));
    pview.exec();
}

void MainWindow::printPreview(QPrinter *pter)
{
    activateChildWnd()->print(pter);
}

QMdiSubWindow *MainWindow::findChildWnd(const QString &docName)
{
    QString canonicalFilePath = QFileInfo(docName).canonicalFilePath();
    foreach (QMdiSubWindow* wnd, ui->mdiArea->subWindowList()) 
    {
        MyChildWnd* childwnd = qobject_cast<MyChildWnd *>(wnd->widget());
        if(childwnd->myCurDocPath == canonicalFilePath)
            return wnd;
    }
    return 0;
}

void MainWindow::formatEnabled()
{
    ui->boldAction->setEnabled(true);
    ui->italicAction->setEnabled(true);
    ui->underlineAction->setEnabled(true);
    ui->leftAlignAction->setEnabled(true);
    ui->centerAction->setEnabled(true);
    ui->rightAlignAction->setEnabled(true);
    ui->justifyAction->setEnabled(true);
    ui->colorAction->setEnabled(true);
}

void MainWindow::on_newAction_triggered()
{
    docNew();
}

void MainWindow::refreshMenus()
{
    //至少有一个文档子窗口打开的情况
    bool hasChild = (activateChildWnd() != 0);
    ui->saveAction->setEnabled(hasChild);
    ui->saveAsAction->setEnabled(hasChild);
    ui->printAction->setEnabled(hasChild);
    ui->printPreviewAction->setEnabled(hasChild);

    ui->pasteAction->setEnabled(hasChild);
    ui->closeAction->setEnabled(hasChild);
    ui->closeAllAction->setEnabled(hasChild);
    ui->tileAction->setEnabled(hasChild);

    ui->cascadeAction->setEnabled(hasChild);
    ui->nextAction->setEnabled(hasChild);
    ui->previousAction->setEnabled(hasChild);

    //文档已打开并且其中由内容被选中时
    bool hasSelect = (activateChildWnd() && activateChildWnd()->textCursor().hasSelection());
    ui->cutAction->setEnabled(hasSelect);
    ui->copyAction->setEnabled(hasSelect);
    ui->boldAction->setEnabled(hasSelect);

    ui->italicAction->setEnabled(hasSelect);
    ui->underlineAction->setEnabled(hasSelect);
    ui->leftAlignAction->setEnabled(hasSelect);
    ui->centerAction->setEnabled(hasSelect);
    ui->rightAlignAction->setEnabled(hasSelect);
    ui->justifyAction->setEnabled(hasSelect);
    ui->colorAction->setEnabled(hasSelect);
}

MyChildWnd* MainWindow::activateChildWnd()
{
    //若有活动文档窗口则将其内的中心部件转换为MyChildWnd类型;若没有则直接返回0
    if (QMdiSubWindow *actSubWnd = ui->mdiArea->activeSubWindow())
        return qobject_cast<MyChildWnd *>(actSubWnd->widget());
    else
        return 0;
}

void MainWindow::addSubWndListMenu()
{
    //首先清空原【窗口】菜单,然后再添加各菜单项
    ui->menu_W->clear();
    ui->menu_W->addAction(ui->closeAction);
    ui->menu_W->addAction(ui->closeAllAction);
    ui->menu_W->addSeparator();
    ui->menu_W->addAction(ui->tileAction);
    ui->menu_W->addAction(ui->cascadeAction);
    ui->menu_W->addSeparator();
    ui->menu_W->addAction(ui->nextAction);
    ui->menu_W->addAction(ui->previousAction);
    QList<QMdiSubWindow *> wnds = ui->mdiArea->subWindowList();
    if (!wnds.isEmpty()) ui->menu_W->addSeparator();//如果有活动子窗口,显示分隔条
    //遍历各个子窗口,显示所有当前已打开的文档子窗口项
    for (int i = 0; i < wnds.size(); ++i)
    {
        MyChildWnd *childwnd = qobject_cast<MyChildWnd *>(wnds.at(i)->widget());
        QString menuitem_text;
        if (i < 9)
        {
            menuitem_text = tr("&%1 %2").arg(i + 1).arg(childwnd->getCurDocName());
        } else {
            menuitem_text = tr("%1 %2").arg(i + 1).arg(childwnd->getCurDocName());
        }
        //添加子窗口菜单项,设置其可选
        QAction *menuitem_act = ui->menu_W->addAction(menuitem_text);
        menuitem_act->setCheckable(true);
        //将当前活动的子窗口设为勾选状态
        menuitem_act->setChecked(childwnd == activateChildWnd());
        //关联菜单项的触发信号到信号映射器的map()槽,该槽会发送mapped()信号
        connect(menuitem_act, SIGNAL(triggered()), myWndMapper, SLOT(map()));
        //将菜单项与相应的窗口部件进行映射,在发送mapped()信号时就会以这个窗口部件为参数
        myWndMapper->setMapping(menuitem_act, wnds.at(i));
    }
    formatEnabled();//使【字体】菜单下的功能可用
}
void MainWindow::setActiveSubWindow(QWidget *wnd)
{
    if (!wnd) return;
    ui->mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow *>(wnd));
}
void MainWindow::closeEvent(QCloseEvent *event)
{
    ui->mdiArea->closeAllSubWindows();
    if(ui->mdiArea->currentSubWindow())
    {
        event->ignore();
    }
    else {
        event->accept();
    }
}

mychildwnd.h

#ifndef MYCHILDWND_H
#define MYCHILDWND_H

#include <QWidget>
#include <QTextEdit>
#include <QFileInfo>
#include <QTextCodec>
#include <QFileDialog>
#include <QTextDocumentWriter>
#include <QMessageBox>
#include <QCloseEvent>
#include <QtWidgets>
#include <QPrinter>

class MyChildWnd : public QTextEdit
{
    Q_OBJECT
public:
    MyChildWnd();
    QString myCurDocPath;//当前文档路径全名
    void newDoc();//新建文档
    QString getCurDocName();//从路径中提取文档名
    bool loadDoc(const QString &docName);//加载文档内容
    bool saveDoc();//保存文件
    bool saveAsDoc();//另存为
    bool saveDocOpt(QString docName);//具体执行保存操作
    void setFormatOnSelectedWord(const QTextCharFormat &fmt);//设置字体与字号
    void setAlignOfDocumentText(int aligntype);//设置对齐样式
    void setParaStyle(int pstyle);//设置段落标号和编号

protected:
    void closeEvent(QCloseEvent *event);
private slots:
    void docBeModified();//文档被修改(尚未保存)时,在窗口标题栏显示*号
private:
    bool beSaved;//文档是否已存盘
    void setCurDoc(const QString &docName);//对当前加载文档的状态进行设置,并保存其路径全名
    bool promptSave();//用户关闭文档的时候提示保存
    
};

#endif // MYCHILDWND_H

mychildwnd.cpp

#include "mychildwnd.h"

MyChildWnd::MyChildWnd()
{
    setAttribute(Qt::WA_DeleteOnClose);//子窗口关闭时销毁该类对象实例
    beSaved = false;//初始文档尚未保存
}
//创建一个新文档
void MyChildWnd::newDoc()
{
    //设置窗口编号
    static int wndSeqNum = 1;
    //将当前打开的文档命名为"Word 文档 编号"的形式,编号在使用完一次后自增1
    myCurDocPath = tr("Word 文档 %1").arg(wndSeqNum++);
    //设置窗口标题,文档被改动后在其名称后面显示"*"号标识
    setWindowTitle(myCurDocPath + "[*]" + tr(" - MyWord"));
    //文档被改动时发送contensChanged()信号,执行自定义docBeModified()槽函数
    connect(document(),SIGNAL(contentsChanged()),this,SLOT(docBeModified()));
}
//文档被修改(尚未保存)时,在窗口标题栏显示*号
void MyChildWnd::docBeModified()
{
    setWindowModified(document()->isModified());//判断文档内容是否被更新
}
//从路径中提取文档名
QString MyChildWnd::getCurDocName()
{
    return QFileInfo(myCurDocPath).fileName();
}

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

}
//加载文档内容
bool MyChildWnd::loadDoc(const QString &docName)
{
    if(!docName.isEmpty())
    {
        if(!QFile::exists(docName))
            return false;
        QFile doc(docName);
        if(!doc.open(QFile::ReadOnly))
            return false;
        QByteArray text = doc.readAll();
        QTextCodec *text_codec = Qt::codecForHtml(text);
        QString str = text_codec->toUnicode(text);
        if(Qt::mightBeRichText(str))
        {
            this->setHtml(str);
        }
        else
        {
            str = QString::fromLocal8Bit(text);
            this->setPlainText(str);
        }
        setCurDoc(docName);
        connect(document(),SIGNAL(contentsChanged()),this,SLOT(docBeModified()));
        return true;
    }
}
//对当前加载文档的状态进行设置,并保存其路径全名
void MyChildWnd::setCurDoc(const QString &docName)
{
    myCurDocPath = QFileInfo(docName).canonicalFilePath();
    beSaved = true;//文档已经被保存过
    document()->setModified(false);//文档未被改动
    setWindowModified(false);//窗口不显示被改动标识
    setWindowTitle(getCurDocName() + "[*]");//设置文档名为子窗口标题
}
//保存文件
bool MyChildWnd::saveDoc()
{
    if(!beSaved)
        return saveAsDoc();
    else {
        saveDocOpt(myCurDocPath);
    }
}
//另存为
bool MyChildWnd::saveAsDoc()
{
    QString docName = QFileDialog::getSaveFileName(this,tr("另存为"),myCurDocPath,tr("HTML 文档 (*.htm *.html);;所有文件 (*.*)"));
    if(docName.isEmpty())
        return false;
    else {
        return saveDocOpt(docName);
    }
}
//用户关闭文档的时候提示保存
bool MyChildWnd::promptSave()
{
    if(!document()->isModified())
        return true;
    QMessageBox::StandardButton result;
    result = QMessageBox::warning(this,tr("MyWord"),tr("文档'%1'已被更改,保存吗?").arg(getCurDocName()),QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
    if(result == QMessageBox::Save)
        return saveDoc();
    else if(result == QMessageBox::Cancel)
        return false;
    return true;
}
//具体执行保存操作
bool MyChildWnd::saveDocOpt(QString docName)
{
    if(!(docName.endsWith(".htm",Qt::CaseInsensitive) || docName.endsWith(".html",Qt::CaseInsensitive)))
    {
        docName += ".html";//默认保存为HTML文档
    }
    QTextDocumentWriter writer(docName);
    bool success = writer.write(this->document());
    if(success)
        setCurDoc(docName);
    return success;
}
//设置字体与字号
void MyChildWnd::setFormatOnSelectedWord(const QTextCharFormat &fmt)
{
    QTextCursor tcursor = this->textCursor();
    if(!tcursor.hasSelection())
        tcursor.select(QTextCursor::WordUnderCursor);
    tcursor.mergeCharFormat(fmt);
    this->mergeCurrentCharFormat(fmt);
}
//设置对齐方式
void MyChildWnd::setAlignOfDocumentText(int aligntype)
{
    if(aligntype == 1)
        this->setAlignment(Qt::AlignLeft | Qt::AlignAbsolute);
    else if(aligntype == 2)
        this->setAlignment(Qt::AlignHCenter);
    else if(aligntype == 3)
        this->setAlignment(Qt::AlignRight | Qt::AlignAbsolute);
    else if(aligntype == 4)
        this->setAlignment(Qt::AlignJustify);
}
//设置段落标号和编号
void MyChildWnd::setParaStyle(int pstyle)
{
    QTextCursor tcursor = this->textCursor();
    if(pstyle != 0)
    {
        //文本列表格式
        QTextListFormat::Style sname = QTextListFormat::ListDisc;
        switch (pstyle) {
        default:
        case 1:
            sname = QTextListFormat::ListDisc;
            break;
        case 2:
            sname = QTextListFormat::ListCircle;
            break;
        case 3:
            sname = QTextListFormat::ListSquare;
            break;
        case 4:
            sname = QTextListFormat::ListDecimal;
            break;
        case 5:
            sname = QTextListFormat::ListLowerAlpha;
            break;
        case 6:
            sname = QTextListFormat::ListUpperAlpha;
            break;
        case 7:
            sname = QTextListFormat::ListLowerRoman;
            break;
        case 8:
            sname = QTextListFormat::ListUpperRoman;
            break;
        }
        tcursor.beginEditBlock();
        QTextBlockFormat tBlockFmt = tcursor.blockFormat();
        QTextListFormat tListFmt;
        if(tcursor.currentList())
        {
            tListFmt = tcursor.currentList()->format();
        }
        else
        {
            tListFmt.setIndent(tBlockFmt.indent()+1);
            tBlockFmt.setIndent(0);
            tcursor.setBlockFormat(tBlockFmt);
        }
        tListFmt.setStyle(sname);
        tcursor.createList(tListFmt);
        tcursor.endEditBlock();
    }
    else
    {
        QTextBlockFormat tbfmt;
        tbfmt.setObjectIndex(-1);
        tcursor.mergeBlockFormat(tbfmt);
    }
}

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

MyWord.pro

#-------------------------------------------------
#
# Project created by QtCreator 2021-09-26T18:23:21
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
qtHaveModule(printsupport): QT += printsupport
TARGET = MyWord
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += \
        main.cpp \
        mainwindow.cpp \
    mychildwnd.cpp

HEADERS += \
        mainwindow.h \
    mychildwnd.h

FORMS += \
        mainwindow.ui

RESOURCES += \
    res.qrc

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 在Qt中,提供了很多方便实用的功能模块,其中myword源码是一个用于实现文档编辑和处理的模块。通过使用myword源码,我们可以方便地创建、编辑和保存文档,以及进行一些文本处理的操作。 为了下载myword源码,我们可以按照以下步骤进行: 1. 首先,我们需要打开一个可靠的代码托管平台或者开源社区,例如GitHub或者Qt官方网站。 2. 在搜索框中输入"myword源码",然后执行搜索操作。 3. 在搜索结果中找到与我们需要的功能最匹配的项目。 4. 点击进入项目页面,查看项目的描述、功能特性以及其它详细信息。 5. 如果项目源码已经公开并托管在代码仓库中,我们可以在项目页面点击"Clone"或者"Download"按钮,选择合适的下载方式。 6. 选择下载源码的方式,通常可以选择将源码打包下载或者使用版本控制工具进行下载。 7. 完成下载后,我们可以解压源码包,并使用Qt Creator或者其它支持Qt开发的IDE打开项目。 8. 根据项目中的指导文档,进行编译和构建项目。 9. 运行编译后的应用程序,进一步测试和调试。 通过上述步骤,我们可以成功下载并使用myword源码,在Qt中进行文档编辑和处理的开发工作。同时,我们可以根据具体需求,进一步修改和定制源码,以满足自己的项目要求。希望以上信息对您有所帮助! ### 回答2: 在Qt中,myword是一个开源的词库,用于在文本处理和自然语言处理领域中提供词汇信息和辅助功能。您可以在QT官方网站或其他开源代码平台上找到myword的源代码下载链接。 首先,您可以在Qt官方网站上的下载页面搜索myword,如果有相关的工具或库,则可以直接从官方网站上获取源代码。官方网站提供了各种Qt相关的工具和开源库,以及详细的文档和示例代码,以帮助开发者更好地使用和理解这些代码。 另外,在其他开源代码平台上,如GitHub、GitLab等,您也可以通过搜索关键"myword"找到相关的源代码仓库。这些平台汇集了很多开发者发布的开源项目,包括Qt相关的代码。在项目页面中,您可以找到源代码的下载链接和相关的文档说明。 一旦您找到了myword的源代码下载链接,您可以通过点击下载按钮或使用命令行工具(如Git)进行下载。下载完成后,您可以将源代码解压到本地目录中。 在解压后的源代码中,您可以找到各种与myword相关的文件和目录。其中,包括主要的代码文件、头文件以及资源文件等。您可以根据需要将这些文件添加到您的Qt项目中,以便在您的应用程序中使用myword提供的功能。 在使用myword之前,建议您详细阅读相关的文档和示例代码,以便更好地理解和使用这个开源库。您可以在文档中找到关于使用方法、函数和类的说明,以及示例代码来帮助您快速上手。 总之,通过在Qt官方网站或其他开源代码平台上搜索myword,在找到相关源代码的下载链接后,下载并解压源代码,您就可以开始使用myword提供的功能,以实现您的文本处理和自然语言处理需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值