1. 关于对话框

(1)标准的桌面应用软件都有一个关于对话框

(2)关于对话框用于标识软件自身的信息。如logo、项目名、版本号、开发者信息、版权信息、联系方式等。

2. 经典设计方案

3. 项目持续开发

(1)自定义文本编辑框中的字体大小及实现思路

  ①通过QFontDialog选择字体以及大小

  ②将QFont对象设置到文本编辑框

(2)设置文本编辑框是否自动换行及实现思路

  ①获取当前文本编辑框的换行模式

  ②将模式进行反转后并进行设置

  ③更新对应QAction对象的状态

(3)打开外部帮助文件及实现思路

  ①QDesktopServices提供了一系列桌面开发相关的服务接口

  ②通过QDesktopServices中的成员函数打开帮助文件:QDesktopServices::openUrl(QUrl("path"));

【编程实验】关于对话框的创建及项目持续开发

//main.cpp、FontDialog.h(cpp)、ReplaceDialog.h(cpp)与上例相同

//AboutDialog.h

#ifndef _ABOUTDIALOG_H_
#define _ABOUTDIALOG_H_

#include <QDialog>
#include <QLabel>
#include <QPlainTextEdit>
#include <QPushButton>

class AboutDialog : public QDialog
{
    Q_OBJECT

    QLabel m_logoLbl;
    QLabel m_qqLbl;
    QPlainTextEdit m_infoEdit;
    QPushButton m_closeBtn;

public:
    );
};

#endif // _ABOUTDIALOG_H_

//AboutDialog.cpp

#include "AboutDialog.h"
#include <QPalette>
#include <QPixmap>

AboutDialog::AboutDialog(QWidget* parent):
    QDialog(parent, Qt::WindowCloseButtonHint),
    m_logoLbl(this),m_qqLbl(this),m_infoEdit(this),m_closeBtn(this)
{
    QPixmap pm(":/Res/pic/dt.png");

    pm = pm.scaled(,,Qt::KeepAspectRatio);
    m_logoLbl.setPixmap(pm);
    m_logoLbl.move(, );
    m_logoLbl.resize(, );

    //使m_infoEdit的背景透明的方法:
    //1.使用调色板
//    QPalette p = m_infoEdit.palette();
//    p.setColor(QPalette::Active, QPalette::Base, palette().color(QPalette::Active,
//               QPalette::Background));
//    p.setColor(QPalette::Inactive, QPalette::Base, palette().color(QPalette::Inactive,
//               QPalette::Background));
//    m_infoEdit.setPalette(p);

    //2.方法2
    //m_infoEdit.setStyleSheet("background-color: rgb(255, 255, 255, 0);");
    //3.方法3
    m_infoEdit.setStyleSheet("background-color:transparent;");

    m_infoEdit.move(,);
    m_infoEdit.resize(, );
    m_infoEdit.setFrameStyle(QFrame::NoFrame);
    m_infoEdit.setReadOnly(true);
    m_infoEdit.insertPlainText("Note Pad Project\n\nPlatform:Qt 5.6.0\n\nVersion:1.0.0\n\nCopyright:D.T.Software");

    m_qqLbl.move(, );
    m_qqLbl.setText("QQ Group: 199546072");

    m_closeBtn.setText("Close");
    m_closeBtn.move(, );
    m_closeBtn.resize(, );

    setFixedSize(, );
    setWindowTitle("About NotePad");

    connect(&m_closeBtn, SIGNAL(clicked()), this, SLOT(close()));
}

//MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMenuBar>
//#include <QKeySequence>
//#include <QAction>
#include <QPlainTextEdit>
#include <QLabel>
#include <QFileDialog>
#include <QSharedPointer>
#include "FindDialog.h"
#include "ReplaceDialog.h"

class MainWindow : public QMainWindow
{
    Q_OBJECT
private:

    QPlainTextEdit mainEditor;
    QLabel statusLbl;
    QString m_filePath;//当前操作的文件路径
    bool m_isTextChanged; //标识编辑框中的内容是否改变
    QSharedPointer<FindDialog> m_pFindDlg;//组合关系,利用智能指针来管理其生命周期
    QSharedPointer<ReplaceDialog> m_pRelaceDlg;

    //将构造函数、复制构造、赋值函数等私有化
    MainWindow(QWidget *parent = );
    MainWindow(const MainWindow&);
    MainWindow& operator= (const MainWindow&);

    bool construct(); //二阶构造模式

    bool initMenuBar();   //初始化菜单栏
    bool initToolBar();   //初始化工具栏
    bool initStatusBar(); //初始化状态栏
    bool initMainEditor();//初始化文本编辑组件

    //菜单设置
    bool initFileMenu(QMenuBar* mb);    //“文件”菜单
    bool initEditMenu(QMenuBar* mb);    //“编辑”菜单
    bool initFormatMenu(QMenuBar* mb);  //“格式”菜单
    bool initViewMenu(QMenuBar* mb);    //“查看”菜单
    bool initHelpMenu(QMenuBar* mb);    //“帮助”菜单

    //工具栏设置
    bool initFileToolItem(QToolBar* tb);
    bool initEditToolItem(QToolBar* tb);
    bool initFormatToolItem(QToolBar* tb);
    bool initViewToolItem(QToolBar* tb);

