{"id":2691,"date":"2025-11-08T12:14:39","date_gmt":"2025-11-08T03:14:39","guid":{"rendered":"https:\/\/www.freelifemakers.org\/wordpress\/?p=2691"},"modified":"2025-11-08T13:22:08","modified_gmt":"2025-11-08T04:22:08","slug":"qt","status":"publish","type":"post","link":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2025\/11\/08\/qt\/","title":{"rendered":"[QT]Rich Text Editor(2)"},"content":{"rendered":"\n<p>\ud83d\udc49\uc544\ub798\ub294 QT6\ubc84\uc804 \ud504\ub85c\uadf8\ub7a8 \uc18c\uc2a4 \ucf54\ub4dc \uc785\ub2c8\ub2e4.<br>Below is the QT6 version program source code.<\/p>\n\n\n\n<p>\ud83d\udc49\uc57d\uac04\uc758 \uae30\ub2a5\uc774 \ub354 \ucd94\uac00 \ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.<br>There are a few more features added.<\/p>\n\n\n\n<p><strong>1.main.cpp<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"mainwindow.h\"\n\n#include &lt;QApplication&gt;\n\nint main(int argc, char *argv&#91;])\n{\n    QApplication a(argc, argv);\n    MainWindow w;\n    w.show();\n    return a.exec();\n}\n\/*\n * fontAwesome : \ud3f0\ud2b8\ub2e4\uc6b4\ub85c\ub4dc \/ fontdownload\n * https:\/\/fontawesome.com\/search?q=pdf&amp;o=r\n *\n *\n *\n*\/\n<\/code><\/pre>\n\n\n\n<p><strong>2.mainwindow.h<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#ifndef MAINWINDOW_H\n#define MAINWINDOW_H\n\n#include &lt;QMainWindow&gt;\n#include &lt;QTextCharFormat&gt; \/\/ QTextCharFormat \uc0ac\uc6a9\uc744 \uc704\ud574 \ud3ec\ud568 \/ Included for use with QTextCharFormat\n#include &lt;QFileInfo&gt;       \/\/ QFileInfo \uc0ac\uc6a9\uc744 \uc704\ud574 \ud3ec\ud568 \/ Included for using QFileInfo\n\/\/ \ub4dc\ub798\uadf8 \uc774\ubbf8\uc9c0 \/ drag image\n#include &lt;QPoint&gt;          \/\/ \ub9c8\uc6b0\uc2a4 \ub4dc\ub798\uadf8 \uc2dc\uc791 \uc704\uce58 \uc800\uc7a5\uc744 \uc704\ud574 \ucd94\uac00 \/ Added to save the mouse drag start position\n\nQT_BEGIN_NAMESPACE\nnamespace Ui {\nclass MainWindow;\n}\nQT_END_NAMESPACE\n\nclass MainWindow : public QMainWindow\n{\n    Q_OBJECT\n\npublic:\n    MainWindow(QWidget *parent = nullptr);\n    ~MainWindow();\n\n    \/\/ QObject\uc758 \uc774\ubca4\ud2b8 \ud544\ud130 \ud568\uc218\ub97c \uc624\ubc84\ub77c\uc774\ub4dc\ud569\ub2c8\ub2e4. \/ Override QObject's event filter function.\n    bool eventFilter(QObject *obj, QEvent *event) override;\n\nprivate slots:\n\n    \/\/ == \ud30c\uc77c \uad00\ub828 \uc2ac\ub86f \/ File-related slots ==\n    bool saveFile(const QString &amp;path);\n    void save(); \/\/ Save\n    void saveAs(); \/\/ Save As\n    void actionNew();  \/\/ \uc0c8 \ud30c\uc77c \/ new file\n    void actionOpen(); \/\/ \ud30c\uc77c \uc5f4\uae30 \/ open\n    void actionExit(); \/\/ \uc885\ub8cc \/ Exit\n\n    \/\/ == \ud3b8\uc9d1 \/ Edit ==\n    void actionFind();     \/\/ \ucc3e\uae30 \uae30\ub2a5 \/ find\n    void actionReplace();  \/\/ \ubc14\uafb8\uae30 \uae30\ub2a5 \/ replace\n\n    \/\/ == \ubdf0 ==\n    void actionZoomIn();  \/\/ \uc90c\uc778 \/ zoom in\n    void actionZoomOut(); \/\/ \uc90c\uc544\uc6c3 \/ zoom out\n    void actionZoomReset(); \/\/ \uc90c \ucd08\uae30\ud654 \/ zoom reset\n\n    \/\/ == \uc774\ubbf8\uc9c0 \/ Image ==\n    void actionInsertImage(); \/\/ \uc774\ubbf8\uc9c0 \uc0bd\uc785 \/ insert image\n\n    \/\/ == Export ==\n    void actionExportBase64(); \/\/ Export As Base64\n    void actionExportBase64WithImages(); \/\/ Export As Base64 for image\n    void actionExportPdf(); \/\/Export As Pdf\n\n    \/\/ == Import ==\n    void actionImportBase64(); \/\/ Import As Base64\n\n    \/\/ == \ud14d\uc2a4\ud2b8 \uae30\ub2a5 \/ Text function ==\n    void actionBold(bool checked);\n    void actionItalic(bool checked);\n    void actionUnderline(bool checked);\n    void actionStrike(bool checked);\n\n    \/\/ -- \uc790\ub3d9\uc5f0\uacb0\uc124\uc815(\uc774\uc804\uc5d0 \uc0ac\uc6a9\ud558\ub358 \ubc29\uc2dd\uc73c\ub85c \uacbd\uace0 \ubc1c\uc0dd) --\n    \/\/ -- Automatic connection setup (warning occurs in the previous method) --\n    \/\/ void on_actionColor_triggered();\n    \/\/ void on_actionFont_triggered();\n\n    \/\/ -- \uc218\ub3d9\uc5f0\uacb0 --\n    void actionColor(); \/\/ \uc0c9\uc0c1 \uc120\ud0dd\uc740 \ud1a0\uae00\uc774 \uc544\ub2c8\ubbc0\ub85c bool \uc778\uc790\uac00 \uc5c6\uc74c \/ Color selection is not a toggle, so there is no bool argument.\n    void actionFont();  \/\/ \ud3f0\ud2b8 \uc120\ud0dd\uc740 \ud1a0\uae00\uc774 \uc544\ub2c8\ubbc0\ub85c bool \uc778\uc790\uac00 \uc5c6\uc74c \/ Font selection is not a toggle, so there is no bool argument.\n\n    \/\/ \ud604\uc7ac \ucee4\uc11c \uc704\uce58\uc758 \uc11c\uc2dd \ubcc0\uacbd\uc744 \uac10\uc9c0\ud558\ub294 \uc2ac\ub86f\n    \/\/ Slot to detect format changes at the current cursor position\n    void updateFormat(const QTextCharFormat &amp;format);\n\n\n    \/\/ == \ub3c4\uc6c0\ub9d0 \uae30\ub2a5 \/ help ==\n    void actionHelp();  \/\/ \ub3c4\uc6c0\ub9d0 \/ help\n    void actionAbout(); \/\/ \uc815\ubcf4 \/ about\n\n\nprivate:\n    Ui::MainWindow *ui;\n    QString currentFilePath; \/\/ \ud604\uc7ac \ud30c\uc77c\uc744 \ucd94\uc801\ud558\ub294 \ubcc0\uc218 \ucd94\uac00 \/ Add a variable to track the current file\n\n    \/\/ == \uc774\ubbf8\uc9c0 \ub9ac\uc0ac\uc774\uc988\ub97c \uc704\ud55c \uba64\ubc84 \ubcc0\uc218 \/ Member variables for image resizing ==\n    bool m_isResizing = false;\n    QPoint m_dragStartPos;\n    int m_originalImageWidth = 0;\n    int m_originalImageHeight = 0;\n\n\n    \/\/ == \uc90c\uc778\/\uc90c\uc544\uc6c3 \uc124\uc815\uc744 \uc704\ud55c \uba64\ubc84 \ubcc0\uc218 \/ Member variables for zoom in\/zoom out settings ==\n    \/\/ \ud3f0\ud2b8 \ud06c\uae30 \ucd08\uae30\ud654\uc6a9 \ubcc0\uc218 \ucd94\uac00(\ubcc0\ud654\ud558\ub294 \ud604\uc7ac\uc0c1\ud0dc \uc800\uc7a5)\n    \/\/ Add a variable to initialize the font size (save the current state as it changes)\n    int m_currentFontSize = 10;\n\n    \/\/ \uae30\ubcf8 \ud3f0\ud2b8 \ud06c\uae30\ub97c \uc800\uc7a5\ud558\ub294 \uba64\ubc84 \ubcc0\uc218(\ub9ac\uc14b\ud560\ub54c\uc758 \uac12)\n    \/\/ Member variable that stores the default font size (value when reset)\n    int m_defaultPointSize = 10; \/\/ \ucd08\uae30 \uae30\ubcf8\uac12 \uc124\uc815 \/ Set factory defaults\n\n};\n\n#endif \/\/ MAINWINDOW_H\n<\/code><\/pre>\n\n\n\n<p><strong>3.mainwindow.cpp<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"mainwindow.h\"\n#include \".\/ui_mainwindow.h\"\n\n\/\/ \ucf54\ub4dc \ucd94\uac00 \/ Add code\n#include &lt;QFileDialog&gt;\n#include &lt;QFile&gt;\n#include &lt;QTextStream&gt;\n#include &lt;QMessageBox&gt;\n#include &lt;QTextCharFormat&gt;\n#include &lt;QColorDialog&gt; \/\/ \uc0c9\uc0c1 \uc120\ud0dd \ub2e4\uc774\uc5bc\ub85c\uadf8 \/ Color selection dialog\n#include &lt;QFontDialog&gt;  \/\/ \ud3f0\ud2b8 \uc120\ud0dd \ub2e4\uc774\uc5bc\ub85c\uadf8 \/ Font selection dialog\n\n#include &lt;QDir&gt;         \/\/ QDir \uc0ac\uc6a9\uc744 \uc704\ud574 \ucd94\uac00 \/ Added for QDir use\n#include &lt;QFileInfo&gt;    \/\/ QFileInfo \uc0ac\uc6a9\uc744 \uc704\ud574 \ucd94\uac00 \/ Added for using QFileInfo\n#include &lt;QUrl&gt;         \/\/ \uc774\ubbf8\uc9c0 \ud30c\uc77c \uacbd\ub85c\ub97c URL\ub85c \ubcc0\ud658\ud558\uae30 \uc704\ud574 \ud544\uc694 \/ Needed to convert image file path to URL\n#include &lt;QImage&gt;       \/\/ \uc774\ubbf8\uc9c0 \ub85c\ub4dc\ub97c \uc704\ud574 \ud544\uc694 \/ Required for image loading\n#include &lt;QTextDocument&gt; \/\/ QTextDocument::addResource \uc0ac\uc6a9\uc744 \uc704\ud574 \ud544\uc694 \/ Required for using QTextDocument::addResource\n#include &lt;QTextImageFormat&gt; \/\/ \uc774\ubbf8\uc9c0 \uc0bd\uc785 \ud3ec\ub9f7 \uc9c0\uc815\uc744 \uc704\ud574 \ud544\uc694 \/ Required to specify image insertion format\n#include &lt;QTextCursor&gt;\n#include &lt;QInputDialog&gt; \/\/ \uc0ac\uc6a9\uc790 \uc785\ub825 \ub2e4\uc774\uc5bc\ub85c\uadf8\ub97c \uc704\ud574 \ucd94\uac00 \/ Added for user input dialog\n#include &lt;QMouseEvent&gt;  \/\/ \ub9c8\uc6b0\uc2a4 \uc774\ubca4\ud2b8 \ucc98\ub9ac\ub97c \uc704\ud574 \ucd94\uac00 \/ Added for mouse event handling\n#include &lt;QtMath&gt;       \/\/ qMax, qMin \ub4f1\uc744 \uc704\ud574 \ud544\uc694 (\uc5ec\uae30\uc11c\ub294 qMax \uc0ac\uc6a9) \/ Required for qMax, qMin, etc. (qMax is used here)\n\n\/\/ export as base64\n#include &lt;QByteArray&gt;\n#include &lt;QClipboard&gt;\n#include &lt;QApplication&gt;\n\n\/\/ export base64 with images\n#include &lt;QRegularExpression&gt;\n#include &lt;QRegularExpressionMatchIterator&gt;\n#include &lt;QBuffer&gt;\n\n\/\/ pdf\n#include &lt;QPrinter&gt;\n#include &lt;QFileDialog&gt;\n#include &lt;QMessageBox&gt;\n#include &lt;QPdfWriter&gt;\n\nMainWindow::MainWindow(QWidget *parent)\n    : QMainWindow(parent)\n    , ui(new Ui::MainWindow)\n{\n    ui-&gt;setupUi(this);\n\n    \/\/ \uba54\uc778 \uc708\ub3c4\uc6b0\uc758 \uc911\uc559 \uc601\uc5ed\uc5d0 textEdit \uc704\uc82f\uc744 \ubc30\uce58\n    \/\/ Place the textEdit widget in the center area of \u200b\u200bthe main window\n    setCentralWidget(ui-&gt;textEdit);\n\n    \/\/ == \ud30c\uc77c \uae30\ub2a5 \/ File functon ==\n    connect(ui-&gt;actionSave, &amp;QAction::triggered, this, &amp;MainWindow::save);  \/\/ save\n    connect(ui-&gt;actionSave_As, &amp;QAction::triggered, this, &amp;MainWindow::saveAs); \/\/ saveas\n    connect(ui-&gt;actionExit, &amp;QAction::triggered, this, &amp;MainWindow::actionExit); \/\/ exit\n    connect(ui-&gt;actionNew, &amp;QAction::triggered, this, &amp;MainWindow::actionNew); \/\/ new\n    connect(ui-&gt;actionOpen, &amp;QAction::triggered, this, &amp;MainWindow::actionOpen);\/\/ open\n    connect(ui-&gt;actionExport_As_Base64, &amp;QAction::triggered, this, &amp;MainWindow::actionExportBase64); \/\/save as base64\n    connect(ui-&gt;actionImport_Base64, &amp;QAction::triggered, this, &amp;MainWindow::actionImportBase64); \/\/Import base64\n    connect(ui-&gt;actionExport_Base64_With_Images, &amp;QAction::triggered, this, &amp;MainWindow::actionExportBase64WithImages); \/\/Import base64\n    connect(ui-&gt;actionExport_As_Pdf, &amp;QAction::triggered, this, &amp;MainWindow::actionExportPdf); \/\/Export As Pdf\n\n\n    \/\/ == \ud3b8\uc9d1 \uae30\ub2a5 \uad6c\ud604 \/ Implementing editing functions ==\n    connect(ui-&gt;actionCopy, &amp;QAction::triggered, ui-&gt;textEdit, &amp;QTextEdit::copy); \/\/copy\n    connect(ui-&gt;actionCut, &amp;QAction::triggered, ui-&gt;textEdit, &amp;QTextEdit::cut); \/\/ cut\n    connect(ui-&gt;actionPaste, &amp;QAction::triggered, ui-&gt;textEdit, &amp;QTextEdit::paste); \/\/ past\n    connect(ui-&gt;actionSelect_All, &amp;QAction::triggered, ui-&gt;textEdit, &amp;QTextEdit::selectAll); \/\/ select all\n    connect(ui-&gt;actionUndo, &amp;QAction::triggered, ui-&gt;textEdit, &amp;QTextEdit::undo); \/\/ undo\n    connect(ui-&gt;actionRedo, &amp;QAction::triggered, ui-&gt;textEdit, &amp;QTextEdit::redo); \/\/ redo\n\n    \/\/ == \ubdf0 \/ View ==\n    connect(ui-&gt;actionZoom_in, &amp;QAction::triggered, this, &amp;MainWindow::actionZoomIn);\n    connect(ui-&gt;actionZoom_out, &amp;QAction::triggered, this, &amp;MainWindow::actionZoomOut);\n    connect(ui-&gt;actionZoom_reset, &amp;QAction::triggered, this, &amp;MainWindow::actionZoomReset);\n\n    \/\/ \uc0ac\uc6a9\uc790 \uc815\uc758 \uc2ac\ub86f \/ custom slots\n    connect(ui-&gt;actionFind, &amp;QAction::triggered, this, &amp;MainWindow::actionFind); \/\/ find\n    connect(ui-&gt;actionReplace, &amp;QAction::triggered, this, &amp;MainWindow::actionReplace); \/\/ replace\n\n\n\n\n    \/\/ == \ud14d\uc2a4\ud2b8 \/ Text ==\n\n    \/\/ \ubcfc\ub4dc\uccb4 \/ Bold\n    \/\/ -- actionBold\ub97c \uad75\uac8c\/\uc587\uac8c \uc0c1\ud0dc\ub97c \uc720\uc9c0\ud558\ub294 '\ud1a0\uae00' \ubc84\ud2bc\uc73c\ub85c \uc124\uc815\n    \/\/ -- Set actionBold to a 'toggle' button that maintains the bold\/thin state.\n    ui-&gt;actionBold-&gt;setCheckable(true);\n\n    \/\/ -- \ud234\ubc14 \uc561\uc158 \ud074\ub9ad \uc2dc \uc11c\uc2dd\uc744 \uc801\uc6a9\ud558\ub3c4\ub85d \uc5f0\uacb0\n    \/\/ -- Connect to apply formatting when clicking a toolbar action\n    connect(ui-&gt;actionBold, &amp;QAction::triggered, this, &amp;MainWindow::actionBold);\n\n    \/\/ \uc774\ud0e4\ub9ad\uccb4 \/ Italic\n    ui-&gt;actionItalic-&gt;setCheckable(true);\n    connect(ui-&gt;actionItalic, &amp;QAction::triggered, this, &amp;MainWindow::actionItalic);\n\n    \/\/ \ubc11\uc904 \/ Underline\n    ui-&gt;actionUnderline-&gt;setCheckable(true);\n    connect(ui-&gt;actionUnderline, &amp;QAction::triggered, this, &amp;MainWindow::actionUnderline);\n\n    \/\/ \ucde8\uc18c\uc120 \/ strikethrough\n    ui-&gt;actionStrike-&gt;setCheckable(true);\n    connect(ui-&gt;actionStrike, &amp;QAction::triggered, this, &amp;MainWindow::actionStrike);\n\n    \/\/ \uae00\uaf34 \uc0c9\uc0c1 \/ font color\n    connect(ui-&gt;actionColor, &amp;QAction::triggered, this, &amp;MainWindow::actionColor);\n\n    \/\/ \uae00\uaf34 \uc120\ud0dd \/ Select font\n    connect(ui-&gt;actionFont, &amp;QAction::triggered, this, &amp;MainWindow::actionFont);\n\n    \/\/ \uc774\ubbf8\uc9c0 \uc774\ubbf8\uc9c0 \ub4dc\ub798\uadf8 \ub9ac\uc0ac\uc774\uc988 \/  Image Image Drag Resize\n    ui-&gt;textEdit-&gt;viewport()-&gt;installEventFilter(this);\n\n\n\n\n    \/\/ == \uc774\ubbf8\uc9c0 \uc0bd\uc785 \/ Insert image ==\n    connect(ui-&gt;actionInsert_image, &amp;QAction::triggered, this, &amp;MainWindow::actionInsertImage);\n\n    \/\/ -- \ud14d\uc2a4\ud2b8 \ucee4\uc11c\uc758 \uc11c\uc2dd\uc774 \ubc14\ub014 \ub54c\ub9c8\ub2e4 \ud234\ubc14 \uc0c1\ud0dc\ub97c \uc5c5\ub370\uc774\ud2b8\ud558\ub3c4\ub85d \uc5f0\uacb0\n    \/\/ -- Connect to update the toolbar state whenever the text cursor's format changes.\n    connect(ui-&gt;textEdit, &amp;QTextEdit::currentCharFormatChanged,\n            this, &amp;MainWindow::updateFormat);\n\n\n    \/\/ == \ub3c4\uc6c0\ub9d0 \uae30\ub2a5 \/ Help ==\n    \/\/ Help\n    connect(ui-&gt;actionHelp, &amp;QAction::triggered, this, &amp;MainWindow::actionHelp);\n\n    \/\/ About\n    connect(ui-&gt;actionAbout, &amp;QAction::triggered, this, &amp;MainWindow::actionAbout);\n}\n\n\n\/\/ == \uc2ac\ub86f \/ Slot ==\n\n\/\/ Export As PDF\nvoid MainWindow::actionExportPdf()\n{\n    \/\/ \uc800\uc7a5\ud560 PDF \ud30c\uc77c \uacbd\ub85c \uc120\ud0dd \/ Select the path to save the PDF file\n    QString filePath = QFileDialog::getSaveFileName(this,\n                                                    tr(\"PDF\ub85c \ub0b4\ubcf4\ub0b4\uae30\/Export pdf\"),\n                                                    QDir::homePath() + \"\/export.pdf\",\n                                                    tr(\"PDF \ud30c\uc77c\/PDF file (*.pdf)\"));\n\n    if (filePath.isEmpty())\n        return;\n\n    \/\/ QPrinter \uac1d\uccb4\ub97c PDF \ubaa8\ub4dc\ub85c \uc124\uc815\n    \/\/ Set the QPrinter object to PDF mode\n    QPrinter printer(QPrinter::HighResolution);\n    printer.setOutputFormat(QPrinter::PdfFormat);\n    printer.setOutputFileName(filePath);\n\n    \/\/ \ud398\uc774\uc9c0 \uc5ec\ubc31 \ubc0f \uc6a9\uc9c0 \uc124\uc815\n    \/\/ Page margins and paper settings\n    printer.setPageMargins(QMarginsF(15, 15, 15, 15));\n    printer.setPageSize(QPageSize(QPageSize::A4));\n\n    \/\/ QTextEdit\uc758 \ubb38\uc11c\ub97c \ud504\ub9b0\ud130\ub85c \ucd9c\ub825\n    ui-&gt;textEdit-&gt;document()-&gt;print(&amp;printer);\n\n    QMessageBox::information(this, tr(\"\uc644\ub8cc\/comolete\"), tr(\"PDF\ub85c \uc131\uacf5\uc801\uc73c\ub85c \ub0b4\ubcf4\ub0c8\uc2b5\ub2c8\ub2e4:\\n%1\").arg(filePath));\n}\n\n\/\/ Export base64 with images\nvoid MainWindow::actionExportBase64WithImages()\n{\n    QTextDocument *doc = ui-&gt;textEdit-&gt;document();\n    QString html = doc-&gt;toHtml();\n\n    \/\/ \uc774\ubbf8\uc9c0 \uacbd\ub85c\ub97c Base64 \ub370\uc774\ud130 URI\ub85c \ubcc0\ud658\n    \/\/ Convert image path to Base64 data URI\n    static const QRegularExpression imgRegex(R\"###(&lt;img&#91;^&gt;]*src=\"(&#91;^\"]+)\"&#91;^&gt;]*&gt;)###\");\n    QRegularExpressionMatchIterator it = imgRegex.globalMatch(html);\n\n    while (it.hasNext()) {\n        QRegularExpressionMatch match = it.next();\n        QString imgTag = match.captured(0);\n        QString imgPath = match.captured(1);\n\n        if (imgPath.startsWith(\"data:image\"))\n            continue;\n\n        QImage image(QUrl(imgPath).toLocalFile());\n        if (image.isNull())\n            continue;\n\n        QByteArray ba;\n        QBuffer buffer(&amp;ba);\n        buffer.open(QIODevice::WriteOnly);\n        image.save(&amp;buffer, \"PNG\");\n\n        QString base64Data = QString(\"data:image\/png;base64,%1\")\n                                 .arg(QString::fromLatin1(ba.toBase64()));\n\n        QString newTag = imgTag;\n        newTag.replace(imgPath, base64Data);\n        html.replace(imgTag, newTag);\n    }\n\n\n    \/\/ \ucd5c\uc885 HTML\uc744 Base64\ub85c \uc778\ucf54\ub529\n    \/\/ Encode the final HTML to Base64\n    QByteArray finalBase64 = html.toUtf8().toBase64();\n\n    \/\/ \ud30c\uc77c \uc800\uc7a5 \ub300\ud654 \uc0c1\uc790 \/ Save file dialog box\n    QString filePath = QFileDialog::getSaveFileName(this, tr(\"Export as Base64 HTML\"),\n                                                    QDir::homePath() + \"\/export_with_images.txt\",\n                                                    tr(\"\ud14d\uc2a4\ud2b8 \ud30c\uc77c\/text file (*.txt);;\ubaa8\ub4e0 \ud30c\uc77c (*)\"));\n    if (filePath.isEmpty())\n        return;\n\n    \/\/ \ud30c\uc77c \uc800\uc7a5 \/ Save file\n    QFile file(filePath);\n    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {\n        QTextStream out(&amp;file);\n        out &lt;&lt; finalBase64;\n        file.close();\n        QMessageBox::information(this, tr(\"\uc644\ub8cc\/Complete\"), tr(\"\uc774\ubbf8\uc9c0\ub97c \ud3ec\ud568\ud55c Base64 HTML\ub85c \ub0b4\ubcf4\ub0c8\uc2b5\ub2c8\ub2e4.\"));\n    }\n}\n\n\n\/\/ base64 Import\nvoid MainWindow::actionImportBase64()\n{\n    \/\/ \ud30c\uc77c \uc5f4\uae30 \ub300\ud654 \uc0c1\uc790 \/ Open file dialog box\n    QString filePath = QFileDialog::getOpenFileName(\n        this, tr(\"Base64 \ud30c\uc77c \uc5f4\uae30\"),\n        QDir::homePath(),\n        tr(\"\ud14d\uc2a4\ud2b8 \ud30c\uc77c (*.txt);;\ubaa8\ub4e0 \ud30c\uc77c (*)\"));\n\n    if (filePath.isEmpty())\n        return;\n\n    \/\/ \ud30c\uc77c \uc77d\uae30 \/ read file\n    QFile file(filePath);\n    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))\n        return;\n\n    QByteArray base64Data = file.readAll();\n    \/\/ Base64 \ub514\ucf54\ub529 \/ Base64 Encoding\n    QByteArray decoded = QByteArray::fromBase64(base64Data);\n    QString html = QString::fromUtf8(decoded);\n\n\n    \/\/ \ubb38\uc11c\ub97c \uc644\uc804\ud788 \uc0c8\ub85c \uc0dd\uc131\ud558\uc5ec \uae30\uc874 \uc0c1\ud0dc \ub9ac\uc14b \/ Reset the previous state by creating a completely new document\n    QTextDocument *newDoc = new QTextDocument(this);\n    ui-&gt;textEdit-&gt;setDocument(newDoc);\n\n    \/\/ HTML \ub85c\ub4dc \/ HTML Load\n    ui-&gt;textEdit-&gt;setHtml(html);\n\n    QMessageBox::information(this, tr(\"\uc644\ub8cc\/Complete\"), tr(\"Base64 \ubb38\uc11c\ub97c \ubd88\ub7ec\uc654\uc2b5\ub2c8\ub2e4.\"));\n}\n\n\n\/\/ base 64\ub85c \uc800\uc7a5\ud558\uae30 \/ Save as base 64\nvoid MainWindow::actionExportBase64()\n{\n    \/\/ QTextEdit\uc758 \ub0b4\uc6a9\uc744 HTML\ub85c \uac00\uc838\uc634 \/ Get the contents of QTextEdit as HTML\n    QString htmlContent = ui-&gt;textEdit-&gt;toHtml();\n\n    \/\/ HTML \ubb38\uc790\uc5f4\uc744 Base64\ub85c \uc778\ucf54\ub529 \/ Encode HTML string to Base64\n    QByteArray base64Data = htmlContent.toUtf8().toBase64();\n\n    \/\/ \uc0ac\uc6a9\uc790\uc5d0\uac8c \uc800\uc7a5 \ub610\ub294 \ud074\ub9bd\ubcf4\ub4dc \ubcf5\uc0ac \uc120\ud0dd\uc9c0 \uc81c\uacf5 \/ Give users the option to save or copy to clipboard\n    QStringList options = {tr(\"\ud30c\uc77c\ub85c \uc800\uc7a5\"), tr(\"\ud074\ub9bd\ubcf4\ub4dc\uc5d0 \ubcf5\uc0ac\"), tr(\"\ucde8\uc18c\")};\n    bool ok;\n    QString choice = QInputDialog::getItem(this, tr(\"Base64 \ub0b4\ubcf4\ub0b4\uae30\"),\n                                           tr(\"\uc791\uc5c5 \uc120\ud0dd:\"), options, 0, false, &amp;ok);\n    if (!ok || choice == tr(\"\ucde8\uc18c\"))\n        return;\n\n    if (choice == tr(\"\ud30c\uc77c\ub85c \uc800\uc7a5\")) {\n        QString filePath = QFileDialog::getSaveFileName(this,\n                                                        tr(\"Base64 \ud30c\uc77c\ub85c \ub0b4\ubcf4\ub0b4\uae30\"),\n                                                        QDir::homePath() + \"\/export_base64.txt\",\n                                                        tr(\"\ud14d\uc2a4\ud2b8 \ud30c\uc77c (*.txt);;\ubaa8\ub4e0 \ud30c\uc77c (*)\"));\n\n        if (!filePath.isEmpty()) {\n            QFile file(filePath);\n            if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {\n                QTextStream out(&amp;file);\n                out &lt;&lt; base64Data;\n                file.close();\n                QMessageBox::information(this, tr(\"\uc644\ub8cc\/Complete\"), tr(\"Base64 \ub370\uc774\ud130\uac00 \ud30c\uc77c\ub85c \uc800\uc7a5\ub418\uc5c8\uc2b5\ub2c8\ub2e4.\"));\n            } else {\n                QMessageBox::critical(this, tr(\"\uc624\ub958\/Error\"), tr(\"\ud30c\uc77c\uc744 \uc800\uc7a5\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4:\\n\") + file.errorString());\n            }\n        }\n    } else if (choice == tr(\"\ud074\ub9bd\ubcf4\ub4dc\uc5d0 \ubcf5\uc0ac\/Copy to clipboard\")) {\n        QClipboard *clipboard = QApplication::clipboard();\n        clipboard-&gt;setText(QString::fromUtf8(base64Data));\n        QMessageBox::information(this, tr(\"\uc644\ub8cc\/Complete\"), tr(\"Base64 \ub370\uc774\ud130\uac00 \ud074\ub9bd\ubcf4\ub4dc\uc5d0 \ubcf5\uc0ac\ub418\uc5c8\uc2b5\ub2c8\ub2e4.\"));\n    }\n}\n\n\n\/\/ HTML\uc800\uc7a5 \/ Save html\nbool MainWindow::saveFile(const QString &amp;path)\n{\n    QFile file(path);\n    \/\/ QTextEdit\uc758 \ub0b4\uc6a9\uc744 \uac00\uc838\uc635\ub2c8\ub2e4.\n    \/\/QString content = ui-&gt;textEdit-&gt;toPlainText(); \/\/ \uc77c\ubc18 \ud14d\uc2a4\ud2b8 \uc800\uc7a5 \uc608\uc2dc \/ Plain text storage example\n    \/\/ \ub9cc\uc57d \ub9ac\uce58 \ud14d\uc2a4\ud2b8(HTML)\ub85c \uc800\uc7a5\ud558\ub824\uba74:\n     QString content = ui-&gt;textEdit-&gt;toHtml();\n\n    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {\n        QTextStream out(&amp;file);\n        out &lt;&lt; content;\n        file.close();\n        currentFilePath = path; \/\/ \uc800\uc7a5 \uc131\uacf5 \uc2dc \uacbd\ub85c \uc5c5\ub370\uc774\ud2b8 \/ Update path when save is successful\n        setWindowTitle(QFileInfo(path).fileName() + \" - Editor\"); \/\/ \ucc3d \uc81c\ubaa9 \ubcc0\uacbd \/ Change window title\n        return true;\n    } else {\n        QMessageBox::critical(this, tr(\"\uc624\ub958\/Error\"), tr(\"\ud30c\uc77c\uc744 \uc800\uc7a5\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4:\\n\") + file.errorString());\n        return false;\n    }\n}\n\n\n\/\/ \ub2e4\ub978 \uc774\ub984\uc73c\ub85c \uc800\uc7a5\ud558\uae30 \/ Save As\nvoid MainWindow::saveAs()\n{\n    \/\/ QFileDialog\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc0ac\uc6a9\uc790\uc5d0\uac8c \ud30c\uc77c \uacbd\ub85c\ub97c \ubb3b\uc2b5\ub2c8\ub2e4.\n    \/\/ Use QFileDialog to ask the user for a file path.\n    QString filePath = QFileDialog::getSaveFileName(this,\n                                                    tr(\"\ubb38\uc11c \uc800\uc7a5\/Save Document\"),\n                                                    currentFilePath.isEmpty() ? QDir::homePath() : currentFilePath,\n                                                    tr(\"\ud14d\uc2a4\ud2b8 \ud30c\uc77c (*.txt);;HTML \ud30c\uc77c (*.html);;\ubaa8\ub4e0 \ud30c\uc77c (*)\"));\n\n    if (!filePath.isEmpty()) {\n        saveFile(filePath);\n    }\n}\n\n\/\/ \uc800\uc7a5\ud558\uae30 \/ Save\nvoid MainWindow::save()\n{\n    if (currentFilePath.isEmpty()) {\n        \/\/ \uacbd\ub85c\uac00 \uc5c6\uc73c\uba74 'Save As'\ub97c \ud638\ucd9c\ud569\ub2c8\ub2e4. \/ If there is no path, call 'Save As'.\n        saveAs();\n    } else {\n        \/\/ \uacbd\ub85c\uac00 \uc788\uc73c\uba74 \uae30\uc874 \ud30c\uc77c\uc5d0 \ub36e\uc5b4\uc501\ub2c8\ub2e4. \/ If the path exists, it will overwrite the existing file.\n        saveFile(currentFilePath);\n    }\n}\n\n\/\/ \uc885\ub8cc\ud558\uae30 \uc2ac\ub86f \/ Exit slot\nvoid MainWindow::actionExit()\n{\n    close(); \/\/ \uba54\uc778 \uc708\ub3c4\uc6b0\ub97c \ub2eb\uace0 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uc885\ub8cc\ud569\ub2c8\ub2e4. \/ Close the main window and exit the application.\n}\n\n\/\/ \uc0c8 \ud30c\uc77c \uc0dd\uc131 \uc2ac\ub86f \/ New file creation slot\nvoid MainWindow::actionNew()\n{\n    ui-&gt;textEdit-&gt;clear();\n    currentFilePath.clear();\n    setWindowTitle(tr(\"Untitled - Editor\"));\n}\n\n\/\/ \ud30c\uc77c \uc5f4\uae30 \uc2ac\ub86f \/ file open slot\nvoid MainWindow::actionOpen()\n{\n    QString filePath = QFileDialog::getOpenFileName(this,\n                                                    tr(\"\ubb38\uc11c \uc5f4\uae30\/Open\"),\n                                                    QDir::homePath(),\n                                                    tr(\"\ub9ac\uce58 \ud14d\uc2a4\ud2b8 \ud30c\uc77c (*.html *.htm);;\ud14d\uc2a4\ud2b8 \ud30c\uc77c (*.txt);;\uc774\ubbf8\uc9c0 \ud30c\uc77c (*.png *.jpg *.jpeg *.gif);;\ubaa8\ub4e0 \ud30c\uc77c (*)\"));\n    if (!filePath.isEmpty()) {\n        QFile file(filePath);\n        if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {\n            QString content = file.readAll();\n\n            if (filePath.endsWith(\".html\", Qt::CaseInsensitive) || filePath.endsWith(\".htm\", Qt::CaseInsensitive)) {\n                ui-&gt;textEdit-&gt;setHtml(content); \/\/ HTML \ud615\uc2dd\uc73c\ub85c \ub85c\ub4dc \/ Load in HTML format\n            }\n            \/\/ \uc774\ubbf8\uc9c0 \ud30c\uc77c\uc744 \ubc14\ub85c \uc5f4\uba74 \ud14d\uc2a4\ud2b8 \ud3b8\uc9d1\uae30\uc5d0 \uc0bd\uc785 \/ Open the image file directly and insert it into a text editor\n            else if (filePath.endsWith(\".png\", Qt::CaseInsensitive) ||\n                     filePath.endsWith(\".jpg\", Qt::CaseInsensitive) ||\n                     filePath.endsWith(\".jpeg\", Qt::CaseInsensitive) ||\n                     filePath.endsWith(\".gif\", Qt::CaseInsensitive)) {\n\n                ui-&gt;textEdit-&gt;clear();\n                QTextDocument *doc = ui-&gt;textEdit-&gt;document();\n                QUrl imageUrl = QUrl::fromLocalFile(filePath);\n                QImage image(filePath);\n\n                doc-&gt;addResource(QTextDocument::ImageResource, imageUrl, image);\n\n                QTextImageFormat imageFormat;\n                imageFormat.setWidth(image.width());\n                imageFormat.setHeight(image.height());\n                imageFormat.setName(imageUrl.toString());\n\n                QTextCursor cursor = ui-&gt;textEdit-&gt;textCursor();\n                cursor.insertImage(imageFormat);\n\n            } else {\n                ui-&gt;textEdit-&gt;setText(content); \/\/ \uc77c\ubc18 \ud14d\uc2a4\ud2b8\ub85c \ub85c\ub4dc \/ Load as plain text\n            }\n\n            file.close();\n            currentFilePath = filePath;\n            setWindowTitle(QFileInfo(filePath).fileName() + tr(\" - Editor\"));\n        } else {\n            QMessageBox::critical(this, tr(\"\uc624\ub958\/Error\"), tr(\"\ud30c\uc77c\uc744 \uc5f4 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4:\\n\") + file.errorString());\n        }\n    }\n}\n\n\n\/\/ == \ud3b8\uc9d1 \uae30\ub2a5 \uc2ac\ub86f \/ Edit function slot ==\n\n\/\/ '\ucc3e\uae30' \uae30\ub2a5 \/ 'Find' function\nvoid MainWindow::actionFind()\n{\n    bool ok;\n    \/\/ \uc0ac\uc6a9\uc790\uc5d0\uac8c \ucc3e\uc744 \ud14d\uc2a4\ud2b8\ub97c \uc785\ub825\ubc1b\uc2b5\ub2c8\ub2e4. \/ Ask the user to enter the text they want to find.\n    QString text = QInputDialog::getText(this, tr(\"\ud14d\uc2a4\ud2b8 \ucc3e\uae30\"),\n                                         tr(\"\ucc3e\uc744 \ub2e8\uc5b4\ub97c \uc785\ub825\ud558\uc138\uc694:\"), QLineEdit::Normal,\n                                         \"\", &amp;ok);\n    if (ok &amp;&amp; !text.isEmpty()) {\n        QTextDocument::FindFlags flags = QTextDocument::FindFlags();\n\n        \/\/ QTextEdit::find()\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub2e4\uc74c \uc77c\uce58 \ud56d\ubaa9\uc744 \ucc3e\uace0 \uc120\ud0dd\ud569\ub2c8\ub2e4.\n        bool found = ui-&gt;textEdit-&gt;find(text, flags);\n\n        if (!found) {\n            QMessageBox::information(this, tr(\"\ucc3e\uae30 \uacb0\uacfc\"), tr(\"'%1'\uc744(\ub97c) \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\").arg(text));\n        }\n    }\n}\n\n\/\/ '\ubc14\uafb8\uae30' \uae30\ub2a5 \/ replace function\nvoid MainWindow::actionReplace()\n{\n    \/\/  \ucc3e\uc744 \ud14d\uc2a4\ud2b8 \uc785\ub825 \/ Enter text to find\n    bool ok;\n    QString findText = QInputDialog::getText(this, tr(\"\ud14d\uc2a4\ud2b8 \ubc14\uafb8\uae30\"),\n                                             tr(\"\ucc3e\uc744 \ub2e8\uc5b4\ub97c \uc785\ub825\ud558\uc138\uc694:\"), QLineEdit::Normal,\n                                             \"\", &amp;ok);\n    if (!ok || findText.isEmpty()) return;\n\n    \/\/ \ubc14\uafc0 \ud14d\uc2a4\ud2b8 \uc785\ub825 \/ Enter text to find\n    QString replaceText = QInputDialog::getText(this, tr(\"\ud14d\uc2a4\ud2b8 \ubc14\uafb8\uae30\"),\n                                                tr(\"\ubc14\uafc0 \ub2e8\uc5b4\ub97c \uc785\ub825\ud558\uc138\uc694:\"), QLineEdit::Normal,\n                                                \"\", &amp;ok);\n    if (!ok) return;\n\n    QTextCursor cursor = ui-&gt;textEdit-&gt;textCursor();\n    QTextDocument::FindFlags flags = QTextDocument::FindFlags();\n    int count = 0;\n\n    \/\/ \ud14d\uc2a4\ud2b8\ub97c \ubb38\uc11c \uc2dc\uc791\ubd80\ud130 \ub2e4\uc2dc \ucc3e\uae30 \uc2dc\uc791\ud558\ub3c4\ub85d \ucee4\uc11c\ub97c \ubb38\uc11c \uc2dc\uc791\uc73c\ub85c \uc774\ub3d9\n    \/\/ Move the cursor to the beginning of the document to start searching text again from the beginning of the document\n    cursor.movePosition(QTextCursor::Start);\n    ui-&gt;textEdit-&gt;setTextCursor(cursor);\n\n    \/\/ \ubb38\uc11c \ub05d\uae4c\uc9c0 \ubc18\ubcf5\ud558\uba70 \ucc3e\uae30 \ubc0f \ubc14\uafb8\uae30\n    \/\/ Find and replace until the end of the document\n    while (ui-&gt;textEdit-&gt;find(findText, flags)) {\n        \/\/ find()\uac00 \uc131\uacf5\ud558\uba74 \ud14d\uc2a4\ud2b8\ub294 \uc774\ubbf8 \uc120\ud0dd\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.\n        \/\/ If find() succeeds, the text is already selected.\n        QTextCursor currentSelection = ui-&gt;textEdit-&gt;textCursor();\n\n        \/\/ \uc120\ud0dd\ub41c \ud14d\uc2a4\ud2b8\ub97c replaceText\ub85c \ub300\uccb4\n        \/\/ Replace the selected text with replaceText\n        currentSelection.insertText(replaceText);\n        count++;\n\n        \/\/ \ub2e4\uc74c \uac80\uc0c9\uc744 \uc704\ud574 \ucee4\uc11c\ub97c \uc0bd\uc785\ub41c \ud14d\uc2a4\ud2b8 \ub4a4\ub85c \uc774\ub3d9 (find\uac00 \uc790\ub3d9\uc73c\ub85c \ucc98\ub9ac\ud568)\n        \/\/ Move the cursor after the inserted text for the next search (find handles this automatically)\n    }\n\n    QMessageBox::information(this, tr(\"\ubc14\uafb8\uae30 \uc644\ub8cc\"), tr(\"\ucd1d %1\uac1c\uc758 \ud56d\ubaa9\uc744 \ubcc0\uacbd\ud588\uc2b5\ub2c8\ub2e4.\").arg(count));\n}\n\n\/\/ ==  \ubdf0 \uae30\ub2a5 \uc2ac\ub86f \/ View function slot ==\n\n\/\/----------------------------------------------------------------\n\/\/ -- \ub0b4\uc7a5\ud568\uc218 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uba74 \uc800\uc7a5\uc774\ub098 \ub0b4\ubcf4\ub0b4\uae30 \ud55c \ud30c\uc77c\uc744 \uc801\uc6a9\ub418\uc9c0 \uc54a\uc74c--\n\/\/ -- Using built-in functions does not apply to files saved or exported--\n\/\/----------------------------------------------------------------\n\/\/ \uc90c\uc778(\ub0b4\uc7a5\ud568\uc218) \/ Zoom in (built-in function)\n\/\/ void MainWindow::actionZoomIn()\n\/\/ {\n\/\/     \/\/ ui-&gt;textEdit\uc740 QMainWindow\uc5d0 \ud3ec\ud568\ub41c QTextEdit \uc704\uc82f\uc758 objectName\uc774\ub77c\uace0 \uac00\uc815\ud569\ub2c8\ub2e4.\n\/\/     if (ui-&gt;textEdit) {\n\/\/         qDebug() &lt;&lt; \"Zoom In triggered\";\n\/\/         \/\/ \uae30\ubcf8 \uc90c \ub2e8\uacc4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ud655\ub300 \/ Zoom in using the default zoom level\n\/\/         ui-&gt;textEdit-&gt;zoomIn(1);\n\/\/     }\n\/\/ }\n\n\/\/ \uc90c\uc544\uc6c3(\ub0b4\uc7a5\ud568\uc218) \/ Zoom out (built-in function)\n\/\/ void MainWindow::actionZoomOut()\n\/\/ {\n\/\/     if (ui-&gt;textEdit) {\n\/\/         qDebug() &lt;&lt; \"Zoom Out triggered\";\n\/\/         \/\/ \uae30\ubcf8 \uc90c \ub2e8\uacc4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ucd95\uc18c \/ Zoom out using the default zoom level\n\/\/         ui-&gt;textEdit-&gt;zoomOut(1);\n\/\/     }\n\/\/ }\n\/\/-----------------------------------------------------------------------\n\n\n\/\/ \uc90c\uc778 \ucee4\uc2a4\ud140 \/ Zoom in custom\nvoid MainWindow::actionZoomIn()\n{\n    \/\/ ui-&gt;textEdit\uc774 \uc720\ud6a8\ud55c\uc9c0 \ud655\uc778\ud569\ub2c8\ub2e4. \/ Check if ui-&gt;textEdit is valid.\n    if (!ui-&gt;textEdit) {\n        return;\n    }\n\n    \/\/ \ud604\uc7ac \ubb38\uc11c\uc758 \uae30\ubcf8 \ud3f0\ud2b8(\ub610\ub294 \ucee4\uc11c \uc704\uce58\uc758 \ud3f0\ud2b8) \uc815\ubcf4\ub97c \uac00\uc838\uc635\ub2c8\ub2e4.\n    \/\/ Get information about the default font of the current document (or the font at the cursor position).\n\n    \/\/ \ubb38\uc11c \uc804\uccb4\uc758 \uae30\ubcf8 \ud3f0\ud2b8 \ud06c\uae30\ub97c \uc0ac\uc6a9\ud560\uc9c0, \ud604\uc7ac \ucee4\uc11c\uc758 \ud3f0\ud2b8 \ud06c\uae30\ub97c \uc0ac\uc6a9\ud560\uc9c0 \uacb0\uc815\ud569\ub2c8\ub2e4.\n    \/\/ Determines whether to use the default font size for the entire document or the font size of the current cursor.\n\n    \/\/ \uc90c \uae30\ub2a5\uc740 \ubcf4\ud1b5 \ubb38\uc11c \uc804\uccb4\uc758 \uae30\ubcf8 \ud3f0\ud2b8 \ud06c\uae30\ub97c \ubcc0\uacbd\ud569\ub2c8\ub2e4.\n    \/\/ The zoom feature usually changes the default font size for the entire document.\n    QFont font = ui-&gt;textEdit-&gt;document()-&gt;defaultFont();\n    int currentSize = font.pointSize();\n\n    \/\/ \ud3f0\ud2b8 \ud06c\uae30\uac00 \ud3ec\uc778\ud2b8 \ub2e8\uc704\ub85c \uc124\uc815\ub418\uc9c0 \uc54a\uc558\uc744 \uacbd\uc6b0 (\uc608: \ud53d\uc140) \ub610\ub294 0\uc77c \uacbd\uc6b0,\n    \/\/ \uc801\uc808\ud55c \uae30\ubcf8\uac12(\uc608: 12)\uc744 \uc0ac\uc6a9\ud569\ub2c8\ub2e4.\n    \/\/ If the font size is not set in points (e.g., pixels) or is 0,\n    \/\/ use an appropriate default value (e.g., 12).\n    if (currentSize &lt;= 0) {\n        currentSize = 12;\n    }\n\n    \/\/ \uc90c \ub2e8\uacc4 \uc124\uc815 \ubc0f \ucd5c\ub300 \ud06c\uae30 \uc81c\ud55c (Max Zoom)\n    \/\/ Set zoom level and limit maximum size (Max Zoom)\n    const int ZOOM_STEP = 2; \/\/ \ud655\ub300 \ub2e8\uc704\ub97c 2pt\ub85c \uc124\uc815 \/ Set the zoom unit to 2pt\n    const int MAX_FONT_SIZE = 48; \/\/ \ucd5c\ub300 \ud3f0\ud2b8 \ud06c\uae30\ub97c 48pt\ub85c \uc81c\ud55c \/ Limit maximum font size to 48pt\n\n    if (currentSize &lt; MAX_FONT_SIZE) {\n        int newSize = qMin(currentSize + ZOOM_STEP, MAX_FONT_SIZE);\n\n        \/\/ \uc0c8 \ud3f0\ud2b8 \ud06c\uae30 \uc801\uc6a9 \/ Apply new font size\n        font.setPointSize(newSize);\n        ui-&gt;textEdit-&gt;document()-&gt;setDefaultFont(font);\n\n        \/\/ \ud14d\uc2a4\ud2b8 \uc804\uccb4\uc5d0 \uc0c8 \ud3f0\ud2b8 \ud06c\uae30 \uc801\uc6a9 (\uae30\uc874 HTML \ub85c\ub4dc \uc2dc \uc778\ub77c\uc778 \uc2a4\ud0c0\uc77c\uc774 \uc801\uc6a9\ub418\uc5b4 \uc788\ub2e4\uba74 \ud544\uc694)\n        \/\/ Apply new font size to all text (needed if inline styles were applied when loading existing HTML)\n        QTextCursor cursor(ui-&gt;textEdit-&gt;document());\n        cursor.select(QTextCursor::Document);\n        QTextCharFormat fmt;\n        fmt.setFontPointSize(newSize);\n\n        \/\/ \ud3ec\ub9f7\uc744 \ubcd1\ud569\ud558\uc5ec \ud3f0\ud2b8 \ud06c\uae30\ub9cc \ubcc0\uacbd\ud558\uace0 \ub2e4\ub978 \uc2a4\ud0c0\uc77c\uc740 \uc720\uc9c0\ud569\ub2c8\ub2e4.\n        \/\/ Merge formats to change only the font size and keep other styles.\n        cursor.mergeCharFormat(fmt);\n        cursor.clearSelection();\n\n        qDebug() &lt;&lt; \"Zoom In to size:\" &lt;&lt; newSize;\n\n        \/\/ (\uc635\uc158) \uc90c \uc0c1\ud0dc \ud45c\uc2dc \uc5c5\ub370\uc774\ud2b8\n        \/\/ (Optional) Update the zoom status display\n        \/\/ updateZoomStatus(newSize);\n    } else {\n        qDebug() &lt;&lt; \"Maximum zoom level reached.\";\n    }\n}\n\n\n\n\/\/ \uc90c\uc544\uc6c3 \ucee4\uc2a4\ud140 \/ Zoom out coustom\nvoid MainWindow::actionZoomOut()\n{\n    \/\/ ui-&gt;textEdit\uc774 \uc720\ud6a8\ud55c\uc9c0 \ud655\uc778\ud569\ub2c8\ub2e4.\n    \/\/ Check if ui-&gt;textEdit is valid.\n    if (!ui-&gt;textEdit) {\n        return;\n    }\n\n    \/\/ \ud604\uc7ac \ubb38\uc11c\uc758 \uae30\ubcf8 \ud3f0\ud2b8 \uc815\ubcf4\ub97c \uac00\uc838\uc635\ub2c8\ub2e4.\n    \/\/ Get the default font information for the current document.\n    QFont font = ui-&gt;textEdit-&gt;document()-&gt;defaultFont();\n    int currentSize = font.pointSize();\n\n    \/\/ \ud3f0\ud2b8 \ud06c\uae30\uac00 \ud3ec\uc778\ud2b8 \ub2e8\uc704\ub85c \uc124\uc815\ub418\uc9c0 \uc54a\uc558\uac70\ub098 0\uc77c \uacbd\uc6b0, \uc801\uc808\ud55c \uae30\ubcf8\uac12(\uc608: 12)\uc744 \uc0ac\uc6a9\ud569\ub2c8\ub2e4.\n    \/\/ If the font size is not set in points or is 0, a reasonable default (e.g. 12) is used.\n    if (currentSize &lt;= 0) {\n        currentSize = 12;\n    }\n\n    \/\/ \uc90c \ub2e8\uacc4 \uc124\uc815 \ubc0f \ucd5c\uc18c \ud06c\uae30 \uc81c\ud55c (Min Zoom)\n    \/\/ Set zoom level and minimum size limit (Min Zoom)\n    const int ZOOM_STEP = 2; \/\/ \ucd95\uc18c \ub2e8\uc704\ub97c 2pt\ub85c \uc124\uc815 (\uc90c \uc778\uacfc \ub3d9\uc77c\ud558\uac8c \uc720\uc9c0) \/ Set the zoom unit to 2pt (keep it the same as zoom in)\n    const int MIN_FONT_SIZE = 8; \/\/ \ucd5c\uc18c \ud3f0\ud2b8 \ud06c\uae30\ub97c 8pt\ub85c \uc81c\ud55c \/ Limit minimum font size to 8pt\n\n    if (currentSize &gt; MIN_FONT_SIZE) {\n\n        \/\/ \ud604\uc7ac \ud06c\uae30\uc5d0\uc11c \uc90c \ub2e8\uacc4\ub9cc\ud07c \ube7c\uace0, \ucd5c\uc18c \ud06c\uae30(MIN_FONT_SIZE)\ubcf4\ub2e4 \uc791\uc544\uc9c0\uc9c0 \uc54a\ub3c4\ub85d \uc81c\ud55c\ud569\ub2c8\ub2e4.\n        \/\/ Subtract the zoom level from the current size, and limit it to no smaller than the minimum size (MIN_FONT_SIZE).\n        int newSize = qMax(currentSize - ZOOM_STEP, MIN_FONT_SIZE);\n\n        \/\/ \uc0c8 \ud3f0\ud2b8 \ud06c\uae30 \uc801\uc6a9 \/ Apply new font size\n        font.setPointSize(newSize);\n        ui-&gt;textEdit-&gt;document()-&gt;setDefaultFont(font);\n\n        \/\/ \ud14d\uc2a4\ud2b8 \uc804\uccb4\uc5d0 \uc0c8 \ud3f0\ud2b8 \ud06c\uae30 \uc801\uc6a9 (\uc90c \uc544\uc6c3\uc774 \ubdf0\ud3ec\ud2b8\ubfd0\ub9cc \uc544\ub2c8\ub77c \uc2e4\uc81c \ud3f0\ud2b8 \ud06c\uae30\uc5d0 \ubc18\uc601\ub418\ub3c4\ub85d)\n        \/\/ Apply the new font size to the entire text (so that zooming out reflects the actual font size, not just the viewport)\n        QTextCursor cursor(ui-&gt;textEdit-&gt;document());\n        cursor.select(QTextCursor::Document);\n        QTextCharFormat fmt;\n        fmt.setFontPointSize(newSize);\n\n        \/\/ \ud3ec\ub9f7\uc744 \ubcd1\ud569\ud558\uc5ec \ud3f0\ud2b8 \ud06c\uae30\ub9cc \ubcc0\uacbd\ud558\uace0 \ub2e4\ub978 \uc2a4\ud0c0\uc77c\uc740 \uc720\uc9c0\ud569\ub2c8\ub2e4. \/ Merge formats to change only the font size and keep other styles.\n        cursor.mergeCharFormat(fmt);\n        cursor.clearSelection();\n\n        qDebug() &lt;&lt; \"Zoom Out to size:\" &lt;&lt; newSize;\n\n        \/\/ \uc90c \uc0c1\ud0dc \ud45c\uc2dc \uc5c5\ub370\uc774\ud2b8 \/ Updated zoom status display\n        \/\/ updateZoomStatus(newSize);\n    } else {\n        qDebug() &lt;&lt; \"Minimum zoom level reached.\";\n    }\n}\n\n\/\/ \uc90c \ucd08\uae30\ud654 \/ Reset zoom\nvoid MainWindow::actionZoomReset()\n{\n    \/\/ ui-&gt;textEdit\uc774 \uc720\ud6a8\ud55c\uc9c0 \ud655\uc778\ud569\ub2c8\ub2e4.\n    \/\/ Check if ui-&gt;textEdit is valid.\n    if (!ui-&gt;textEdit) {\n        return;\n    }\n\n    \/\/ \uae30\ubcf8 \ud3f0\ud2b8 \ud06c\uae30\ub97c \uac00\uc838\uc635\ub2c8\ub2e4. \/ Get the default font size.\n    const int newSize = m_defaultPointSize;\n\n    \/\/ \ubb38\uc11c\uc758 \uae30\ubcf8 \ud3f0\ud2b8\ub97c \uc124\uc815\ud569\ub2c8\ub2e4. \/ Sets the default font for the document.\n    QFont font = ui-&gt;textEdit-&gt;document()-&gt;defaultFont();\n    font.setPointSize(newSize);\n    ui-&gt;textEdit-&gt;document()-&gt;setDefaultFont(font);\n\n    \/\/ \ud14d\uc2a4\ud2b8 \uc804\uccb4\uc5d0 \uc11c\uc2dd \uc77c\uad04 \uc801\uc6a9 (\uc778\ub77c\uc778 \uc2a4\ud0c0\uc77c\uc744 \ub36e\uc5b4\uc4f0\uae30 \uc704\ud568)\n    \/\/ Apply formatting to all text (to overwrite inline styles)\n    QTextCursor cursor(ui-&gt;textEdit-&gt;document());\n    cursor.select(QTextCursor::Document);\n    QTextCharFormat fmt;\n    fmt.setFontPointSize(newSize);\n\n    \/\/ \ud3ec\ub9f7\uc744 \ubcd1\ud569\ud558\uc5ec \ud3f0\ud2b8 \ud06c\uae30\ub9cc \uae30\ubcf8\uac12\uc73c\ub85c \ubcc0\uacbd\ud569\ub2c8\ub2e4.\n    \/\/ Merge formats to only change the font size to default.\n    cursor.mergeCharFormat(fmt);\n    cursor.clearSelection();\n\n    qDebug() &lt;&lt; \"Zoom Reset to default size:\" &lt;&lt; newSize;\n\n    \/\/ \uc90c \uc0c1\ud0dc \ud45c\uc2dc \uc5c5\ub370\uc774\ud2b8 \/ Updated zoom status display\n    \/\/ updateZoomStatus(newSize);\n}\n\n\n\/\/ ==  \ud14d\uc2a4\ud2b8 \uae30\ub2a5 \uad6c\ud604 \uc2ac\ub86f \/ Text function implementation slot ==\n\n\/\/ \uad75\uac8c \ubc84\ud2bc\uc774 \ud074\ub9ad\ub420 \ub54c \ud638\ucd9c\ub418\ub294 \uc2ac\ub86f \/ A slot called when the bold button is clicked\n\/\/ \ubcfc\ub4dc\uccb4 \uc801\uc6a9 \uc2ac\ub86f \uad6c\ud604 \/ Implementing a bold font slot\nvoid MainWindow::actionBold(bool checked)\n{\n    \/\/ \uc0c8\ub85c\uc6b4 \ubb38\uc790 \uc11c\uc2dd \uac1d\uccb4\ub97c \uc0dd\uc131 \/ Create a new character format object\n    QTextCharFormat format;\n\n    \/\/ QAction\uc758 \uccb4\ud06c \uc0c1\ud0dc(\ub20c\ub9bc \uc0c1\ud0dc)\uc5d0 \ub530\ub77c \uad75\uac8c\/\ubcf4\ud1b5\uc744 \uc124\uc815\n    \/\/ Set bold\/normal depending on the checked state (pressed state) of QAction\n\n    \/\/ QAction::triggered(bool checked) \uc2dc\uadf8\ub110\uc758 'checked' \uac12\uc744 \uc0ac\uc6a9\ud569\ub2c8\ub2e4.\n    \/\/ Use the 'checked' value of the QAction::triggered(bool checked) signal.\n    format.setFontWeight(checked ? QFont::Bold : QFont::Normal);\n\n    \/\/ \uc11c\uc2dd\uc744 \ud14d\uc2a4\ud2b8 \ud3b8\uc9d1\uae30\uc5d0 \ubcd1\ud569 (\uc120\ud0dd \uc601\uc5ed \ub610\ub294 \ucee4\uc11c \uc704\uce58\uc758 \ub2e8\uc5b4\uc5d0 \uc801\uc6a9)\n    \/\/ Merge formatting into text editor (applies to selection or word at cursor position)\n\n    \/\/ \uc774 \ucf54\ub4dc\ub294 QTextEdit::mergeCurrentCharFormat()\uc744 \uc0ac\uc6a9\ud569\ub2c8\ub2e4.\n    \/\/ This code uses QTextEdit::mergeCurrentCharFormat().\n    ui-&gt;textEdit-&gt;mergeCurrentCharFormat(format);\n\n    \/\/ QAction\uc758 \uc0c1\ud0dc\ub294 \uc5f0\uacb0\ub41c QToolButton\uc5d0 \uc758\ud574 \uc790\ub3d9\uc73c\ub85c \ud1a0\uae00\ub429\ub2c8\ub2e4.\n    \/\/ The state of a QAction is automatically toggled by the connected QToolButton.\n}\n\n\n\n\/\/ \uc774\ud0e4\ub9ad \ubc84\ud2bc\uc774 \ud074\ub9ad\ub420 \ub54c \ud638\ucd9c\ub418\ub294 \uc2ac\ub86f \/ A slot called when the italic button is clicked.\nvoid MainWindow::actionItalic(bool checked)\n{\n    QTextCharFormat format;\n\n    \/\/ checked \uc0c1\ud0dc\uc5d0 \ub530\ub77c \uc774\ud0e4\ub9ad \uc18d\uc131 \uc124\uc815 \/ Set italic property based on checked state\n    format.setFontItalic(checked);\n    ui-&gt;textEdit-&gt;mergeCurrentCharFormat(format);\n}\n\n\/\/ \ubc11\uc904 \ubc84\ud2bc\uc774 \ud074\ub9ad\ub420 \ub54c \ud638\ucd9c\ub418\ub294 \uc2ac\ub86f\n\/\/ Slot called when the underline button is clicked\nvoid MainWindow::actionUnderline(bool checked)\n{\n    QTextCharFormat format;\n\n    \/\/ checked \uc0c1\ud0dc\uc5d0 \ub530\ub77c \ubc11\uc904 \uc18d\uc131 \uc124\uc815\n    \/\/ Set the underline property according to the checked state\n    format.setFontUnderline(checked);\n    ui-&gt;textEdit-&gt;mergeCurrentCharFormat(format);\n}\n\n\/\/ \ucde8\uc18c\uc120 \ubc84\ud2bc\uc774 \ud074\ub9ad\ub420 \ub54c \ud638\ucd9c\ub418\ub294 \uc2ac\ub86f\n\/\/ Slot called when the cancel button is clicked\nvoid MainWindow::actionStrike(bool checked)\n{\n    QTextCharFormat format;\n\n    \/\/ checked \uc0c1\ud0dc\uc5d0 \ub530\ub77c \ucde8\uc18c\uc120 \uc18d\uc131 \uc124\uc815\n    \/\/ Set strikethrough property based on checked status\n    format.setFontStrikeOut(checked);\n    ui-&gt;textEdit-&gt;mergeCurrentCharFormat(format);\n}\n\n\/\/ \uae00\uaf34 \uc0c9\uc0c1 \ubc84\ud2bc\uc774 \ud074\ub9ad\ub420 \ub54c \ud638\ucd9c\ub418\ub294 \uc2ac\ub86f (\uc218\ub3d9\uc5f0\uacb0 \uc0ac\uc6a9\uc2dc)\n\/\/ Slot called when the font color button is clicked (when using manual linking)\nvoid MainWindow::actionColor()\n{\n    \/\/ \ud604\uc7ac \ud14d\uc2a4\ud2b8 \uc0c9\uc0c1\uc744 \uae30\ubcf8\uac12\uc73c\ub85c \uc0ac\uc6a9 \/ Use current text color as default\n    QColor initialColor = ui-&gt;textEdit-&gt;currentCharFormat().foreground().color();\n    QColor color = QColorDialog::getColor(initialColor, this, tr(\"\uae00\uaf34 \uc0c9\uc0c1 \uc120\ud0dd\"));\n\n    if (color.isValid()) {\n        QTextCharFormat format;\n        \/\/ \uc120\ud0dd\ub41c \uc0c9\uc0c1\uc744 \uc804\uacbd\uc0c9(\uae00\uaf34 \uc0c9\uc0c1)\uc73c\ub85c \uc124\uc815 \/ Set the selected color as the foreground color (font color)\n        format.setForeground(QBrush(color));\n        ui-&gt;textEdit-&gt;mergeCurrentCharFormat(format);\n    }\n}\n\n\/\/ \uae00\uaf34 \uc120\ud0dd \ubc84\ud2bc\uc774 \ud074\ub9ad\ub420 \ub54c \ud638\ucd9c\ub418\ub294 \uc2ac\ub86f (\uc218\ub3d9\uc5f0\uacb0 \uc0ac\uc6a9\uc2dc)\n\/\/ Slot called when the font selection button is clicked (when using manual linking)\nvoid MainWindow::actionFont()\n{\n    \/\/ \ud604\uc7ac \ud3f0\ud2b8\ub97c \uae30\ubcf8\uac12\uc73c\ub85c \uc0ac\uc6a9 \/ Use the current font as default\n    QFont initialFont = ui-&gt;textEdit-&gt;currentCharFormat().font();\n    bool ok;\n    QFont font = QFontDialog::getFont(&amp;ok, initialFont, this, tr(\"\uae00\uaf34 \uc120\ud0dd\"));\n\n    if (ok) {\n        QTextCharFormat format;\n        \/\/ \uc120\ud0dd\ub41c \ud3f0\ud2b8\ub97c \uc801\uc6a9 \/ Apply selected font\n        format.setFont(font);\n        ui-&gt;textEdit-&gt;mergeCurrentCharFormat(format);\n    }\n}\n\n\/\/ == \uc790\ub3d9\uc5f0\uacb0\uc740 \uacbd\uace0 \ubc1c\uc0dd\ud568 ==\n\/\/ void MainWindow::on_actionColor_triggered()\n\/\/ {\n\/\/     \/\/ \ud604\uc7ac \ud14d\uc2a4\ud2b8 \uc0c9\uc0c1\uc744 \uae30\ubcf8\uac12\uc73c\ub85c \uc0ac\uc6a9\n\/\/     QColor initialColor = ui-&gt;textEdit-&gt;currentCharFormat().foreground().color();\n\/\/     QColor color = QColorDialog::getColor(initialColor, this, tr(\"\uae00\uaf34 \uc0c9\uc0c1 \uc120\ud0dd\"));\n\n\/\/     if (color.isValid()) {\n\/\/         QTextCharFormat format;\n\/\/         \/\/ \uc120\ud0dd\ub41c \uc0c9\uc0c1\uc744 \uc804\uacbd\uc0c9(\uae00\uaf34 \uc0c9\uc0c1)\uc73c\ub85c \uc124\uc815\n\/\/         format.setForeground(QBrush(color));\n\/\/         ui-&gt;textEdit-&gt;mergeCurrentCharFormat(format);\n\/\/     }\n\/\/ }\n\n\/\/ void MainWindow::on_actionFont_triggered()\n\/\/ {\n\/\/     \/\/ \ud604\uc7ac \ud3f0\ud2b8\ub97c \uae30\ubcf8\uac12\uc73c\ub85c \uc0ac\uc6a9\n\/\/     QFont initialFont = ui-&gt;textEdit-&gt;currentCharFormat().font();\n\/\/     bool ok;\n\/\/     QFont font = QFontDialog::getFont(&amp;ok, initialFont, this, tr(\"\uae00\uaf34 \uc120\ud0dd\"));\n\n\/\/     if (ok) {\n\/\/         QTextCharFormat format;\n\/\/         \/\/ \uc120\ud0dd\ub41c \ud3f0\ud2b8\ub97c \uc801\uc6a9\n\/\/         format.setFont(font);\n\/\/         ui-&gt;textEdit-&gt;mergeCurrentCharFormat(format);\n\/\/     }\n\/\/ }\n\n\n\/\/ == \uc774\ubbf8\uc9c0 \uc0bd\uc785 \uc2ac\ub86f \/ Image insertion slot  ==\nvoid MainWindow::actionInsertImage()\n{\n    QString imagePath = QFileDialog::getOpenFileName(this,\n                                                     tr(\"\uc774\ubbf8\uc9c0 \uc0bd\uc785\"),\n                                                     QDir::homePath(),\n                                                     tr(\"\uc774\ubbf8\uc9c0 \ud30c\uc77c (*.png *.jpg *.jpeg *.gif *.bmp)\"));\n\n    if (!imagePath.isEmpty()) {\n        QImage image(imagePath);\n\n        if (image.isNull()) {\n            QMessageBox::critical(this, tr(\"\uc624\ub958\"), tr(\"\uc774\ubbf8\uc9c0 \ud30c\uc77c\uc744 \ub85c\ub4dc\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\"));\n            return;\n        }\n\n        QTextDocument *doc = ui-&gt;textEdit-&gt;document();\n        QUrl imageUrl = QUrl::fromLocalFile(imagePath);\n\n        doc-&gt;addResource(QTextDocument::ImageResource, imageUrl, image);\n\n        QTextImageFormat imageFormat;\n        \/\/ \uae30\ubcf8 \uc0bd\uc785 \ud06c\uae30\ub97c \uc6d0\ubcf8 \ud06c\uae30\ub85c \uc124\uc815 \/ Set default insert size to original size\n        imageFormat.setWidth(image.width());\n        imageFormat.setHeight(image.height());\n        imageFormat.setName(imageUrl.toString());\n\n        QTextCursor cursor = ui-&gt;textEdit-&gt;textCursor();\n        cursor.insertImage(imageFormat);\n    }\n}\n\n\/\/ == \uc774\ubca4\ud2b8 \ud544\ud130 \uad6c\ud604 (\uc774\ubbf8\uc9c0 \ub4dc\ub798\uadf8 \ub9ac\uc0ac\uc774\uc988) \/ Implementing an event filter (image drag resize) ==\nbool MainWindow::eventFilter(QObject *obj, QEvent *event)\n{\n    if (obj == ui-&gt;textEdit-&gt;viewport()) {\n        QMouseEvent *mouseEvent = static_cast&lt;QMouseEvent*&gt;(event);\n        QTextCursor cursor = ui-&gt;textEdit-&gt;textCursor();\n        QTextCharFormat format = cursor.charFormat();\n\n        \/\/ \ub9c8\uc6b0\uc2a4 \ub204\ub984 \uc774\ubca4\ud2b8 (Resize \uc2dc\uc791 \uac10\uc9c0) \/ Mouse press event (detect resize start)\n        if (event-&gt;type() == QEvent::MouseButtonPress &amp;&amp; mouseEvent-&gt;button() == Qt::LeftButton) {\n            if (format.isImageFormat()) {\n                \/\/ \uc774\ubbf8\uc9c0\uac00 \uc120\ud0dd\ub41c \uc704\uce58\uc5d0\uc11c \ud074\ub9ad\uc774 \ubc1c\uc0dd\ud55c \uacbd\uc6b0 \/ If a click occurs at the location where the image is selected\n                m_isResizing = true;\n                m_dragStartPos = mouseEvent-&gt;pos();\n\n                \/\/ \ud604\uc7ac \uc774\ubbf8\uc9c0 \ud3ec\ub9f7\uc5d0\uc11c \uae30\uc874 \ud06c\uae30\ub97c \uac00\uc838\uc635\ub2c8\ub2e4. \/ Get the original size from the current image format.\n                QTextImageFormat imageFormat = format.toImageFormat();\n                m_originalImageWidth = imageFormat.width();\n                m_originalImageHeight = imageFormat.height();\n\n                \/\/ \ub9ac\uc0ac\uc774\uc988 \uc911\uc5d0\ub294 \ub9c8\uc6b0\uc2a4 \uc774\ubca4\ud2b8\ub97c QTextEdit\uc73c\ub85c \uc804\ub2ec\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.\n                \/\/ Mouse events are not passed to QTextEdit during resizing.\n                return true;\n            }\n        }\n\n        \/\/ \ub9c8\uc6b0\uc2a4 \uc774\ub3d9 \uc774\ubca4\ud2b8 (Resize \uc9c4\ud589) \/ Mouse move event (Resize in progress)\n        else if (event-&gt;type() == QEvent::MouseMove) {\n            if (m_isResizing &amp;&amp; mouseEvent-&gt;buttons() &amp; Qt::LeftButton) {\n\n                \/\/ X\ucd95 \uc774\ub3d9 \uac70\ub9ac\ub97c \uae30\ubc18\uc73c\ub85c \ud06c\uae30\ub97c \uc870\uc808\ud569\ub2c8\ub2e4. \/ Scales based on the distance moved along the X-axis.\n                int deltaX = mouseEvent-&gt;pos().x() - m_dragStartPos.x();\n\n                \/\/ \uc0c8\ub85c\uc6b4 \ub108\ube44 \uacc4\uc0b0 (\ucd5c\uc18c 50\ud53d\uc140 \uc81c\ud55c) \/ New width calculation (minimum 50 pixels limit)\n                int newWidth = qMax(50, m_originalImageWidth + deltaX);\n\n                \/\/ \uc885\ud6a1\ube44 \uc720\uc9c0\ud558\uc5ec \uc0c8\ub85c\uc6b4 \ub192\uc774 \uacc4\uc0b0 \/ Calculate new height while maintaining aspect ratio\n                \/\/ \uc18c\uc218\uc810 \uc5f0\uc0b0\uc744 \uc704\ud574 double\ub85c \uce90\uc2a4\ud305 \/ Cast to double for decimal operations\n                int newHeight = (int)((double)m_originalImageHeight * ((double)newWidth \/ m_originalImageWidth));\n\n                \/\/ \ud604\uc7ac \ucee4\uc11c \uc704\uce58\uc5d0 \uc788\ub294 \uc774\ubbf8\uc9c0 \ud3ec\ub9f7\uc744 \uc5c5\ub370\uc774\ud2b8\ud569\ub2c8\ub2e4.\n                \/\/ Updates the image format at the current cursor position.\n                QTextCursor currentCursor = ui-&gt;textEdit-&gt;textCursor();\n                if (currentCursor.charFormat().isImageFormat()) {\n                    QTextImageFormat newImageFormat = currentCursor.charFormat().toImageFormat();\n\n                    newImageFormat.setWidth(newWidth);\n                    newImageFormat.setHeight(newHeight);\n\n                    \/\/ \uc11c\uc2dd \uc801\uc6a9 \/ Apply Formatting\n                    ui-&gt;textEdit-&gt;mergeCurrentCharFormat(newImageFormat);\n                }\n\n                return true; \/\/ \uc774\ubca4\ud2b8\ub97c \uc18c\ube44\ud558\uc5ec \ud14d\uc2a4\ud2b8 \uc120\ud0dd \ub4f1 \uae30\ubcf8 \ub3d9\uc791 \ubc29\uc9c0 \/ Consuming events to prevent default actions such as text selection\n            }\n        }\n\n        \/\/ \ub9c8\uc6b0\uc2a4 \ub193\uae30 \uc774\ubca4\ud2b8 (Resize \uc885\ub8cc) \/ Mouse release event (Resize ends)\n        else if (event-&gt;type() == QEvent::MouseButtonRelease) {\n            if (m_isResizing &amp;&amp; mouseEvent-&gt;button() == Qt::LeftButton) {\n                m_isResizing = false;\n                \/\/ \ub9ac\uc0ac\uc774\uc988 \uc885\ub8cc \/ End of resize\n                return true;\n            }\n        }\n    }\n\n    \/\/ \ud544\ud130\ub9c1\ud558\uc9c0 \uc54a\uc740 \ubaa8\ub4e0 \uc774\ubca4\ud2b8\ub97c \ub300\uc0c1 \uac1d\uccb4\ub85c \uc804\ub2ec\ud569\ub2c8\ub2e4.\n    \/\/ Forward all unfiltered events to the target object.\n    return QMainWindow::eventFilter(obj, event);\n}\n\n\n\/\/ \ucee4\uc11c \uc704\uce58\uc758 \ubb38\uc790 \uc11c\uc2dd\uc774 \ubc14\ub014 \ub54c \ud638\ucd9c\ub418\ub294 \uc2ac\ub86f\n\/\/ Slot called when the character format at the cursor position changes\n\n\/\/ \ud234\ubc14 \uc0c1\ud0dc \uc5c5\ub370\uc774\ud2b8 \uc2ac\ub86f \uad6c\ud604 \/ Implementing a Toolbar State Update Slot\nvoid MainWindow::updateFormat(const QTextCharFormat &amp;format)\n{\n    \/\/ \ud604\uc7ac \uc11c\uc2dd\uc5d0\uc11c \ud3f0\ud2b8\uc758 \uad75\uae30\ub97c \ud655\uc778 \/ Check the font weight in the current format\n    bool isBold = format.font().bold();\n\n    \/\/ -- actionBold\uc758 \uccb4\ud06c \uc0c1\ud0dc\ub97c \ud3f0\ud2b8\uc758 \uad75\uae30 \uc0c1\ud0dc\uc5d0 \ub9de\uac8c \uc5c5\ub370\uc774\ud2b8 \/ Update the check state of actionBold to match the bold state of the font.\n    \/\/ -- \uc774\ub807\uac8c \ud574\uc57c \uc0ac\uc6a9\uc790\uac00 \uad75\uc740 \uae00\uc528\ub85c \ucee4\uc11c\ub97c \uc62e\uae30\uba74 \ubc84\ud2bc\uc774 \ub20c\ub9b0 \uc0c1\ud0dc\ub85c \ubcf4\uc785\ub2c8\ub2e4. \/ This way, when the user moves the cursor over the bold text, the button appears pressed.\n    ui-&gt;actionBold-&gt;setChecked(isBold);\n\n    \/\/ \ub2e4\ub978 \uc11c\uc2dd(Italic, Underline)\uc5d0 \ub300\ud574\uc11c\ub3c4 \uc774 \ud568\uc218 \ub0b4\uc5d0\uc11c \ub3d9\uc77c\ud558\uac8c \ucc98\ub9ac\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\n    \/\/ You can handle other formats (Italic, Underline) in the same way within this function.\n    \/\/ ui-&gt;actionItalic-&gt;setChecked(format.font().italic());\n\n\n    \/\/ \uc774\ud0e4\ub9ad\uccb4 \uc0c1\ud0dc \uc5c5\ub370\uc774\ud2b8 \/ Italic status updates\n    bool isItalic = format.font().italic();\n    ui-&gt;actionItalic-&gt;setChecked(isItalic);\n\n    \/\/ \ubc11\uc904 \uc0c1\ud0dc \uc5c5\ub370\uc774\ud2b8 \/ Underline status update\n    bool isUnderline = format.font().underline();\n    ui-&gt;actionUnderline-&gt;setChecked(isUnderline);\n\n    \/\/ \ucde8\uc18c\uc120 \uc0c1\ud0dc \uc5c5\ub370\uc774\ud2b8 \/ Strikethrough status update\n    bool isStrike = format.font().strikeOut();\n    ui-&gt;actionStrike-&gt;setChecked(isStrike);\n}\n\n\/\/ == \ub3c4\uc6c0\ub9d0 &amp; Help \uae30\ub2a5 \/ Help &amp; Help function ==\nvoid MainWindow::actionHelp()\n{\n    QMessageBox::information(this,\n                             tr(\"\ub3c4\uc6c0\ub9d0\/Help\"),\n                             tr(\"&lt;h3&gt;\uac04\ub2e8\ud55c \ud14d\uc2a4\ud2b8 \ud3b8\uc9d1\uae30 \uc0ac\uc6a9\ubc95\/How to use a simple text editor&lt;\/h3&gt;\"\n                                \"&lt;p&gt;&lt;strong&gt;\ud30c\uc77c \uba54\ub274:&lt;\/strong&gt; \uc0c8 \ud30c\uc77c, \uc5f4\uae30, \uc800\uc7a5, PDF\/Base64 \ub0b4\ubcf4\ub0b4\uae30\ub97c \uc9c0\uc6d0\ud569\ub2c8\ub2e4.&lt;\/p&gt;\"\n                                \"&lt;p&gt;&lt;strong&gt;File Menu:&lt;\/strong&gt; Supports New File, Open, Save, and PDF\/Base64 Export.&lt;\/p&gt;\"\n                                \"&lt;p&gt;&lt;strong&gt;\ud3b8\uc9d1 \uba54\ub274:&lt;\/strong&gt; \ucc3e\uae30 \ubc0f \ubc14\uafb8\uae30 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.&lt;\/p&gt;\"\n                                \"&lt;p&gt;&lt;strong&gt;Edit menu:&lt;\/strong&gt; You can use the Find and Replace feature.&lt;\/p&gt;\"\n                                \"&lt;p&gt;&lt;strong&gt;\ubdf0 \uba54\ub274:&lt;\/strong&gt; \ud14d\uc2a4\ud2b8 \uc90c\uc778\/\uc90c\uc544\uc6c3\/\ucd08\uae30\ud654\ub97c \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.&lt;\/p&gt;\"\n                                \"&lt;p&gt;&lt;strong&gt;View Menu:&lt;\/strong&gt; You can zoom in\/out\/reset the text.&lt;\/p&gt;\"\n                                \"&lt;p&gt;&lt;strong&gt;\uc11c\uc2dd \uc9c0\uc815:&lt;\/strong&gt; \ud14d\uc2a4\ud2b8\ub97c \uad75\uac8c, \uae30\uc6b8\uc784\uaf34, \ubc11\uc904, \ucde8\uc18c\uc120\uc73c\ub85c \uc124\uc815\ud558\uace0, \uc0c9\uc0c1 \ubc0f \ud3f0\ud2b8\ub97c \ubcc0\uacbd\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.&lt;\/p&gt;\"\n                                \"&lt;p&gt;&lt;strong&gt;Formatting:&lt;\/strong&gt; You can make text bold, italic, underline, strikethrough, and change the color and font.&lt;\/p&gt;\"\n                                \"&lt;p&gt;&lt;strong&gt;\uc774\ubbf8\uc9c0:&lt;\/strong&gt; \ub85c\uceec \uc774\ubbf8\uc9c0\ub97c \uc0bd\uc785\ud558\uace0 \ub9c8\uc6b0\uc2a4\ub85c \ud06c\uae30\ub97c \uc870\uc808\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.&lt;\/p&gt;\"\n                                \"&lt;p&gt;&lt;strong&gt;Image:&lt;\/strong&gt; Insert a local image and resize it with your mouse.&lt;\/p&gt;\"\n                                ),\n                             QMessageBox::Ok);\n}\n\n\/\/ about slot\nvoid MainWindow::actionAbout()\n{\n    QMessageBox::about(this,\n                       tr(\"Rich Text Editor \uc815\ubcf4\/Rich Text Editor information\"),\n                       tr(\"&lt;h2&gt;Rich Text Editor v1.0 (Qt)&lt;\/h2&gt;\"\n                          \"&lt;p&gt;Qt \ud504\ub808\uc784\uc6cc\ud06c\ub97c \uae30\ubc18\uc73c\ub85c \uac1c\ubc1c\ub41c \uac04\ub2e8\ud55c \ud14d\uc2a4\ud2b8 \ud3b8\uc9d1\uae30\uc785\ub2c8\ub2e4.&lt;\/p&gt;\"\n                          \"&lt;p&gt;A Rich text editor developed based on the Qt framework.&lt;\/p&gt;\"\n                          \"&lt;p&gt;\uc8fc\uc694 \uae30\ub2a5: \ud30c\uc77c \uc785\ucd9c\ub825, \ud14d\uc2a4\ud2b8 \uc11c\uc2dd \uc9c0\uc815, \uc774\ubbf8\uc9c0 \uc0bd\uc785 \ubc0f \ud06c\uae30 \uc870\uc808.&lt;\/p&gt;\"\n                          \"&lt;p&gt;Key features: file input\/output, text formatting, image insertion and resizing.&lt;\/p&gt;\"\n                          \"&lt;p&gt;Copyright &amp;copy; 2025&lt;\/p&gt;\"\n\n                          ));\n}\n\n\n\/\/ \uba54\ubaa8\ub9ac\ud574\uc81c \/ \"&lt;p&gt;Key features: file input\/output, text formatting, image insertion and resizing.&lt;\/p&gt;\"\nMainWindow::~MainWindow()\n{\n    delete ui;\n}\n\n\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\ud83d\udc49\uc544\ub798\ub294 QT6\ubc84\uc804 \ud504\ub85c\uadf8\ub7a8 \uc18c\uc2a4 \ucf54\ub4dc \uc785\ub2c8\ub2e4.Below is the QT6 version program source code. \ud83d\udc49\uc57d\uac04\uc758 \uae30\ub2a5\uc774 \ub354 \ucd94\uac00 \ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.There are a few more features added. 1.main.cpp 2.mainwindow.h 3.mainwindow.cpp<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17,1],"tags":[],"class_list":["post-2691","post","type-post","status-publish","format-standard","hentry","category-qt","category-uncategorized","missing-thumbnail"],"_links":{"self":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/2691","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=2691"}],"version-history":[{"count":7,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/2691\/revisions"}],"predecessor-version":[{"id":2703,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/2691\/revisions\/2703"}],"wp:attachment":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=2691"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=2691"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=2691"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}