当前位置:网站首页>Text editor for QT project practice -- Episode 9

Text editor for QT project practice -- Episode 9

2022-06-25 01:00:00 PureヾChan

Previously, we have implemented text boxes or some functions of text , Next, we will focus on some operations on paragraphs . Some operations on paragraphs we think of are bold , Oblique cutting , And underline .

towards ChildWnd.h Add function :

public:
  void setFormatOnSelectedWord(const QTextCharFormat& fmt);

The essence of setting this function is to establish a connection with some functions of the main window , It is essentially a format setting function , And some formatting of fields , In fact, they all belong to ChildWnd Class .

The main idea is that the main window is a surface call , The child window is the substantive setting .

SetFormatOnSelectedWord() Function implementation :

void ChildWnd::setFormatOnSelectedWord(const QTextCharFormat &fmt)
{
    QTextCursor tCursor=textCursor();
    // Uncheck to select the text setting under the cursor 
    if(!tCursor.hasSelection()) tCursor.select(QTextCursor::WordUnderCursor);

    // Selected , Merge text formatting 
    tCursor.mergeCharFormat(fmt);// Merge the text selected by the cursor with the selected format 
    mergeCurrentCharFormat(fmt);// Set the format of the subsequent text editor to the cursor selected text 


}

Function will first get a copy of the cursor , Then judge whether the content indicated by the cursor is selected , If it is not selected, it will be set as the text under the selected cursor .

If the text content is already selected , Then merge the selected text with the selected format , That is to say tCursor.mergeCharFormat function . and mergeCurrentCharFormat Function sets the format of the entire text box to the selected format .

Add a function to the main window (mainWindow.h):

public:
 void textBold();// In bold 
    void textItalic();// Oblique cutting 
    void textUnderline();// Underline 

Function implementation :

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());
    // Determine as active child window 
    if(activateChildWnd()){
        activateChildWnd()->setFormatOnSelectedWord(fmt);

    }
}

void MainWindow::textUnderline()
{
    QTextCharFormat fmt;
    fmt.setFontUnderline(ui->underlineAction->isChecked());
    // Determine whether it is an active child window 
    if(activateChildWnd()){
        activateChildWnd()->setFormatOnSelectedWord(fmt);// Set the format according to the selected format 
    }
}

These functions define a format class first QTextCharFormat Object and then use setFontWeight Method to format text . Then judge whether this window is an active window , If so, call the subclass's function that actually sets the text format , Apply to active child window .

stay ui The document says Action( In bold , tilt , Underline ) Add slot function :

private slots:
    void on_boldAction_triggered();

    void on_italicAction_triggered();

    void on_underlineAction_triggered();

Function implementation :

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

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

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

The slot function calls the main window function , The main window function calls the sub window function .

Program effect :

Source code :

ChildWnd.h:

#ifndef CHILDWND_H
#define CHILDWND_H

#include<QTextEdit>

// The idea is to create a sub window editing area in the main window , Is to call the constructor of another class , So that is ChildWnd This class 
class ChildWnd : public QTextEdit
{
    Q_OBJECT
public:
    ChildWnd();
    QString m_Currentpath;  // The path of the current document 
    void newDoc();          // New document 
    QString GetCurDocName();// Extract the document name from the file path 
    bool loadDoc(const QString& docName);
    void setCurDoc(const QString& docName);// Set the current document function 
    bool saveDoc();// Save the document 
    bool saveAsDoc();// Save as document 
    bool saveDocOpt(QString &docName);// Actually perform the save operation 
    void setFormatOnSelectedWord(const QTextCharFormat& fmt);
protected:
    void closeEvent(QCloseEvent *event);// Turn off event handling 
private:
    bool promptSave();// Try to save 
private slots:
    void docBeModified();   // The corresponding slot function when modifying the document 
private:
    bool m_bSaved;          // Whether the document is saved 

};

#endif // CHILDWND_H

mainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include"childwnd.h"
#include<QSignalMapper>
#include<QMdiSubWindow>
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void InitMainWindow();// Initialize the window function 
    void DocNew();
    void DocOpen();
    void docSave();
    void docSaveAs();
    void docUndo();// revoke 
    void docRedo();// rewrite 
    void docCut();// shear 
    void docCopy();// Copy 
    void docPaste();// Paste 

    void textBold();// In bold 
    void textItalic();// Oblique cutting 
    void textUnderline();// Underline 