    //生成菜单项
    bool makeAction(QAction*& action, QWidget* parent, QString text, int key);
    //生成工具栏中的各按钮
    bool makeAction(QAction*& action, QWidget* parent, QString tip, QString icon);

    QString showFileDialog(QFileDialog::AcceptMode mode, QString title);//显示打开和保存对话框
    void showErrorMessage(QString message);//显示“错误对话框”(QMessagBox)
    int showQueryMessage(QString message); //显示“询问对话框”
    QString saveCurrentData(QString path = "", QString title = "Save"); //保存编辑框中的内容
    void preEditorChanged(); //判断文本框是否被更改,并决定是否弹出“保存对话框”
    void openFileToEditor(QString path);
    QAction* findMenuBarAction(QString text);
    QAction* findToolBarAction(QString text);

protected:
    void closeEvent(QCloseEvent *e); //重写窗体的关闭事件
    void dragEnterEvent(QDragEnterEvent* e);
    void dropEvent(QDropEvent * e);

private slots:
    void onFileNew();
    void onFileOpen();
    void onFileSave();
    void onFileSaveAs();
    void onFilePrint();
    void onFileExit();
    void onTextChanged();//文本框内容发生改变里,会收到textChanged信号,这里是接收该信号的槽函数

    void onCopyAvailable(bool available);
    void onRedoAvailable(bool available);
    void onUndoAvailable(bool available);
    void onCursorPositionChanged();
    void onEditDelete();
    void onEditFind();
    void onEditReplace();
    void onEditGoto();
    void onFormatFont();
    void onFormatWrap();
    void onViewToolBar();
    void onViewStatusBar();
    void onHelpAbout();
    void onHelpManual();

public:
    static MainWindow* NewInstance();

    ~MainWindow();
};

#endif // MAINWINDOW_H

//MainWindowUI.cpp

#include "MainWindow.h"
#include <QMenu>
#include <QToolBar>
#include <QStatusBar>
#include <QLabel>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
      m_pFindDlg(new FindDialog(this,&mainEditor)),
      m_pRelaceDlg(new ReplaceDialog(this, &mainEditor))
{
    setWindowTitle("NotePad - [ New ]");
    mainEditor.setAcceptDrops(false);//默认下,QPlainTextEdit是接收拖放事件的
                                     //其父对象会收不到“拖放”事件,这里设为false
    setAcceptDrops(true); //由MainWindow来接管拖放事件

    m_filePath = "";

    m_isTextChanged = false;
}

//二阶构造中的第2阶构造
bool MainWindow::construct()
{
    bool ret = true;

    ret = ret && initMenuBar();
    ret = ret && initToolBar();
    ret = ret && initStatusBar();
    ret = ret && initMainEditor();

    return ret;
}

MainWindow* MainWindow::NewInstance()
{
    MainWindow* ret = new MainWindow();

    if((ret == NULL) || !ret->construct())
    {
        delete ret;
        ret = NULL;
    }

    return ret;
}

//初始化菜单栏
bool MainWindow::initMenuBar()
{
    bool ret = true;
    QMenuBar* mb = menuBar(); //menuBar为QMainWindow的成员变量

    ret = ret && initFileMenu(mb);
    ret = ret && initEditMenu(mb);
    ret = ret && initFormatMenu(mb);
    ret = ret && initViewMenu(mb);
    ret = ret && initHelpMenu(mb);

    return ret;
}

//初始化工具栏
bool MainWindow::initToolBar()
{
    bool ret = true;

    QToolBar* tb = addToolBar("Tool Bar");

    tb->setIconSize(QSize(, ));

    ret = ret && initFileToolItem(tb);
    tb->addSeparator();

    ret = ret && initEditToolItem(tb);
    tb->addSeparator();

    ret = ret && initFormatToolItem(tb);
    tb->addSeparator();

    ret = ret && initViewToolItem(tb);

    return ret;
}

//初始化状态栏
bool MainWindow::initStatusBar()
{
    bool ret = true;
    QStatusBar* sb = statusBar();
    QLabel* label = new QLabel("D.T.Software");

    if( label != NULL )
    {
        statusLbl.setMinimumWidth();
        statusLbl.setAlignment(Qt::AlignCenter);
        statusLbl.setText("Ln: 1    Col: 1");

        label->setMinimumWidth();
        label->setAlignment(Qt::AlignCenter);

        sb->addPermanentWidget(new QLabel()); //添加分隔线
        sb->addPermanentWidget(&statusLbl);
        sb->addPermanentWidget(label);
    }
    else
    {
        ret = false;
    }
    return ret;
}

//初始化主文本编辑组件
bool MainWindow::initMainEditor()
{
    bool ret = true;
    QPalette p = mainEditor.palette();

    p.setColor(QPalette::Inactive, QPalette::Highlight,
               p.color(QPalette::Active, QPalette::Highlight));
    p.setColor(QPalette::Inactive, QPalette::HighlightedText,
               p.color(QPalette::Active, QPalette::HighlightedText));

    mainEditor.setPalette(p);
    mainEditor.setParent(this);

    connect(&mainEditor, SIGNAL(textChanged()), this, SLOT(onTextChanged()));
    connect(&mainEditor, SIGNAL(copyAvailable(bool)),this,SLOT(onCopyAvailable(bool)));
    connect(&mainEditor, SIGNAL(redoAvailable(bool)),this,SLOT(onRedoAvailable(bool)));
    connect(&mainEditor, SIGNAL(undoAvailable(bool)),this,SLOT(onUndoAvailable(bool)));
    connect(&mainEditor, SIGNAL(cursorPositionChanged()), this, SLOT(onCursorPositionChanged()));
    setCentralWidget(&mainEditor);

    return ret;
}

