一 界面设计
1.1 新建项目
- 建立mianwindow
1.2 添加action
- 知识点:添加次级菜单的方式,直接拖拽到例如”字体“后面的到三角位置即可
1.3 界面部件
- 添加语句
ui->mdiArea->setBackground(Qt::white);
使得背景变成白色
- 添加语句
RC_ICONS += images/wps.ico
, 设置窗口图标
1.4 创建新的c++类,继承QTextEdit来实现多窗口的编辑界面显示
- 新建成的c++类如下,需要做头文件声明
#include QTextEdit
,添加Q_OBJECT
,并使其构造函数修改成TextEdit(QWidget *parent = nullptr);
,为为什么要这么做,是因为当前类继承于QTextEdit
,c++类在实现的时候,是先调用并构造父类才构造子类,而父类的构造函数里面需要传入参数QWidget *parent = nullptr
,此处不需要使用到const string,所以使用第二个构造函数,所以需要对当前的类的构造函数进行修改
二 代码实现
2.0 几个重要的连接
- 连接1:有些按键的功能需要选中文本之后才可以使用,如何判断文本是否被选中,
on_initTextAction
是自定义信号槽,将copyAvailable
中的信号发送给信号槽,控制按键是否可以使用
//如果打开的窗体中选中或取消选中文本时候,&TextEdit::copyAvailable 可以发送信号,
connect(edit,&myTextEdit::copyAvailable, this, &MainWindow::on_initTextAction);
void MainWindow::on_initTextAction(bool checked)
{
ui->actionCut->setEnabled(checked);
ui->actionCopy->setEnabled(checked);
ui->actionPaste->setEnabled(checked);
ui->actionColor->setEnabled(checked);
ui->actionBold->setEnabled(checked);
ui->actionItaly->setEnabled(checked);
ui->actionUnderline->setEnabled(checked);
ui->actionLeftAlign->setEnabled(checked);
ui->actionRightAlign->setEnabled(checked);
ui->actionCenter->setEnabled(checked);
}
- 连接2:判断子窗体是否被激活,如果被激活,启动某些按钮
//窗体被激活的时候,发出信号&QMdiArea::subWindowActivated,当前窗体的initWindowAction会收到信号
//窗体被关闭也会发出信号,信号参数为0
connect(ui->mdiArea, &QMdiArea::subWindowActivated, this, &MainWindow::initAllWindowAction);
void MainWindow::initAllWindowAction()
{
bool hasACtiveWindow = (getActiveWindow() !=nullptr);
ui->actionSave->setEnabled(hasACtiveWindow);
ui->actionPrint->setEnabled(hasACtiveWindow);
ui->actionRedo->setEnabled(hasACtiveWindow);
ui->actionUndo->setEnabled(hasACtiveWindow);
ui->actionNext->setEnabled(hasACtiveWindow);
ui->actionPre->setEnabled(hasACtiveWindow);
ui->actionPrintView->setEnabled(hasACtiveWindow);
ui->actionCut->setEnabled(hasACtiveWindow);
ui->actionCopy->setEnabled(hasACtiveWindow);
ui->actionPaste->setEnabled(hasACtiveWindow);
ui->actionColor->setEnabled(hasACtiveWindow);
ui->actionBold->setEnabled(hasACtiveWindow);
ui->actionItaly->setEnabled(hasACtiveWindow);
ui->actionUnderline->setEnabled(hasACtiveWindow);
ui->actionLeftAlign->setEnabled(hasACtiveWindow);
ui->actionRightAlign->setEnabled(hasACtiveWindow);
ui->actionCenter->setEnabled(hasACtiveWindow);
}
- 连接三:目的,在“窗口”菜单栏中显示所有打开的窗口
//将活动窗口添加到菜单栏
actionGroup = new QActionGroup(this); //创建一个action group来装action
actionGroup->setExclusive(true); //选中的action只能有一个
signalMap = new QSignalMapper(this);
connect(ui->menuWindow,&QMenu::aboutToShow, this, &MainWindow::on_addActionWindowToMenu);
connect(signalMap,SIGNAL(mapped(QWidget*)),this,SLOT(on_connectActionAndMap(QWidget*)));
2.1 setWindowModified
机制,作用是如果当窗显示的文档有未保存的更改,就会显示*
void TextEdit::initNewDoc()
{
//修改子窗体的标题
docName = QString ("文档 %1").arg(docNo++);
//使用windowModified 机制,添加[*]占位符
//当窗显示的文档有未保存的更改,就会显示*
setWindowTitle(docName + "[*]");
//document() 返回当前textEdit内的文档
connect(document(),&QTextDocument::contentsChanged,this, &TextEdit::setWindowModify);
}
void TextEdit::setWindowModify()
{
//返回文档是否被用户修改
setWindowModified(document()->isModified());
}
2.2 打印和打印预览功能,需要修改.pro文件
,包含头文件
#include <QPrinter>
#include <QPrintDialog>
#include <QPrintPreviewDialog>
2.3 映射器的作用,实现多个不同的信号,捆绑连接到同一个槽函数,简化信号连接过程,但是要求是同类型的信号,映射器在当前案例中的实现就是,每个打开的文档,为其创建了一个action,将他们添加到工具栏里面显示
- action发送信号给映射器,映射器发送信号给主窗体来控制对应的子窗体,为啥不都在void MainWindow::addAcrtionsToMenu()里面connect,要去初始化函数里面连接? 是因为槽不是只调用一次
void MainWindow::init()
{
。。。。。。。。
connect(ui->menu_window,&QMenu::aboutToShow, this,&MainWindow::addAcrtionsToMenu);
connect(signalMap,SIGNAL(mapped(QWidget*)),this,SLOT(connectActionAndMap(QWidget*)));
}
void MainWindow::addAcrtionsToMenu()
{
QList <QMdiSubWindow *> subWindowList = ui->mdiArea->subWindowList(); //获取子窗体列表
if(!subWindowList.isEmpty()) ui->menu_window->addSeparator(); //在菜单上添加一个分隔符
for(int i=0;i <subWindowList.count(); i++){
QMdiSubWindow *subWindow = subWindowList[i];
TextEdit *edit = qobject_cast<TextEdit*>(subWindow->widget());
QString actionTitle = QString("%1 %2").arg(i+1).arg(edit->getDocName());
QAction *action = ui->menu_window->addAction(actionTitle); //向菜单添加actiOn
actionGroup->addAction(action);
if(edit == SubWindow()) action->setCheckable(true); //对应的活动子窗体设置为被选中状态
//将action 的triggered信号发送给信号映射器signalMap,由map来进行统一的转发
connect(action,SIGNAL(triggered(bool)),signalMap,SLOT(map()));
signalMap->setMapping(action,subWindow); //添加映射,设置信号发送者和要发送的参数
}
}
void MainWindow::connectActionAndMap(QWidget *widget)
{
if(widget) ui->mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow*>(widget));
}
2.4 窗体的关闭,需要重写父类函数 void closeEvent(QCloseEvent *event) override;
,当前案例对应mainWindow有自己的关闭,以及打开的文档有自己的关闭需求,因此在各自的头文件里面都需要重写该函数,this->close()
,本质也是调用该函数
2.5 MDI添加滚动条
ui->mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
ui->mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
2.6 修改MDI背景色
//背景初始化
ui->mdiArea->setBackground(Qt::white);
2.7 将文本内容写入本地文件,当前案例是继承QTextEdit
,如果是继承QPlainTextEdit
,代码也不需要修改,因为 QPlainTextEdit 和 QTextEdit 都使用 QTextDocument 作为其文档模型,QTextEdit
可以处理纯文本或者富文本(除了纯文本就是富文本,包含图片或者其他HTML格式等),QPlainTextEdit
只能处理纯文本
//打开文件对话框
QString filename = QFileDialog::getSaveFileName(this,"另存为","../","HTML文档(*.html);;文本文档(*.txt)");
if(filename.isEmpty())
{
return false;
}
QTextDocumentWriter QdocWrite(filename);
QdocWrite.write(this->document());
2.8 字号下拉框的初始化,需要手动初始化,才会产生下拉框,字体下拉框不需要手动初始化,标准格式初始化是直接在编辑组合框
里面进行内容的添加
- 初始化字体下选框,在自定义函数中实现
void MainWindow::initFontSize()
{
ui->comboBoxSize->clear();
for(int fontSzie:QFontDatabase::standardSizes()){
ui->comboBoxSize->addItem(QString::number(fontSzie));
}
QFont appFont = QApplication::font(); //当前程序的默认字体
int fontsize = appFont.pointSize(); // 当前应用程序的字号
int sizeIndex = ui->comboBoxSize->findText(QString::number(fontsize));
ui->comboBoxSize->setCurrentIndex(sizeIndex);
};
- 将选中的内容设置为相应的字号,在槽函数中实现
void MainWindow::on_comboBoxSize_activated(const QString &arg1)
{
myTextEdit *edit = getActiveWindow(); //获取活动子窗体
if(edit){
QTextCharFormat format;
format.setFontPointSize(arg1.toInt());
edit->mergeCurrentCharFormat(format);
}
}
三 总代码
MainWindow .h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "mytextedit.h"
#include <QCloseEvent>
#include <QActionGroup>
#include <QSignalMapper>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_actionNew_triggered();
void on_actionOpen_triggered();
void on_actionSave_triggered();
void on_actionUndo_triggered();
void on_actionRedo_triggered();
void on_actionCopy_triggered();
void on_actionPaste_triggered();
void on_actionCut_triggered();
void on_actionColor_triggered();
void on_actionBold_triggered(bool checked);
void on_actionItaly_triggered(bool checked);
void on_actionUnderline_triggered(bool checked);
void on_actionLeftAlign_triggered(bool checked);
void on_actionRightAlign_triggered(bool checked);
void on_actionCenter_triggered(bool checked);
void on_actionPingPu_triggered();
void on_actionZanKai_triggered();
void on_actionPre_triggered();
void on_actionNext_triggered();
void on_initTextAction(bool checked);
void on_comboBoxStytle_activated(int index);
void on_fontComboBox_activated(const QString &arg1);
void on_comboBoxSize_activated(const QString &arg1);
void on_addActionWindowToMenu();
void on_connectActionAndMap(QWidget *widget);
protected:
void closeEvent(QCloseEvent *event) override;
private:
Ui::MainWindow *ui;
myTextEdit *getActiveWindow();
void init();
void initAllWindowAction();
void initTextAction(bool checked); //初始化文字操作相关的按钮
void initFontSize(); //初始化字号组合框
QActionGroup *actionGroup;
QSignalMapper *signalMap;
};
#endif // MAINWINDOW_H
myTextEdit.h
#ifndef MYTEXTEDIT_H
#define MYTEXTEDIT_H
#include <QObject>
#include <QTextEdit>
#include <QCloseEvent>
class myTextEdit : public QTextEdit
{
Q_OBJECT
public:
myTextEdit(QWidget *parent = nullptr);
~myTextEdit();
void NewDoc();
bool OpenDoc();
bool SaveDoc();
bool WriteToFile(QString docRoot); //将写的内容存入指定文档
bool DocSaveAs(); //已有文件做了修改,需要保存修改
int get_docIndex();
void loadFile(const QString filename);
QString getDocName();
protected:
void closeEvent(QCloseEvent *event) override;
private:
static int docIndex; //打开的文档的编号
QString docName;
QString docRoot;
private slots:
void on_isDocModified();
};
#endif // MYTEXTEDIT_H
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QColorDialog>
#include <QMdiSubWindow>
#include <QTextList>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
init();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::init()
{
//背景初始化
ui->mdiArea->setBackground(Qt::white);
//添加两个滚动条
ui->mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
ui->mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
//窗体被激活的时候,发出信号&QMdiArea::subWindowActivated,当前窗体的initWindowAction会收到信号
//窗体被关闭也会发出信号,信号参数为0
connect(ui->mdiArea, &QMdiArea::subWindowActivated, this, &MainWindow::initAllWindowAction);
initAllWindowAction();
initTextAction(false); //文件界面打开的时为空,相关文字操作也应该是不能操作的
initFontSize();
//将活动窗口添加到菜单栏
actionGroup = new QActionGroup(this); //创建一个action group来装action
actionGroup->setExclusive(true); //选中的action只能有一个
signalMap = new QSignalMapper(this);
connect(ui->menuWindow,&QMenu::aboutToShow, this, &MainWindow::on_addActionWindowToMenu);
connect(signalMap,SIGNAL(mapped(QWidget*)),this,SLOT(on_connectActionAndMap(QWidget*)));
}
void MainWindow::initAllWindowAction()
{
bool hasACtiveWindow = (getActiveWindow() !=nullptr);
ui->actionSave->setEnabled(hasACtiveWindow);
ui->actionPrint->setEnabled(hasACtiveWindow);
ui->actionRedo->setEnabled(hasACtiveWindow);
ui->actionUndo->setEnabled(hasACtiveWindow);
ui->actionNext->setEnabled(hasACtiveWindow);
ui->actionPre->setEnabled(hasACtiveWindow);
ui->actionPrintView->setEnabled(hasACtiveWindow);
ui->actionCut->setEnabled(hasACtiveWindow);
ui->actionCopy->setEnabled(hasACtiveWindow);
ui->actionPaste->setEnabled(hasACtiveWindow);
ui->actionColor->setEnabled(hasACtiveWindow);
ui->actionBold->setEnabled(hasACtiveWindow);
ui->actionItaly->setEnabled(hasACtiveWindow);
ui->actionUnderline->setEnabled(hasACtiveWindow);
ui->actionLeftAlign->setEnabled(hasACtiveWindow);
ui->actionRightAlign->setEnabled(hasACtiveWindow);
ui->actionCenter->setEnabled(hasACtiveWindow);
}
void MainWindow::initTextAction(bool checked)
{
ui->actionCut->setEnabled(checked);
ui->actionCopy->setEnabled(checked);
ui->actionPaste->setEnabled(checked);
ui->actionColor->setEnabled(checked);
ui->actionBold->setEnabled(checked);
ui->actionItaly->setEnabled(checked);
ui->actionUnderline->setEnabled(checked);
ui->actionLeftAlign->setEnabled(checked);
ui->actionRightAlign->setEnabled(checked);
ui->actionCenter->setEnabled(checked);
}
void MainWindow::initFontSize()
{
ui->comboBoxSize->clear();
for(int fontSzie:QFontDatabase::standardSizes()){
ui->comboBoxSize->addItem(QString::number(fontSzie));
}
QFont appFont = QApplication::font(); //当前程序的默认字体
int fontsize = appFont.pointSize(); // 当前应用程序的字号
int sizeIndex = ui->comboBoxSize->findText(QString::number(fontsize));
ui->comboBoxSize->setCurrentIndex(sizeIndex);
};
void MainWindow::on_actionNew_triggered()
{
myTextEdit *edit = new myTextEdit(this);
ui->mdiArea->addSubWindow(edit);
edit->show();
edit->NewDoc();
initTextAction(false); //文件界面打开的时为空,相关文字操作也应该是不能操作的
//如果打开的窗体中选中或取消选中文本时候,&TextEdit::copyAvailable 可以发送信号,
connect(edit,&myTextEdit::copyAvailable, this, &MainWindow::on_initTextAction);
}
void MainWindow::on_actionOpen_triggered()
{
myTextEdit *edit = new myTextEdit(this);
ui->mdiArea->addSubWindow(edit);
edit->OpenDoc();
initTextAction(false);
//如果打开的窗体中选中或取消选中文本时候,&TextEdit::copyAvailable 可以发送信号,
connect(edit,&myTextEdit::copyAvailable, this, &MainWindow::on_initTextAction);
}
void MainWindow::on_actionSave_triggered()
{
myTextEdit *edit = new myTextEdit(this);
ui->mdiArea->addSubWindow(edit);
edit->SaveDoc();
}
void MainWindow::closeEvent(QCloseEvent *event){
}
myTextEdit *MainWindow::getActiveWindow()
{
//返回当前活动窗口,如果没有就是空
QMdiSubWindow *window = ui->mdiArea->activeSubWindow();
if(window){
return qobject_cast<myTextEdit*>(window->widget());
}
else {
return nullptr;
}
}
void MainWindow::on_actionUndo_triggered()
{
myTextEdit *edit = this->getActiveWindow(); //获取活动子窗体
if(edit){
edit->undo();
}
}
void MainWindow::on_actionRedo_triggered()
{
myTextEdit *edit = this->getActiveWindow(); //获取活动子窗体
if(edit){
edit->redo();
}
}
void MainWindow::on_actionCopy_triggered()
{
myTextEdit *edit = this->getActiveWindow(); //获取活动子窗体
if(edit){
edit->copy();
}
}
void MainWindow::on_actionPaste_triggered()
{
myTextEdit *edit = this->getActiveWindow(); //获取活动子窗体
if(edit){
edit->paste();
}
}
void MainWindow::on_actionCut_triggered()
{
myTextEdit *edit = this->getActiveWindow(); //获取活动子窗体
if(edit){
edit->cut();
}
}
void MainWindow::on_actionColor_triggered()
{
myTextEdit *edit = this->getActiveWindow(); //获取活动子窗体
if(edit){
QColor color = QColorDialog::getColor();
if (color.isValid()) {
QTextCharFormat format; //为字体提供颜色选择
format.setForeground(color);//设置前景色
edit->mergeCurrentCharFormat(format); //设置选中文本的颜色
QPixmap pixmap(16,16);
pixmap.fill(color);
ui->actionColor->setIcon(pixmap);
}
}
}
void MainWindow::on_actionBold_triggered(bool checked)
{
myTextEdit *edit = this->getActiveWindow(); //获取活动子窗体
if(edit){
auto format = edit->currentCharFormat();
format.setFontWeight(checked ?QFont::Bold : QFont::Normal);
edit->mergeCurrentCharFormat(format);
}
}
void MainWindow::on_actionItaly_triggered(bool checked)
{
myTextEdit *edit = this->getActiveWindow(); //获取活动子窗体
if(edit){
auto format = edit->currentCharFormat();
format.setFontItalic(checked);
edit->mergeCurrentCharFormat(format);
}
}
void MainWindow::on_actionUnderline_triggered(bool checked)
{
myTextEdit *edit = this->getActiveWindow(); //获取活动子窗体
if(edit){
auto format = edit->currentCharFormat();
format.setFontUnderline(checked);
edit->mergeCurrentCharFormat(format);
}
}
void MainWindow::on_actionLeftAlign_triggered(bool checked)
{
myTextEdit *edit = this->getActiveWindow(); //获取活动子窗体
if(edit){
edit->setAlignment(Qt::AlignLeft);
}
}
void MainWindow::on_actionRightAlign_triggered(bool checked)
{
myTextEdit *edit = this->getActiveWindow(); //获取活动子窗体
if(edit){
edit->setAlignment(Qt::AlignRight);
}
}
void MainWindow::on_actionCenter_triggered(bool checked)
{
myTextEdit *edit = this->getActiveWindow(); //获取活动子窗体
if(edit){
edit->setAlignment(Qt::AlignCenter);
}
}
void MainWindow::on_actionPingPu_triggered()
{
ui->mdiArea->tileSubWindows();
}
void MainWindow::on_actionZanKai_triggered()
{
ui->mdiArea->cascadeSubWindows();
}
void MainWindow::on_actionPre_triggered()
{
ui->mdiArea->activatePreviousSubWindow();
}
void MainWindow::on_actionNext_triggered()
{
ui->mdiArea->activateNextSubWindow();
}
void MainWindow::on_initTextAction(bool checked)
{
ui->actionCut->setEnabled(checked);
ui->actionCopy->setEnabled(checked);
ui->actionPaste->setEnabled(checked);
ui->actionColor->setEnabled(checked);
ui->actionBold->setEnabled(checked);
ui->actionItaly->setEnabled(checked);
ui->actionUnderline->setEnabled(checked);
ui->actionLeftAlign->setEnabled(checked);
ui->actionRightAlign->setEnabled(checked);
ui->actionCenter->setEnabled(checked);
}
void MainWindow::on_comboBoxStytle_activated(int index)
{
myTextEdit *edit = getActiveWindow(); //获取活动子窗体
if(edit){
if(index == 0){ //标准格式,如果之前文本有格式,要去除原本的项目符号
QTextCursor curse = edit->textCursor(); //获取当前textEdit的可见游标的副本
curse.beginEditBlock(); //编辑开始
QTextList *list = curse.currentList();
if(list){
list->remove(curse.block());
QTextBlockFormat blockFormat = curse.blockFormat();
blockFormat.setIndent(0); //重置段落缩进
curse.setBlockFormat(blockFormat);
}
}
QTextListFormat::Style style;
switch(index){
case 1:
style = QTextListFormat::ListSquare;
break;
case 2:
style = QTextListFormat::ListCircle;
break;
case 3:
style = QTextListFormat::ListDisc;
break;
case 4:
style = QTextListFormat::ListUpperAlpha;
break;
case 5:
style = QTextListFormat::ListLowerAlpha;
break;
case 6:
style = QTextListFormat::ListLowerRoman;
break;
default:
style = QTextListFormat::ListStyleUndefined;
break;
}
QTextCursor curse = edit->textCursor(); //获取当前textEdit的可见游标的副本
curse.beginEditBlock(); //编辑开始
QTextBlockFormat blockFormat = curse.blockFormat();
QTextListFormat listFormat;
QTextList *list = curse.currentList();
if(list){
listFormat = list->format();
list->remove(curse.block());
blockFormat.setIndent(0);
curse.setBlockFormat(blockFormat);
}
listFormat.setStyle(style);
curse.createList(listFormat);
curse.endEditBlock(); //编辑结束
}
}
void MainWindow::on_fontComboBox_activated(const QString &arg1)
{
myTextEdit *edit = getActiveWindow(); //获取活动子窗体
if(edit){
QTextCharFormat format;
format.setFontFamily(arg1);
edit->mergeCurrentCharFormat(format);
}
}
void MainWindow::on_comboBoxSize_activated(const QString &arg1)
{
myTextEdit *edit = getActiveWindow(); //获取活动子窗体
if(edit){
QTextCharFormat format;
format.setFontPointSize(arg1.toInt());
edit->mergeCurrentCharFormat(format);
}
}
void MainWindow::on_addActionWindowToMenu()
{
QList<QAction*> actionList = actionGroup->actions();
for(QAction* action : actionList) //释放掉所有组内action
{
delete action;
}
QList <QMdiSubWindow*> subwindowList = ui->mdiArea->subWindowList(); //获取子窗体列表
if(!subwindowList.isEmpty()){
ui->menuWindow->addSeparator(); //在“窗口”菜单栏上添加一个分隔符
}
for(int i=0; i< subwindowList.count(); i++){
QMdiSubWindow* subwindow = subwindowList[i];
//获取当前的活动的action,添加到actionGroup
myTextEdit *edit =qobject_cast<myTextEdit*> (subwindow->widget());
QString actionTitle = QString("%1 %2").arg(i+1).arg(edit->getDocName());
QAction *action = ui->menuWindow->addAction(actionTitle);
actionGroup->addAction(action);
if(edit == getActiveWindow()){
action->setCheckable(true);
action->setChecked(true); //对应的活动子窗体设置为被选中状态
}
//将action 的triggered信号发送给信号映射器signalMap,由map来进行统一的转发
connect(action,SIGNAL(triggered(bool)),signalMap,SLOT(map()));
signalMap->setMapping(action,subwindow); //添加映射,设置信号发送者和要发送的参数
}
}
void MainWindow::on_connectActionAndMap(QWidget *widget)
{
if(widget) ui->mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow*>(widget));
}
myTextEdit.cpp
#include "mytextedit.h"
#include <QFileDialog>
#include <QFile>
#include <QTextStream>
#include <QMessageBox>
#include <QTextDocumentWriter>
int myTextEdit::docIndex = 1;
myTextEdit::myTextEdit(QWidget *parent):QTextEdit(parent)
{
docName = "";
docRoot = "";
}
myTextEdit::~myTextEdit()
{
}
void myTextEdit::NewDoc()
{
// docIndex++;
// this->setWindowTitle("文档" + QString::number(this->get_docIndex()));
// this->show();
docName = QString("文档%1").arg(docIndex++);
//使用windowModified 机制,添加[*]占位符
//当窗显示的文档有未保存的更改,就会显示*
this->setWindowTitle(docName + "[*]");
//document() 返回当前textEdit内的文档
connect(this->document(),&QTextDocument::contentsChanged,this, &myTextEdit::on_isDocModified);
this->show();
}
void myTextEdit::on_isDocModified()
{
//返回文档是否被用户修改
setWindowModified(document()->isModified());
}
bool myTextEdit::OpenDoc()
{
//打开文件对话框
QString fileroot = QFileDialog::getOpenFileName(this, "打开一个文件", QDir::currentPath(),
"所有文件(*.*);;源文件(*.h *.cpp);;文本文件(*.txt)");
if(fileroot.isEmpty()) return false;
this->show();
QFileInfo info(fileroot);
docName = info.fileName();
docRoot = fileroot;
this->setWindowTitle(docName + "[*]");
connect(this->document(),&QTextDocument::contentsChanged,this, &myTextEdit::on_isDocModified);
this->loadFile(fileroot);
}
bool myTextEdit::SaveDoc()
{
if(this->document()->isModified()){
if(docRoot.isEmpty()){ //如果当前文档的路径是空,说明是新建的文档
//打开文件对话框
QString docRoot = QFileDialog::getSaveFileName(this,"选择保存路径","../","HTML文档(*.html);;文本文档(*.txt)");
if(docRoot.isEmpty()) return false;
//将内容写入txt
WriteToFile(docRoot);
}else{ //打开的是已有的文档,需要另存为
DocSaveAs();
}
}
}
bool myTextEdit::WriteToFile(QString docRoot)
{
//QTextDocumentWriter类用于将QTextDocument内容写入本地文件
QTextDocumentWriter QdocWrite(docRoot);
if(QdocWrite.write(this->document())){ //如果写入成功
this->docRoot = QFileInfo(docRoot).canonicalFilePath(); //获取文件的绝对路径
this->document()->setModified(false);
setWindowModified(false); //窗口不显示*占位符
}
}
bool myTextEdit::DocSaveAs()
{
// this->docRoot = QFileInfo(docName).canonicalFilePath(); //获取文件的绝对路径
// QTextDocumentWriter QdocWrite(docRoot);
// QdocWrite.write(this->document());
QString docRoot = QFileDialog::getSaveFileName(this,"另存为","../","HTML文档(*.html);;文本文档(*.txt)");
if(docName.isEmpty()) return false;
return WriteToFile(docRoot);
}
int myTextEdit::get_docIndex()
{
return docIndex;
}
void myTextEdit::loadFile(const QString filename)
{
QFile file(filename);
if(file.open(QIODevice::ReadOnly )){
//QTextStream stream(&file);
//this->setPlainText(stream.readAll());
QByteArray text = file.readAll();
if(Qt::mightBeRichText(text)){ //判断是不是富文本,富文本可以存图片,样式等等,纯文本只存储文字
setHtml(text); //富文本显示
}else{
setPlainText(text); //纯文本显示
}
file.close();
}
}
QString myTextEdit::getDocName()
{
return docName;
}
void myTextEdit::closeEvent(QCloseEvent *event)
{
if(this->document()->isModified()){
auto res = QMessageBox::information(this,"提示","文件未保存,是否需要保存?",QMessageBox::Save|QMessageBox::No);
if(res == QMessageBox::Save){
//将内容写入txt
SaveDoc();
}else if(res == QMessageBox::No){
this->close();
}
}
}