private slots:
    void on_newAction_triggered();
    void RefreshMenu();// Refresh window menu slot function 
    void addSubWindowListMenu();// Refresh window information function 
    void on_closeAction_triggered();

    void on_closeAllAction_triggered();

    void on_titleAction_triggered();

    void on_cascadeAction_triggered();

    void on_nextAction_triggered();

    void on_previousAction_triggered();

    void setActivSubWindow(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();

protected:
  void closeEvent(QCloseEvent *event);
private:
    void formatEnable();
    ChildWnd* activateChildWnd();// obtain mdieara Active child window of 
    // Find window functions 
    QMdiSubWindow* FindChildWnd(const QString& docName);


private:
    Ui::MainWindow *ui;
    QSignalMapper* m_singnalmapper;//  Create a signal mapper 
};

#endif // MAINWINDOW_H

ChildWnd.cpp

#include "childwnd.h"
#include<QFileInfo>
#include<QFileDialog>
#include<QTextDocumentWriter>
#include<QMessageBox>
#include<QCloseEvent>
ChildWnd::ChildWnd()
{
    // Destroy the instance object of the class when the child window is closed , Reach recycling 
    setAttribute(Qt::WA_DeleteOnClose);

    m_bSaved=false;// The original edit state is unchanged 
}

void ChildWnd::newDoc()
{
    static int wndSeqNum=1;
    m_Currentpath=QString("WPS  file  %1").arg(wndSeqNum++);// Each time you create a document, the name is different ,, utilize wndSeqNum To achieve the goal 

    // Set the title of the form , Add... After document changes “*” Number identification 
    setWindowTitle(m_Currentpath+"[*]"+"-MyWPS");
    connect(document(),SIGNAL(contentsChanged()),
            this,SLOT(docBeModified()));

}

QString ChildWnd::GetCurDocName()
{
    return QFileInfo(m_Currentpath).fileName();//fileINfo Class can be called from a file filename operation , Returns the file name extracted from the file path 
}

bool ChildWnd::loadDoc(const QString &docName)
{
   // First determine whether the loaded document name is empty 
    if(!docName.isEmpty()){
        QFile file(docName);// Get all the information of the file through the file name 
        if(!file.exists()) return false;// File does not exist return false

        if(!file.open(QFile::ReadOnly)) return false;// If the read-only mode fails to open, it returns false
        QByteArray text=file.readAll();
        if(Qt::mightBeRichText(text)){
            setHtml(text);// If it is rich text, it is set to HTml
        }else{
            setPlainText(text);// If the rich text is not set to simple string format 

        }
        setCurDoc(docName);
        connect(document(),SIGNAL(contentsChanged()),
                this,SLOT(docBeModified()));
        return true;
    }
}

void ChildWnd::setCurDoc(const QString &docName)
{

    m_Currentpath=QFileInfo(docName).canonicalFilePath();// It will put the path name of the file “.” All removed 
    m_bSaved=true;
    document()->setModified(false);// Set the document modification property to false
    setWindowModified(false);       // The window does not display the change logo 
    setWindowTitle(GetCurDocName()+"[*]");// Set sub window title 

}

bool ChildWnd::saveDoc()
{
    if(m_bSaved) return saveDocOpt(m_Currentpath);// Save directly after saving 
    else saveAsDoc();// Save as 

}

bool ChildWnd::saveAsDoc()
{
    // Save as, of course, provides a file window to prompt for saving 
    QString docName=QFileDialog::getSaveFileName(this,
                                 " Save as ",
                                 m_Currentpath,
                                 "HTML file  (*.htm *html);;"
                                 " All the files (*.*)");
    if(docName.isEmpty()) return false;
    else return saveDocOpt(docName);
}

bool ChildWnd::saveDocOpt(QString &docName)
{
    if(!(docName.endsWith(".htm",Qt::CaseInsensitive)||
         docName.endsWith(".html",Qt::CaseInsensitive))){
        // If it does not end in the specified format , Add specified format 
        docName+=".html";

    }
    QTextDocumentWriter writer(docName);
    bool isSuccess=writer.write(this->document());//write Method returns the write state 
    if(isSuccess) setCurDoc(docName);// Survey setting window status function 
    return isSuccess;

}