//文件(下拉)菜单
bool MainWindow::initFileMenu(QMenuBar* mb)
{
    QMenu* menu = new QMenu("File(&F)", mb);//指定parent为mb
    bool ret = (menu != NULL);

    if ( ret )
    {
        QAction* action = NULL;
        //"新建"菜单项
        ret = ret &&  makeAction(action, mb, "New(&N)", Qt::CTRL + Qt::Key_N);
        if(ret)
        {
            connect(action, SIGNAL(triggered()), this, SLOT(onFileNew()));
            menu->addAction(action); //add Action to Menu Item
        }

        //"打开"菜单项
        ret = ret &&  makeAction(action, mb, "Open(&O)...", Qt::CTRL + Qt::Key_O);
        if(ret)
        {
            connect(action, SIGNAL(triggered()), this, SLOT(onFileOpen()));
            menu->addAction(action); //add Action to Menu Item
        }

        //"保存"菜单项
        ret = ret &&  makeAction(action, mb, "Save(&S)", Qt::CTRL + Qt::Key_S);
        if(ret)
        {
            connect(action, SIGNAL(triggered()), this, SLOT(onFileSave()));
            menu->addAction(action); //add Action to Menu Item
        }

        //"另存为"菜单项
        ret = ret &&  makeAction(action, mb, );
        if(ret)
        {
            connect(action, SIGNAL(triggered()), this, SLOT(onFileSaveAs()));
            menu->addAction(action); //add Action to Menu Item
        }

        //水平分隔线
        menu->addSeparator();

        //"打印"菜单项
        ret = ret &&  makeAction(action, mb, "Print(&P)...", Qt::CTRL + Qt::Key_P);
        if(ret)
        {
            connect(action, SIGNAL(triggered()),this, SLOT(onFilePrint()));
            menu->addAction(action); //add Action to Menu Item
        }

        menu->addSeparator();

        //"退出"菜单项
        ret = ret && makeAction(action, mb, "Exit(&X)", Qt::CTRL + Qt::Key_Q);
        if(ret)
        {
            connect(action, SIGNAL(triggered()), this, SLOT(onFileExit()));
            menu->addAction(action); //add Action Item to Menu
        }
    }

    if ( ret )
    {
        mb->addMenu(menu); //add Menu to Menu Bar
    }
    else
    {
        delete menu;
    }

    return ret;
}

//“编辑”菜单
bool MainWindow::initEditMenu(QMenuBar* mb)
{
    QMenu* menu = new QMenu("Edit(&E)", mb);
    bool ret = (menu != NULL);

    if( ret )
    {
        QAction* action = NULL;

        ret = ret && makeAction(action, mb, "Undo(&U)", Qt::CTRL + Qt::Key_Z);
        if ( ret )
        {
            connect(action, SIGNAL(triggered()), &mainEditor, SLOT(undo()));
            action->setEnabled(false);
            menu->addAction(action);
        }

        ret = ret && makeAction(action, mb, "Redo(&R)...", Qt::CTRL + Qt::Key_Y);
        if ( ret )
        {
            connect(action, SIGNAL(triggered()), &mainEditor, SLOT(redo()));
            action->setEnabled(false);
            menu->addAction(action);
        }

        menu->addSeparator();

        ret = ret && makeAction(action, mb, "Cut(&T)", Qt::CTRL + Qt::Key_X);
        if ( ret )
        {
            connect(action, SIGNAL(triggered()), &mainEditor, SLOT(cut()));
            action->setEnabled(false);
            menu->addAction(action);
        }

        ret = ret && makeAction(action, mb, "Copy(&C)", Qt::CTRL + Qt::Key_C);
        if ( ret )
        {
            connect(action, SIGNAL(triggered()), &mainEditor, SLOT(copy()));
            action->setEnabled(false);
            menu->addAction(action);
        }

        ret = ret && makeAction(action, mb, "Paste(&P)", Qt::CTRL + Qt::Key_V);
        if ( ret )
        {
            connect(action, SIGNAL(triggered()), &mainEditor, SLOT(paste()));
            menu->addAction(action);
        }

        ret = ret && makeAction(action, mb, "Delete(&L)", Qt::Key_Delete);
        if ( ret )
        {
            connect(action, SIGNAL(triggered()), this, SLOT(onEditDelete()));
            menu->addAction(action);
        }

        menu->addSeparator();

        ret = ret && makeAction(action, mb,  "Find(&F)...", Qt::CTRL + Qt::Key_F);
        if ( ret )
        {
            connect(action, SIGNAL(triggered()), this, SLOT(onEditFind()));
            menu->addAction(action);
        }

        ret = ret && makeAction(action, mb, "Replace(&R)...", Qt::CTRL + Qt::Key_H);
        if ( ret )
        {
            connect(action, SIGNAL(triggered()), this, SLOT(onEditReplace()));
            menu->addAction(action);
        }

        ret = ret && makeAction(action, mb, "Goto(&G)...", Qt::CTRL + Qt::Key_G);
        if ( ret )
        {
            connect(action, SIGNAL(triggered()), this, SLOT(onEditGoto()));
            menu->addAction(action);
        }

        menu->addSeparator();

        ret = ret && makeAction(action, mb, "Select All(&A)...", Qt::CTRL + Qt::Key_A);
        if ( ret )
        {
            connect(action, SIGNAL(triggered()), &mainEditor, SLOT(selectAll()));
            menu->addAction(action);
        }
    }

    if ( ret )
    {
        mb->addMenu(menu);
    }
    else
    {
        delete menu;
    }

    return ret;
}

//“格式”菜单
bool MainWindow::initFormatMenu(QMenuBar* mb)
{
    QMenu* menu = new QMenu("Format(&O)", mb);
    bool ret = ( menu != NULL);

    if (ret)
    {
        QAction* action = NULL;

        ret = ret && makeAction(action, mb, );
        if ( ret )
        {
            action->setCheckable(true);
            action->setChecked(true);
            connect(action, SIGNAL(triggered()), this, SLOT(onFormatWrap()));
            menu ->addAction(action);
        }

        ret = ret && makeAction(action, mb, );
        if ( ret )
        {
            connect(action, SIGNAL(triggered()), this, SLOT(onFormatFont()));
            menu ->addAction(action);
        }
    }

    if ( ret )
    {
        mb->addMenu(menu);
    }
    else
    {
        delete menu;
    }

    return ret;
}

//“查看”菜单
bool MainWindow::initViewMenu(QMenuBar* mb)
{
    QMenu* menu = new QMenu("View(&V)", mb);
    bool ret = ( menu != NULL);

    if (ret)
    {
        QAction* action = NULL;

        ret = ret && makeAction(action, mb, );
        if ( ret )
        {
            action->setCheckable(true);
            action->setChecked(true);
            connect(action, SIGNAL(triggered()), this, SLOT(onViewToolBar()));
            menu ->addAction(action);
        }

        ret = ret && makeAction(action, mb, );
        if ( ret )
        {
            action->setCheckable(true);
            action->setChecked(true);
            connect(action, SIGNAL(triggered()), this, SLOT(onViewStatusBar()));
            menu ->addAction(action);
        }
    }

    if ( ret )
    {
        mb->addMenu(menu);
    }
    else
    {
        delete menu;
    }

    return ret;
}

//“帮助”菜单
bool MainWindow::initHelpMenu(QMenuBar* mb)
{
    QMenu* menu = new QMenu("Help(&H)", mb);
    bool ret = ( menu != NULL);

    if (ret)
    {
        QAction* action = NULL;

        ret = ret && makeAction(action, mb, );
        if ( ret )
        {
            connect(action, SIGNAL(triggered()), this, SLOT(onHelpManual()));
            menu ->addAction(action);
        }

        ret = ret && makeAction(action, mb, );
        if ( ret )
        {
            connect(action, SIGNAL(triggered()), this, SLOT(onHelpAbout()));
            menu ->addAction(action);
        }
    }

    if ( ret )
    {
        mb->addMenu(menu);
    }
    else
    {
        delete menu;
    }

    return ret;
}

//工具栏设置
bool MainWindow::initFileToolItem(QToolBar* tb)
{
    bool ret = true;
    QAction* action = NULL;

    ret = ret && makeAction(action, tb, "New", ":/Res/pic/new.png");
    if ( ret )
    {
        connect(action, SIGNAL(triggered()), this, SLOT(onFileNew()));
        tb->addAction(action);
    }

    ret = ret && makeAction(action, tb, "Open", ":/Res/pic/open.png");
    if ( ret )
    {
        connect(action, SIGNAL(triggered()), this, SLOT(onFileOpen()));
        tb->addAction(action);
    }

    ret = ret && makeAction(action, tb, "Save", ":/Res/pic/save.png");
    if ( ret )
    {
        connect(action, SIGNAL(triggered()), this, SLOT(onFileSave()));
        tb->addAction(action);
    }

    ret = ret && makeAction(action, tb, "Save As", ":/Res/pic/saveas.png");
    if ( ret )
    {
        connect(action, SIGNAL(triggered()), this, SLOT(onFileSaveAs()));
        tb->addAction(action);
    }

    ret = ret && makeAction(action, tb, "Print", ":/Res/pic/print.png");
    if ( ret )
    {
        connect(action, SIGNAL(triggered()),this, SLOT(onFilePrint()));
        tb->addAction(action);
    }

    return ret;
}