void ChildWnd::setFormatOnSelectedWord(const QTextCharFormat &fmt)
{
    QTextCursor tCursor=textCursor();
    // Uncheck to select the text setting under the cursor 
    if(!tCursor.hasSelection()) tCursor.select(QTextCursor::WordUnderCursor);

    // Selected , Merge text formatting 
    tCursor.mergeCharFormat(fmt);// Merge the text selected by the cursor with the selected format 
    mergeCurrentCharFormat(fmt);// Set the format of the subsequent text editor to the cursor selected text 


}

void ChildWnd::closeEvent(QCloseEvent *event)
{
    if(promptSave()) event->accept();// Accept the event 
    else event->ignore();// Ignore Events 
}

bool ChildWnd::promptSave()
{
    // The document has not been modified 
    if(!document()->isModified()) return true;

    QMessageBox::StandardButton result;
    result=QMessageBox::warning(this,
                               QString(" System prompt "),
                               QString(" file %1 The modified , Save ?")
                                .arg(GetCurDocName()),
                                QMessageBox::Yes|
                                QMessageBox::Discard|
                                QMessageBox::No);
    if(result==QMessageBox::Yes){
        return saveDoc();
    }else if(result==QMessageBox::No){
        return false;
    }
    return true;// Select ignore to return true 


}

void ChildWnd::docBeModified()
{
    setWindowModified(document()->isModified());
}

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"childwnd.h"
#include<QDebug>
#include<QMdiSubWindow>
#include<QList>
#include<QCloseEvent>
#include<QFileDialog>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    InitMainWindow();
}

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

// Initialize the window function 
void MainWindow::InitMainWindow()
{
    // Initialize the character list 
    QFontDatabase fontdb;
    foreach (int fontsize, fontdb.standardSizes()) {
       //standarSizes The function returns the standard character list . Here is the size of each standard character 
        // Pass to fontsize
        ui->FontSize_comboBox->addItem(QString::number(fontsize));// Pass the characters obtained each time to the component list 

    }

    QFont defFont;// Program default font ( Including font size and font style )
    QString sFontSize;
    int defFontSize;// The default font size of the current application 
    int defFontindex;// Serial number of the current font size table 
    defFont=QApplication::font();// Get the font style of the current program 
    defFontSize=defFont.pointSize();// Returns the current font size 

    sFontSize=QString::number(defFontSize);// Convert the integer font size to a convenient list of string type to find the sequence number 
    defFontindex=ui->FontSize_comboBox->findText(sFontSize);// Return the sequence number corresponding to the default font size 
    ui->FontSize_comboBox->setCurrentIndex(defFontindex);// Set the font size and serial number under the default program 


    // Add scroll bar 
    ui->mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);// Set the vertical scroll bar , Property to display when needed 
    ui->mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);// Set the horizontal scroll bar , Property to display when needed 
    // Note: when setting the scroll bar, you will encounter a small bug, When you want to set the scroll bar, you should leave a little space for the horizontal scroll bar , Otherwise it can't show 

    RefreshMenu();// When initializing, call to initialize the toolbar first 、

    // When there are active child windows , Transmit signal refresh menu 
    connect(ui->mdiArea,&QMdiArea::subWindowActivated,this,&MainWindow::RefreshMenu);

    addSubWindowListMenu();
    // Here we need another slot function corresponding to , When the window is clicked, new window contents are added 
    connect(ui->menu_W,&QMenu::aboutToShow,this,&MainWindow::addSubWindowListMenu);



    // Initialize the signal mapper 
    m_singnalmapper=new QSignalMapper(this);
    connect(m_singnalmapper,SIGNAL(mapped(QWidget*)),
            this,SLOT(setActivSubWindow(QWidget*)));
}

void MainWindow::DocNew()
{
    ChildWnd* childwnd=new ChildWnd;
    ui->mdiArea->addSubWindow(childwnd);// Add the new sub window to the editing area 

    // Assign and cut at the same time Action Establishing a connection 
    connect(childwnd,SIGNAL(copyAvailable(bool)),ui->cutAction,SLOT(setEnabled(bool)));
    connect(childwnd,SIGNAL(copyAvailable(bool)),ui->copyAction,SLOT(setEnabled(bool)));

    childwnd->newDoc();
    childwnd->show();
    formatEnable();// Set the toolbar to available after creating a new window 
}