bool MainWindow::initEditToolItem(QToolBar* tb)
{
    bool ret = true;
    QAction* action = NULL;

    ret = ret && makeAction(action, tb, "Undo", ":/Res/pic/undo.png");
    if ( ret )
    {
        connect(action, SIGNAL(triggered()), &mainEditor, SLOT(undo()));
        action->setEnabled(false);
        tb->addAction(action);
    }

    ret = ret && makeAction(action, tb, "Redo", ":/Res/pic/redo.png");
    if ( ret )
    {
        connect(action, SIGNAL(triggered()), &mainEditor, SLOT(redo()));
        action->setEnabled(false);
        tb->addAction(action);
    }

    ret = ret && makeAction(action, tb, "Cut", ":/Res/pic/cut.png");
    if ( ret )
    {
        connect(action, SIGNAL(triggered()), &mainEditor, SLOT(cut()));
        action->setEnabled(false);
        tb->addAction(action);
    }

    ret = ret && makeAction(action, tb, "Copy", ":/Res/pic/copy.png");
    if ( ret )
    {
        connect(action, SIGNAL(triggered()), &mainEditor, SLOT(copy()));
        action->setEnabled(false);
        tb->addAction(action);
    }

    ret = ret && makeAction(action, tb, "Paste", ":/Res/pic/paste.png");
    if ( ret )
    {
        connect(action, SIGNAL(triggered()), &mainEditor, SLOT(paste()));
        tb->addAction(action);
    }

    ret = ret && makeAction(action, tb, "Find", ":/Res/pic/find.png");
    if ( ret )
    {
        connect(action, SIGNAL(triggered()), this, SLOT(onEditFind()));
        tb->addAction(action);
    }

    ret = ret && makeAction(action, tb, "Replace", ":/Res/pic/replace.png");
    if ( ret )
    {
        connect(action, SIGNAL(triggered()), this, SLOT(onEditReplace()));
        tb->addAction(action);
    }

    ret = ret && makeAction(action, tb, "Goto", ":/Res/pic/goto.png");
    if ( ret )
    {
        tb->addAction(action);
    }

    return ret;
}

bool MainWindow::initFormatToolItem(QToolBar* tb)
{
    bool ret = true;
    QAction* action = NULL;

    ret = ret && makeAction(action, tb, "Auto Wrap", ":/Res/pic/wrap.png");
    if ( ret )
    {
        action->setCheckable(true);
        action->setChecked(true);
        connect(action, SIGNAL(triggered()), this, SLOT(onFormatWrap()));
        tb->addAction(action);
    }

    ret = ret && makeAction(action, tb, "Font", ":/Res/pic/font.png");
    if ( ret )
    {
        connect(action, SIGNAL(triggered()), this, SLOT(onFormatFont()));
        tb->addAction(action);
    }

    return ret;
}

bool MainWindow::initViewToolItem(QToolBar* tb)
{
    bool ret = true;
    QAction* action = NULL;

    ret = ret && makeAction(action, tb, "Tool Bar", ":/Res/pic/tool.png");
    if ( ret )
    {
        action->setCheckable(true);
        action->setChecked(true);
        connect(action, SIGNAL(triggered()), this, SLOT(onViewToolBar()));
        tb->addAction(action);
    }

    ret = ret && makeAction(action, tb, "Status Bar", ":/Res/pic/status.png");
    if ( ret )
    {
        action->setCheckable(true);
        action->setChecked(true);
        connect(action, SIGNAL(triggered()), this, SLOT(onViewStatusBar()));
        tb->addAction(action);
    }

    return ret;
}

//生成菜单项(第1个参数是菜单项对象,第2个参数为父组件,第3个参数为显示文本,第4个参数为快捷键)
bool MainWindow::makeAction(QAction*& action, QWidget* parent, QString text, int key)
{
    bool ret = true;

    action = new QAction(text, parent); //设置parent

    if(action != NULL)
    {
        action->setShortcut(QKeySequence(key)); //设置快捷键
    }
    else
    {
        ret = false;
    }

    return ret;
}

//生成工具栏中的各按钮
bool MainWindow::makeAction(QAction*& action, QWidget* parent, QString tip, QString icon)
{
    bool ret = true;
    action = new QAction("", parent);

    if( action != NULL )
    {
        action ->setToolTip(tip);
        action->setIcon(QIcon(icon));
    }
    else
    {
       ret = false;
    }

    return ret;
}

MainWindow::~MainWindow()
{

}

//MainWindowSlots.cpp

//该文件MainWindowSlots.cpp与MainWindowUI.cpp的分离
//体现了界面和功能代码分离的思想
#include "MainWindow.h"
#include "AboutDialog.h"
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
#include <QMap>
#include <QCloseEvent>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QMimeData>
#include <QToolBar>
#include <QPrintDialog> //QT += printsupport
#include <QApplication>
#include <QInputDialog>
#include <QStatusBar>
#include <QFontDialog>
#include <QDesktopServices>
#include <QDebug>

void MainWindow::showErrorMessage(QString message)
{
    QMessageBox msg(this);

    msg.setWindowTitle("Erro");
    msg.setText(message);
    msg.setIcon(QMessageBox::Critical);
    msg.setStandardButtons(QMessageBox::Ok);

    msg.exec();
}

int MainWindow::showQueryMessage(QString message)
{
    QMessageBox msg(this);

    msg.setWindowTitle("Query");
    msg.setText(message);
    msg.setIcon(QMessageBox::Question);
    msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);

    return msg.exec();
}

QString MainWindow::showFileDialog(QFileDialog::AcceptMode mode, QString title)
{
    QString ret = "";
    QFileDialog fd(this);
    QStringList filters;
    QMap<QString, QString> map;
    ] =
    {
        {"Text(*.txt)",    ".txt"},
        {"All Files(*.*)", "*"   },
        {NULL,             NULL}
    };

    ; filterArray[i][] != NULL; i++)
    {
        filters.append(filterArray[i][]);
        map.insert(filterArray[i][], filterArray[i][]);
    }

    fd.setWindowTitle(title);
    fd.setAcceptMode(mode); //QFileDialog::AcceptOpen或AcceptSave
    fd.setNameFilters(filters);

    if(mode == QFileDialog::AcceptOpen)
    {
        fd.setFileMode(QFileDialog::ExistingFile); //打开文件必须存在!
    }

    if(fd.exec() == QFileDialog::Accepted)
    {
        ret = fd.selectedFiles()[];

        //Qt5中ret返回的是完整的路径名,含后缀。因此,后面的if块可省略,但Qt4可能
        //会返回不带后缀的文件名,当保存文件时,须手动加上去。
        if(mode == QFileDialog::AcceptSave)
        {
            QString postfix = map[fd.selectedNameFilter()];
            if((postfix != "*") && !ret.endsWith(postfix))
            {
                ret = ret + postfix;
            }
        }
    }

    return ret;
}

void MainWindow::preEditorChanged()
{
    if (m_isTextChanged)
    {
        int r = showQueryMessage("Do you want to save the changes to file?");

        switch(r)
        {
        case QMessageBox::Yes:
            saveCurrentData(m_filePath);
            break;
        case QMessageBox::No:
            m_isTextChanged = false;
            break;
        case QMessageBox::Cancel:
            break;
        }
    }
}

void MainWindow::onFileNew()
{
    preEditorChanged();

    if(!m_isTextChanged)
    {
        mainEditor.clear();

        setWindowTitle("NotePad - [ New ]");

        m_filePath = "";

        m_isTextChanged = false;
    }
}

void MainWindow::openFileToEditor(QString path)
{
    if( path != "")
    {
        QFile file(path);

        if (file.open(QIODevice::ReadOnly | QIODevice::Text))
        {
            mainEditor.setPlainText(QString(file.readAll()));

            file.close();

            m_filePath = path; //记录当前打开的文件路径和文件名

            m_isTextChanged = false;

            setWindowTitle("NotePad - [" + m_filePath + "]");
        }
        else
        {
            showErrorMessage(QString("Open file Error!\n\n") + "\"" + path + "\"");
        }
    }
}

void MainWindow::onFileOpen()
{
    preEditorChanged();

    if( !m_isTextChanged)
    {
        QString path = showFileDialog(QFileDialog::AcceptOpen, "Open");
        openFileToEditor(path);
    }
}

QString MainWindow::saveCurrentData(QString path, QString title)
{
    QString ret = path;
    if (ret =="")
    {
        //执行下面语句时,用户可以点击“取消”,此时ret返回""
        ret = showFileDialog(QFileDialog::AcceptSave, title);
    }

    if (ret != "")
    {
        QFile file(ret);

        if (file.open(QIODevice::WriteOnly | QIODevice::Text))
        {
            QTextStream out(&file);

            out << mainEditor.toPlainText();

            file.close();

            setWindowTitle("NotePad - [" + ret + "]");

            m_isTextChanged = false; //己保存
        }
        else
        {
            showErrorMessage(QString("Save file Error!\n\n") + "\"" + m_filePath + "\"");
            ret =""; //保存失败时
        }
    }

    return ret;
}

void MainWindow::onFileSave()
{
    QString path = saveCurrentData(m_filePath, "Save");

    if( path != "" )
    {
        m_filePath = path;
    }
}

void MainWindow::onFileSaveAs()
{
    QString path = saveCurrentData(m_filePath, "Save As");

    if( path != "" )
    {
        m_filePath = path;
    }
}

void MainWindow::onTextChanged()
{
    if( !m_isTextChanged )
    {
        setWindowTitle("*" + windowTitle());
    }

    m_isTextChanged = true;
    //qDebug()<< "onTextChanged()";
}

void MainWindow::closeEvent(QCloseEvent* e)
{
    preEditorChanged();

    if(!m_isTextChanged)
    {
        QMainWindow::closeEvent(e);
    }
    else
    {
        //当用户按下“取消”
        e->ignore();//忽略关闭事件
    }
}

void MainWindow::dragEnterEvent(QDragEnterEvent *e)
{
    if(e->mimeData()->hasUrls())
    {
        e->acceptProposedAction();
    }
    else
    {
        e->ignore();
    }
}

void MainWindow::dropEvent(QDropEvent *e)
{
    qDebug() << "dropEvent";
    if(e->mimeData()->hasUrls())
    {
        QList<QUrl> list = e->mimeData()->urls();
        QString path = list[].toLocalFile();
        QFileInfo fi(path);

        if(fi.isFile())
        {
            preEditorChanged();
            if(!m_isTextChanged)
            {
                openFileToEditor(path);
            }
        }
        else
        {
            showErrorMessage("Can't open a folder!");
        }
    }
    else
    {
        e->ignore();
    }
}

void MainWindow::onCopyAvailable(bool available)
{
    QAction* action = findMenuBarAction("Copy");
    if (action != NULL) action->setEnabled(available);

    action = findMenuBarAction("Cut");
    if (action != NULL) action->setEnabled(available);

    action = findToolBarAction("Copy");
    if (action != NULL) action->setEnabled(available);

    action = findToolBarAction("Cut");
    if (action != NULL) action->setEnabled(available);
}

void MainWindow::onRedoAvailable(bool available)
{
    QAction* action = findMenuBarAction("Redo");
    if (action != NULL) action->setEnabled(available);

    action =  findToolBarAction("Redo");
    if (action != NULL) action->setEnabled(available);
}