void MainWindow::DocOpen()
{
   QString docName=QFileDialog::getOpenFileName(this,
                                " Open file ",
                                "",
                                " text file (*.txt);;"
                                "HTML file (*.html *.htm);;"
                                " All the files (*.*)");

   if(!docName.isEmpty()){
       QMdiSubWindow* existWnd=FindChildWnd(docName);
       if(existWnd){
           // If you find this sub window 
           ui->mdiArea->setActiveSubWindow(existWnd);// Make this window active 
           return;
       }
       ChildWnd* childWnd=new ChildWnd;
       ui->mdiArea->addSubWindow(childWnd);
       connect(childWnd,SIGNAL(copyAvailable(bool)),
               ui->cutAction,SLOT(setEnabled(bool)));//copyAvailable It is triggered when the document is opened and the text is selected 

       connect(childWnd,SIGNAL(copyAvailable(bool)),
               ui->copyAction,SLOT(setEnabled(bool)));

       if(childWnd->loadDoc(docName)){
         statusBar()->showMessage(" The file is open ",3000);
         childWnd->show();
         formatEnable();
       }else{
           childWnd->close();
       }
   }
}

void MainWindow::docSave()
{
    if(activateChildWnd()&&activateChildWnd()->saveDoc()){
        statusBar()->showMessage(" Saved successfully ",3000);
    }
}

void MainWindow::docSaveAs()
{
    if(activateChildWnd()&&activateChildWnd()->saveAsDoc()){
        statusBar()->showMessage(" Saved successfully ",3000);
    }
}

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::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());
        // Determine as active child window 
        if(activateChildWnd()){
            activateChildWnd()->setFormatOnSelectedWord(fmt);

        }
    }

    void MainWindow::textUnderline()
    {
        QTextCharFormat fmt;
        fmt.setFontUnderline(ui->underlineAction->isChecked());
        // Determine whether it is an active child window 
        if(activateChildWnd()){
            activateChildWnd()->setFormatOnSelectedWord(fmt);// Set the format according to the selected format 
        }
    }

void MainWindow::formatEnable()
{
    ui->boldAction->setEnabled(true);// Set the functions of the toolbar to available 
    ui->italicAction->setEnabled(true);
    ui->underlineAction->setEnabled(true);
    ui->letfAlignAction->setEnabled(true);
    ui->centerAlignAction->setEnabled(true);
    ui->rightAlignAction->setEnabled(true);
    ui->justifyAction->setEnabled(true);
    ui->colorAction->setEnabled(true);
    //qDebug()<<12%1<<endl;
}

ChildWnd *MainWindow::activateChildWnd()
{
    QMdiSubWindow*actWnd=ui->mdiArea->activeSubWindow();// Get the active window of the document editor 
    if(actWnd)
        return qobject_cast<ChildWnd*>(actWnd->widget());// If it is an active window, convert the window to the target window and return 
    else
        return 0;
}

QMdiSubWindow *MainWindow::FindChildWnd(const QString &docName)
{
    QString strFile=QFileInfo(docName).canonicalFilePath();
    foreach (QMdiSubWindow* subWnd, ui->mdiArea->subWindowList()) {
        ChildWnd* childWnd=qobject_cast<ChildWnd*>(subWnd->widget());// Convert each child window to ChildWnd type 
        if(childWnd->m_Currentpath==strFile)return subWnd;


    }
    return 0;
}


void MainWindow::on_newAction_triggered()
{
    DocNew();// Click the create action to create a new document 
}

void MainWindow::RefreshMenu()
{
    bool hasChild;
    hasChild=(activateChildWnd()!=0);
    ui->saveAction->setEnabled(hasChild);
    ui->printAction->setEnabled(hasChild);
    ui->saveAsAction->setEnabled(hasChild);
    ui->printPreviewAction->setEnabled(hasChild);
    ui->pasteAction->setEnabled(hasChild);
    ui->closeAction->setEnabled(hasChild);
    ui->closeAllAction->setEnabled(hasChild);
    ui->titleAction->setEnabled(hasChild);
    ui->cascadeAction->setEnabled(hasChild);
    ui->nextAction->setEnabled(hasChild);
    ui->previousAction->setEnabled(hasChild);

    // Besides the above document operations, there are also text operations 
    bool hasSelect=(activateChildWnd() && activateChildWnd()->textCursor().hasSelection());//textcursor The function returns information about the selected text , This function is used to check whether the text is selected 
    ui->copyAction->setEnabled(hasSelect);
    ui->cutAction->setEnabled(hasSelect);
    ui->boldAction->setEnabled(hasSelect);
    ui->italicAction->setEnabled(hasSelect);
    ui->underlineAction->setEnabled(hasSelect);
    ui->letfAlignAction->setEnabled(hasSelect);
    ui->centerAlignAction->setEnabled(hasSelect);
    ui->rightAlignAction->setEnabled(hasSelect);
    ui->colorAction->setEnabled(hasSelect);
    ui->justifyAction->setEnabled(hasSelect);

}