void MainWindow::onUndoAvailable(bool available)
{
    QAction* action = findMenuBarAction("Undo");
    if (action != NULL) action->setEnabled(available);

    action =  findToolBarAction("Undo");
    if (action != NULL) action->setEnabled(available);
}

QAction* MainWindow::findMenuBarAction(QString text)
{
    QAction* ret = NULL;
    const QObjectList& list = menuBar()->children();

    ; i<list.count(); i++)
    {
        //各菜单(如文件、编辑、查看等)
        QMenu* menu = dynamic_cast<QMenu*>(list[i]);

        if(menu != NULL)
        {
            QList<QAction*> actions = menu->actions();

            ; j<actions.count(); j++)
            {
                if(actions[j]->text().startsWith(text))
                {
                    ret = actions[j];
                    break;
                }
            }
        }
    }

    return ret;
}

QAction* MainWindow::findToolBarAction(QString text)
{
    QAction* ret = NULL;
    const QObjectList& list = children();

    ; i<list.count(); i++)
    {
        QToolBar* toolBar = dynamic_cast<QToolBar*>(list[i]);

        if(toolBar != NULL)
        {
            QList<QAction*> actions = toolBar->actions();

            ; j<actions.count(); j++)
            {
                if(actions[j]->toolTip().startsWith(text))
                {
                    ret = actions[j];
                    break;
                }
            }
        }
    }

    return ret;
}

void MainWindow::onFilePrint()
{
    QPrintDialog dlg(this);
    dlg.setWindowTitle("Print");

    if(dlg.exec() == QPrintDialog::Accepted)
    {
        QPrinter* p = dlg.printer();

        mainEditor.document()->print(reinterpret_cast<QPagedPaintDevice*>(p));
    }
}

void MainWindow::onCursorPositionChanged()
{
    int pos = mainEditor.textCursor().position();
    QString text = mainEditor.toPlainText();
    ;//列数
    ; //行数
    ; //用于记录光标之前最后一个'\n'所在索引位置

    //从头到光标所在位置
    ; i<pos; i++)
    {
        if( text[i] == '\n')
        {
            ln++;
            flag = i;
        }
    }

    col = pos -(flag + );
    statusLbl.setText() + ));
}

void MainWindow::onEditDelete()
{
    QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Delete, Qt::NoModifier);
    QKeyEvent keyRelease(QEvent::KeyRelease, Qt::Key_Delete, Qt::NoModifier);

    QApplication::sendEvent(&mainEditor, &keyPress);
    QApplication::sendEvent(&mainEditor, &keyRelease);
}

void MainWindow::onEditFind()
{
    m_pFindDlg->show();
}

void MainWindow::onEditReplace()
{
    m_pRelaceDlg->show();
}

void MainWindow::onEditGoto()
{
    bool ok = false;
    ,,mainEditor.document()->lineCount(),
                                ,&ok,Qt::WindowCloseButtonHint | Qt::Drawer);
    if (ok)
    {
        QString text = mainEditor.toPlainText();
        QTextCursor c = mainEditor.textCursor();
        ;
        ;//表示下一个换行符的位置

        ; i<ln; i++)
        {
            pos = next + ;
            next = text.indexOf('\n', pos);
        }

        c.setPosition(pos);
        mainEditor.setTextCursor(c);
    }
}

void MainWindow::onViewToolBar()
{
    //枚举窗体上的所有组件(含菜单、Editor、工具栏、状态栏等)
    const QObjectList& list = children();

    ; i<list.count(); i++)
    {
        QToolBar* tb = dynamic_cast<QToolBar*>(list[i]);

        if(tb != NULL)
        {
            bool visible = tb->isVisible();

            tb->setVisible(!visible);

            //更新菜单栏和工具栏的状态标志
            findMenuBarAction("Tool Bar")->setChecked(!visible);
            findToolBarAction("Tool Bar")->setChecked(!visible);

            break;
        }
    }
}

void MainWindow::onViewStatusBar()
{
    QStatusBar* sb = statusBar();
    bool visible = sb->isVisible();

    sb->setVisible(!visible);

    //更新菜单栏和工具栏的状态标志
    findMenuBarAction("Status Bar")->setChecked(!visible);
    findToolBarAction("Status Bar")->setChecked(!visible);
}

void MainWindow::onFileExit()
{
    close();
}

void MainWindow::onFormatWrap()
{
    QPlainTextEdit::LineWrapMode mode = mainEditor.lineWrapMode();

    if(mode == QPlainTextEdit::NoWrap)
    {
        mainEditor.setLineWrapMode(QPlainTextEdit::WidgetWidth);

        findMenuBarAction("Auto Wrap")->setChecked(true);
        findToolBarAction("Auto Wrap")->setChecked(true);
    }
    else
    {
        mainEditor.setLineWrapMode(QPlainTextEdit::NoWrap);

        findMenuBarAction("Auto Wrap")->setChecked(false);
        findToolBarAction("Auto Wrap")->setChecked(false);
    }
}

void MainWindow::onFormatFont()
{
    bool ok = false;
    QFont font = QFontDialog::getFont(&ok, mainEditor.font(), this);

    if(ok)
    {
        mainEditor.setFont(font);
    }
}

void MainWindow::onHelpManual()
{
    //打开本地文件
    QDesktopServices::openUrl(QUrl("file:///C:/Users/santaclaus/Desktop/help.txt"));

    //打开网站
    //QDesktopServices::openUrl(QUrl("http://www.xxx.com"));
}

void MainWindow::onHelpAbout()
{
    AboutDialog(this).exec();
}

4. 小结

(1)关于对话框用于标识软件自身的信息

(2)使用QFontDialog设置文本编辑框的字体

(3)设置文本编辑框的自动换行属性

(4)通过QDesktopServices使用桌面环境的系统服务

第50课 关于对话框(About)的更多相关文章

  1. 第50课 C++对象模型分析(上)

    1. 回归本质 (1)class是一种特殊的结构体 ①在内存中class依旧可以看作变量的集合 ②class与struct遵循相同的内存对齐规则 ③class中的成员函数与成员变量是分开存放的.即每个 ...

  2. 第50 课C++对象模型分析——成员函数(上)

    类中的成员函数位于代码段中调用成员函数时对象地址作为参数隐式传递成员函数通过对象地址访问成员变量C++语法规则隐藏了对象地址的传递过程 #include<iostream> #includ ...

  3. 第50 课C++对象模型分析——成员变量(上)

    C++对象模型,其实就是C++中的对象在内存中是如何排布的.C++中的对象包含了成员变量和成员函数,其实就是研究C++中的类对象它的成员变量和成员函数在内存中是如何排布的. 回归本质class 是一种 ...

  4. Android开发系列(二十七):使用ProgressDialog创建进度对话框

    进度对话框在寻常的应用中非经常见,比方下载的时候,打开页面的时候.转移文件等等.有环形的.有长条形的. 基本就这两种 创建进度对话框的两种方式: 1.创建ProgressDialog实例,然后调用Pr ...

  5. HTML 与 css 的简单学习

    第21课: 内联元素,又称为行内元素,主要来控制一行内的字: 如: span,不是独占一行,不能设置宽高,竖直方向上不能设置 margin与 pading的值,不过水平方向上可以设置哦.(因为它只在一 ...

  6. 黑马程序员——JAVA基础之GUI

    -----Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- GUI(图形用户界面)  GUI •  Graphical User Interface(图形用 ...

  7. 王家林 大数据Spark超经典视频链接全集[转]

    压缩过的大数据Spark蘑菇云行动前置课程视频百度云分享链接 链接:http://pan.baidu.com/s/1cFqjQu SCALA专辑 Scala深入浅出经典视频 链接:http://pan ...

  8. HTML, CSS学习笔记(完整版)

    第一章 div布局 前几课内容 .htm是早期的后缀.由于那时仅仅能支持长度为3的后缀.因此html与htm是一样的. shtml是server先处理然后再交给浏览器处理 #HTML小知识#之#XHT ...

  9. android教学大纲

    android班 教学大纲 个小时 次课:Android开发环境搭建及工具介绍 Android系统简介 Android开发环境简介及搭建 AndroidStudio提供的工具组件 次课:第一个Andr ...

随机推荐

  1. disabled="true" 的标签元素不可提交

    把jsp页面的input 标签设置成不可编辑: <input  name="Id"    value="${order.Id}" readOnly=&qu ...

  2. 向 div 元素添加圆角边框:

    div { border:2px solid; border-radius:25px; }

  3. mybatis报错invalid types () or values ()解决方法

      原因: Pojo类User没提供无参数构造方法, 加上该构造方法后,问题解决 ### Cause: org.apache.ibatis.reflection.ReflectionException ...

  4. Integer.valueof(String s)和Integer.parseInt(String s)的具体区别是什么?

    Integer.valueof(String s)和Integer.parseInt(String s)的具体区别是什么? Integer.valueof(String s)是将一个包装类是将一个实际 ...

  5. Windows 10 的音频和 MIDI API将统一

    微软一统 Windows 10 的音频和 MIDI API 微软在夏季NAMM上的A3E大会上做了主题演讲,他们对Windows 10的音频和MIDI API都做了新的规划,开发者针对Windows ...

  6. jQuery iPresenter 3D图片旋转

    在线实例 效果一 效果二 使用方法 <div class="htmleaf-container"> <div class="htmleaf-conten ...

  7. DOM事件揭秘-事件流

    事件:文档/窗口中发生的特定的交互瞬间 瀑布流,图片轮播 动作都是通过事件触发的 课程内容: 1,理解事件流 2,使用时间处理程序 3,不同的事件类型 ie4.0以后, 事件流:描述的是从页面中接收事 ...

  8. sharepoint2013的审核日志的时间区域设置

    最近在项目中碰到审核日志的时间为GMT格式 ,如何格式化成本地时间. 网站集设置成本地区域无法解决此类问题,后来查询资料才知道.无法更改 Change Audit Time From GMT Time ...

  9. linux 文件系统简介

    linux文件系统简介   文件系统是linux的一个十分基础的知识,同时也是学习linux的必备知识. 本文将站在一个较高的视图来了解linux的文件系统,主要包括了linux磁盘分区和目录.挂载基 ...

  10. Linux系统安装NoSQL(MongoDB和Redis)步骤及问题解决办法

    ➠更多技术干货请戳:听云博客 如下是我工作中的记录,介绍的是linux系统下NoSQL:MongoDB和Redis的安装过程和遇到的问题以及解决办法: 需要的朋友可以按照如下步骤进行安装,可以快速安装 ...