void MainWindow::addSubWindowListMenu()
{
    // Because every time you click hi Execute this function , If you don't clear it first, the menu bar will become longer and longer 
    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->titleAction);
    ui->menu_W->addAction(ui->cascadeAction);
    ui->menu_W->addSeparator();
    ui->menu_W->addAction(ui->nextAction);
    ui->menu_W->addAction(ui->previousAction);


    // This is the corresponding function when clicking on the window , Then we have to judge whether there is an active sub window 
    QList<QMdiSubWindow*> wnds=ui->mdiArea->subWindowList();// This function will mdiArea The window in the is returned in the form of a linked list 
    if(!wnds.isEmpty()){
        ui->menu_W->addSeparator();// If there is an active child window, add a split line 
    }
    for(int i=0;i<wnds.size();++i){
        ChildWnd* childwnd=qobject_cast<ChildWnd*>(wnds.at(i)->widget());// Convert the elements in the linked list into components , Then the type is converted to ChildWnds
        QString menuItem_text;
        menuItem_text=QString("%1 %2")
                .arg(i+1)
                .arg(childwnd->GetCurDocName());
        QAction* menuItem_act=ui->menu_W->addAction(menuItem_text);// Add the name of the window to menu_w Inside 
        menuItem_act->setCheckable(true);
        menuItem_act->setChecked(childwnd==activateChildWnd());// Check whether it is an active sub window ,activateChildWnd Function returns whether the window is an active child window 

        // Add each one to the Action Add signal 
        connect(menuItem_act,SIGNAL(triggered(bool)),
                m_singnalmapper,SLOT(map()));// every last action The menu will trigger when it is clicked triggered Signal execution map() Slot function 
        // In this case, it will be implemented map() function , But how to distinguish them ?
        m_singnalmapper->setMapping(menuItem_act,wnds.at(i));// By setting different Action The difference between , Use serial numbers to distinguish 


    }
    formatEnable();
}

void MainWindow::on_closeAction_triggered()
{
    ui->mdiArea->closeActiveSubWindow();// Close the active child window 
}

void MainWindow::on_closeAllAction_triggered()
{
    ui->mdiArea->closeAllSubWindows();// Close all active child windows 

}

void MainWindow::on_titleAction_triggered()
{
    ui->mdiArea->tileSubWindows();// tile 
}

void MainWindow::on_cascadeAction_triggered()
{
    ui->mdiArea->cascadeSubWindows();//cengdie
}

void MainWindow::on_nextAction_triggered()
{
    ui->mdiArea->activateNextSubWindow();// Next window 
}

void MainWindow::on_previousAction_triggered()
{
    ui->mdiArea->activatePreviousSubWindow();// The previous window 
}

void MainWindow::setActivSubWindow(QWidget*wnd)
{
    // First, determine whether it is an active child window 
    if(!wnd){
        return;

    }else{
        // Set this window in the text editing area as the active sub window 
        ui->mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow*>(wnd));
        // Setting the active sub window is passed into a text editing area mdiSubWindow Of , So type conversion is used here 

    }
}
void MainWindow::closeEvent(QCloseEvent *event){
    ui->mdiArea->closeAllSubWindows();// When the window is closed, of course, the child window must also be closed 
    if(ui->mdiArea->currentSubWindow())
        event->ignore();// Ignore this event 
    else
        event->accept();// Accept this event 
}

void MainWindow::on_openAction_triggered()
{
    DocOpen();// Open document 
}

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

void MainWindow::on_saveAsAction_triggered()
{
    docSaveAs();// Save as 
}

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::on_boldAction_triggered()
{
    textBold();
}

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

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

 

原网站

版权声明
本文为[PureヾChan]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202210545037064.html