...
void MainWindow::on_save_as_triggered()
{
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
if(codeEditor->saveAsFile()){
saveSuccessAction(codeEditor);
}
}
}
...
c++
35 添加析构函数
【Qt开发项目实战——代码编辑器Code Editor Demo——35 项目完善——添加析构函数】
...
class MyCodeEditor : public QPlainTextEdit
{
Q_OBJECT
public:
...
~MyCodeEditor();
...
...
};
...
c++
...
MyCodeEditor::~MyCodeEditor()
{
delete lineNumberWidget;
}
...
c++
...
class MyTextEditByCode : public QWidget
{
Q_OBJECT
public:
...
~MyTextEditByCode();
...
...
};
...
c++
...
MyTextEditByCode::~MyTextEditByCode()
{
delete textEdit;
delete textBrowser;
delete scrollBar;
}
...
c++
36 复制粘贴剪切打印
【Qt开发项目实战——代码编辑器Code Editor Demo——36 项目完善——复制粘贴剪切打印】
...
void MainWindow::on_copy_triggered()
{
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
codeEditor->copy();
}
}
void MainWindow::on_paste_triggered()
{
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
codeEditor->paste();
}
}
void MainWindow::on_cut_triggered()
{
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
codeEditor->cut();
}
}
void MainWindow::on_undo_triggered()
{
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
codeEditor->undo();
}
}
void MainWindow::on_redo_triggered()
{
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
codeEditor->redo();
}
}
...
void MainWindow::on_print_triggered()
{
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
QPrinter printDev;
#if QT_CONFIG(printdialog)
QPrintDialog dialog(&printDev,this);
if(dialog.exec()==QDialog::Rejected)
return;
#endif
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
codeEditor->print(&printDev);
}
#endif
}
...
c++
37 设置字体Ⅰ
【Qt开发项目实战——代码编辑器Code Editor Demo——37 项目完善——设置字体Ⅰ】
...
#include "QSettings"
...
class MainWindow : public QMainWindow
{
...
private:
...
QSettings * mSettings;
QList<QString> getHistory();
void saveHistory(QString path);
};
...
c++
...
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
...
mSettings = new QSettings("settings.ini",QSettings::IniFormat);
initFont();
...
}
...
void MainWindow::initFont(){
mFontFamily = mSettings->value("font_family","Consolas").toString();
mFontSize = mSettings->value("font_size",14).toInt();
}
...
QList<QString> MainWindow::getHistory(){
...
}
void MainWindow::saveHistory(QString path){
...
}
...
void MainWindow::on_font_triggered()
{
bool fontSelected;
QFont font = QFontDialog::getFont(&fontSelected,QFont(mFontFamily,mFontSize),this);
if(fontSelected){
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
codeEditor->setAllFont(font);
}
mSettings->setValue("font_family",font.family());
mSettings->setValue("font_size",font.pixelSize());
}
}
...
c++
...
class MyCodeEditor : public QPlainTextEdit
{
Q_OBJECT
public:
...
void setAllFont(QFont font);
...
};
...
c++
...
MyCodeEditor::MyCodeEditor(QWidget *parent,QFont font) : QPlainTextEdit(parent)
{
...
setAllFont(font);
...
}
...
void MyCodeEditor::setAllFont(QFont font)
{
this->setFont(font);
mHighlighter->setFont(font);
updateLineNumberWidgetWidth();
}
...
c++
...
class MyHighlighter: public QSyntaxHighlighter
{
public:
...
void setFont(QFont font);
...
};
...
c++
...
void MyHighlighter::setFont(QFont font)
{
mFontFamily = font.family();
mFontSize = font.pixelSize();
}
...
c++
38 设置字体Ⅱ
【Qt开发项目实战——代码编辑器Code Editor Demo——38 项目完善——设置字体Ⅱ】
...
void MainWindow::on_font_triggered()
{
bool fontSelected;
QFont font = QFontDialog::getFont(&fontSelected,QFont(mFontFamily,mFontSize),this);
if(fontSelected){
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
codeEditor->setAllFont(font);
}
mSettings->setValue("font_family",font.family());
mSettings->setValue("font_size",font.pointSize());
}
}
...
c++
...
MyCodeEditor::MyCodeEditor(QWidget *parent,QFont font) : QPlainTextEdit(parent)
{
...
initHighlighter();
setAllFont(font);
...
}
...
c++
39 退出保存提示Ⅰ
【Qt开发项目实战——代码编辑器Code Editor Demo——39 项目完善——退出保存提示Ⅰ】
...
class MyCodeEditor : public QPlainTextEdit
{
Q_OBJECT
public:
...
bool checkSaved();
...
private:
...
bool isSaved = false;
...
};
...
c++
...
void MyCodeEditor::updateSaveState()
{
isSaved = false;
}
...
bool MyCodeEditor::saveFile()
{
...
isSaved = true;
...
}
bool MyCodeEditor::saveAsFile()
{
...
isSaved = true;
...
}
...
c++
...
class MainWindow : public QMainWindow
{
...
private slots:
...
void on_tabWidget_tabCloseRequested(int index);
...
};
...
c++
...
void MainWindow::on_tabWidget_tabCloseRequested(int index)
{
MyCodeEditor * codeEditor = (MyCodeEditor*)ui->tabWidget->currentWidget();
if(!codeEditor->checkSaved()){
QMessageBox::StandardButton btn = QMessageBox::question(this,"警告","您还没有保存文档!是否保存?",QMessageBox::Yes|QMessageBox::No);
if(btn ==QMessageBox::Yes){
if(codeEditor->saveFile()){
saveSuccessAction(codeEditor);
}
}
}
delete codeEditor;
ui->tabWidget->removeTab(index);
}
...
c++
40 退出保存提示Ⅱ
【Qt开发项目实战——代码编辑器Code Editor Demo——40 项目完善——退出保存提示Ⅱ】
...
class MyCodeEditor : public QPlainTextEdit
{
...
private slots:
...
void updateSaveState();
...
};
...
c++
...
void MyCodeEditor::initConnection()
{
...
connect(this,SIGNAL(textChanged()),this,SLOT(updateSaveState()));
...
}
...
void MyCodeEditor::updateSaveState()
{
isSaved = false;
}
...
c++
41 设置工具状态
【Qt开发项目实战——代码编辑器Code Editor Demo——41 项目完善——设置工具状态】
...
class MainWindow : public QMainWindow
{
...
private:
...
void initAction();
...
};
...
c++
...
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
...
initAction();
...
}
...
void MainWindow::initAction()
{
bool valid =ui->tabWidget->count()>0;
ui->save_file->setEnabled(valid);
ui->save_as->setEnabled(valid);
ui->copy->setEnabled(valid);
ui->paste->setEnabled(valid);
ui->cut->setEnabled(valid);
ui->undo->setEnabled(valid);
ui->redo->setEnabled(valid);
}
...
c++
42 退出保存提示Ⅲ
【Qt开发项目实战——代码编辑器Code Editor Demo——42 项目完善——退出保存提示Ⅲ】
...
void MainWindow::on_tabWidget_tabCloseRequested(int index)
{
MyCodeEditor * codeEditor = (MyCodeEditor*)ui->tabWidget->currentWidget();
if(!codeEditor->checkSaved()){
QMessageBox::StandardButton btn = QMessageBox::question(this,"警告","您还没有保存文档!是否保存?" , QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel);
if(btn ==QMessageBox::Yes){
if(codeEditor->saveFile())
saveSuccessAction(codeEditor);
return;
}else if(btn ==QMessageBox::Cancel)
return;
}
ui->tabWidget->removeTab(index);
delete codeEditor;
initAction();
}
...
c++
43 窗口关闭事件
【Qt开发项目实战——代码编辑器Code Editor Demo——43 项目完善——窗口关闭事件】
...
class MainWindow : public QMainWindow
{
...
protected:
void closeEvent(QCloseEvent *event);
...
};
...
c++
...
void MainWindow::closeEvent(QCloseEvent *event)
{
if(ui->tabWidget->count()>0){
QMessageBox::question(this,
"警告",
"有未保存的文件,确定要关闭吗?",
QMessageBox::Yes|QMessageBox::No)==QMessageBox::Yes?event->accept():event->ignore();
}
}
c++
44 关闭标签页问题修复
【Qt开发项目实战——代码编辑器Code Editor Demo——39 项目完善——关闭标签页问题修复】
...
void MainWindow::on_tabWidget_tabCloseRequested(int index)
{
...
ui->tabWidget->removeTab(index);
delete codeEditor;
}
...
c++
45 关键字保留字配置
【Qt开发项目实战——代码编辑器Code Editor Demo——45 项目完善——关键字保留字配置】
alignas
alignof
andb
and_eqb
asma
auto
bitandb
bitorb
bool
break
case
catch
char
char8_tc
char16_t
char32_t
class
complb
conceptc
const
const_cast
constevalc
constexpr
constinitc
continue
co_awaitc
co_returnc
co_yieldc
decltype
default
delete
do
double
dynamic_cast
else
enum
explicit
exportc
extern
false
float
for
friend
goto
if
inline
int
long
mutable
namespace
new
noexcept
notb
not_eqb
nullptr
operator
orb
or_eqb
private
protected
public
register reinterpret_cast
requiresc
return
short
signed
sizeof
static
static_assert
static_cast
struct
switch
template
this
thread_local
throw
true
try
typedef
typeid
typename
union
unsigned
using
using
virtual
void
volatile
wchar_t
while
xorb
xor_eqb
c++
abstract
assert
boolean
break
byte
case
catch
char
class
continue
default
do
double
else
enum
extends
final
finally
float
for
if
implements
import
int
interface
instanceof
long
native
new
package
private
protected
public
return
short
static
strictfp
super
switch
synchronized
this
throw
throws
transient
try
void
volatile
while
c++
小结——完整代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include "QFileDialog"
#include "QMessageBox"
#include "QFontDialog"
#include <QDateTime>
#if defined(QT_PRINTSUPPORT_LIB)
#include <QtPrintSupport/qtprintsupportglobal.h>
#if QT_CONFIG(printer)
#if QT_CONFIG(printdialog)
#include <QPrintDialog>
#endif
#include <QPrinter>
#endif
#endif
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
mSettings = new QSettings("settings.ini",QSettings::IniFormat);
initMenu();
initFont();
initAction();
#if !QT_CONFIG(printer)
ui->print->setEnabled(false);
#endif
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::initFont(){
mFontFamily = mSettings->value("font_family","Consolas").toString();
mFontSize = mSettings->value("font_size",14).toInt();
}
void MainWindow::initAction()
{
bool valid =ui->tabWidget->count()>0;
ui->save_file->setEnabled(valid);
ui->save_as->setEnabled(valid);
ui->copy->setEnabled(valid);
ui->paste->setEnabled(valid);
ui->cut->setEnabled(valid);
ui->undo->setEnabled(valid);
ui->redo->setEnabled(valid);
}
void MainWindow::initMenu()
{
QMenu * recent = this->findChild<QMenu *>("recent");
QList<QObject *> chLists =recent->children();
foreach(QObject * ch,chLists){
QAction *action = (QAction *)ch;
recent->removeAction(action);
}
QList<QString> lists = getHistory();
for(int i=lists.size()-1 ;i>=0;i--){
recent->addAction(lists[i],this,&MainWindow::on_open_rencent_file);
}
if(lists.size()>0){
recent->addAction("清除历史记录",this,&MainWindow::on_clear_history_triggered,QKeySequence("Ctrl+Alt+Shift+C"));
}
}
QList<QString> MainWindow::getHistory(){
int size =mSettings->beginReadArray("history");
QList<QString> lists;
for(int i = 0;i<size;i++){
mSettings->setArrayIndex(i);
QString path = mSettings->value("path").toString();
lists.append(path);
}
mSettings->endArray();
return lists;
}
void MainWindow::saveHistory(QString path){
QList<QString> lists = getHistory();
foreach(QString str,lists){
if(str==path){
lists.removeOne(str);
}
}
lists.append(path);
mSettings->beginWriteArray("history");
for(int i =0;i<lists.size();i++){
mSettings->setArrayIndex(i);
mSettings->setValue("path",lists[i]);
}
mSettings->endArray();
}
void MainWindow::on_new_file_triggered()
{
ui->tabWidget->addTab(new MyCodeEditor(this,QFont(mFontFamily,mFontSize)),"NewFile.xjy");
initAction();
}
void MainWindow::on_open_rencent_file()
{
createTab(((QAction *)sender())->text());
}
void MainWindow::on_open_file_triggered()
{
createTab(QFileDialog::getOpenFileName(this,"打开文件"));
}
void MainWindow::createTab(QString fileName)
{
QFile file(fileName);
if(!file.open(QIODevice::ReadOnly|QFile::Text)){
QMessageBox::warning(this,"警告","无法打开此文件:"+file.errorString());
return;
}
QTextStream in(&file);
QString text = in.readAll();
MyCodeEditor * codeEditor = new MyCodeEditor(this,QFont(mFontFamily,mFontSize));
codeEditor->setPlainText(text);
codeEditor->setFileName(fileName);
ui->tabWidget->addTab(codeEditor,fileName);
ui->tabWidget->setCurrentIndex(ui->tabWidget->count()-1);
file.close();
saveHistory(fileName);
initMenu();
initAction();
}
void MainWindow::on_save_file_triggered()
{
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
if(codeEditor->saveFile()){
saveSuccessAction(codeEditor);
}
}
}
void MainWindow::on_save_as_triggered()
{
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
if(codeEditor->saveAsFile()){
saveSuccessAction(codeEditor);
}
}
}
void MainWindow::on_copy_triggered()
{
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
codeEditor->copy();
}
}
void MainWindow::on_paste_triggered()
{
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
codeEditor->paste();
}
}
void MainWindow::on_cut_triggered()
{
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
codeEditor->cut();
}
}
void MainWindow::on_undo_triggered()
{
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
codeEditor->undo();
}
}
void MainWindow::on_redo_triggered()
{
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
codeEditor->redo();
}
}
void MainWindow::on_font_triggered()
{
bool fontSelected;
QFont font = QFontDialog::getFont(&fontSelected,QFont(mFontFamily,mFontSize),this);
if(fontSelected){
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
codeEditor->setAllFont(font);
}
mSettings->setValue("font_family",font.family());
mSettings->setValue("font_size",font.pointSize());
}
}
void MainWindow::on_print_triggered()
{
MyCodeEditor *codeEditor = (MyCodeEditor* )ui->tabWidget->currentWidget();
if(codeEditor){
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
QPrinter printDev;
#if QT_CONFIG(printdialog)
QPrintDialog dialog(&printDev,this);
if(dialog.exec()==QDialog::Rejected)
return;
#endif
codeEditor->print(&printDev);
#endif
}
}
void MainWindow::on_about_triggered()
{
QMessageBox::about(this,"这是我的Notepad!","这是我的Notepad,欢迎学习和使用!");
}
void MainWindow::on_exit_triggered()
{
QCoreApplication::exit();
}
void MainWindow::on_clear_history_triggered()
{
mSettings->remove("history");
initMenu();
}
void MainWindow::on_tabWidget_tabCloseRequested(int index)
{
MyCodeEditor * codeEditor = (MyCodeEditor*)ui->tabWidget->currentWidget();
if(!codeEditor->checkSaved()){
QMessageBox::StandardButton btn = QMessageBox::question(this,"警告","您还没有保存文档!是否保存?",QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel);
if(btn ==QMessageBox::Yes){
if(codeEditor->saveFile())
saveSuccessAction(codeEditor);
return;
}else if(btn ==QMessageBox::Cancel)
return;
}
ui->tabWidget->removeTab(index);
delete codeEditor;
initAction();
}
void MainWindow::saveSuccessAction( MyCodeEditor * codeEditor)
{
QString fileName = codeEditor->getFileName();
saveHistory(fileName);
ui->tabWidget->setTabText(ui->tabWidget->currentIndex(),fileName);
initMenu();
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if(ui->tabWidget->count()>0){
QMessageBox::question(this,
"警告",
"有未保存的文件,确定要关闭吗?",
QMessageBox::Yes|QMessageBox::No)==QMessageBox::Yes?event->accept():event->ignore();
}
}
c++
#include "mycodeeditor.h"
#include "myhighlighter.h"
#include <QPainter>
#include <QTextStream>
#include <QScrollBar>
#include <QFileDialog>
#include <QMessageBox>
#include<QDebug>
MyCodeEditor::MyCodeEditor(QWidget *parent,QFont font) : QPlainTextEdit(parent)
{
lineNumberWidget = new LineNumberWidget(this);
initConnection();
initHighlighter();
setAllFont(font);
highlightCurrentLine();
updateLineNumberWidgetWidth();
setLineWrapMode(QPlainTextEdit::NoWrap);
}
MyCodeEditor::~MyCodeEditor()
{
delete lineNumberWidget;
}
void MyCodeEditor::initConnection()
{
connect(this,SIGNAL(cursorPositionChanged()),this,SLOT(highlightCurrentLine()));
connect(this,SIGNAL(textChanged()),this,SLOT(updateSaveState()));
connect(this,SIGNAL(blockCountChanged(int)),this,SLOT(updateLineNumberWidgetWidth()));
connect(this,SIGNAL(updateRequest(QRect,int)),this,SLOT(updateLineNumberWidget(QRect,int)));
}
void MyCodeEditor::setAllFont(QFont font)
{
this->setFont(font);
mHighlighter->setFont(font);
updateLineNumberWidgetWidth();
}
bool MyCodeEditor::checkSaved()
{
return isSaved;
}
void MyCodeEditor::initHighlighter()
{
mHighlighter = new MyHighlighter(document());
}
int MyCodeEditor::getLineNumberWidgetWidth()
{
return 8+QString::number(blockCount()+1).length()*fontMetrics().horizontalAdvance(QChar('0'));
}
void MyCodeEditor::highlightCurrentLine()
{
QList<QTextEdit::ExtraSelection> extraSelections;
QTextEdit::ExtraSelection selection;
selection.format.setBackground(QColor(0,100,100,20));
selection.format.setProperty(QTextFormat::FullWidthSelection,true);
selection.cursor =textCursor();
extraSelections.append(selection);
setExtraSelections(extraSelections);
}
void MyCodeEditor::updateLineNumberWidget(QRect rect, int dy)
{
if(dy)
lineNumberWidget->scroll(0,dy);
else
lineNumberWidget->update(0,rect.y(),getLineNumberWidgetWidth(),rect.height());
}
void MyCodeEditor::updateLineNumberWidgetWidth()
{
setViewportMargins(getLineNumberWidgetWidth(),0,0,0);
}
void MyCodeEditor::updateSaveState()
{
isSaved = false;
}
void MyCodeEditor::resizeEvent(QResizeEvent *event)
{
QPlainTextEdit::resizeEvent(event);
lineNumberWidget->setGeometry(0,0,getLineNumberWidgetWidth(),contentsRect().height());
}
void MyCodeEditor::lineNumberWidgetPaintEvent(QPaintEvent *event)
{
QPainter painter(lineNumberWidget);
painter.fillRect(event->rect(),QColor(100,100,100,20));
QTextBlock block = firstVisibleBlock();
int blockNumber =block.blockNumber();
int cursorTop = blockBoundingGeometry(textCursor().block()).translated(contentOffset()).top();
int top = blockBoundingGeometry(block).translated(contentOffset()).top();
int bottom = top +blockBoundingRect(block).height();
while(block.isValid()&&top<=event->rect().bottom()){
painter.setPen(cursorTop==top?Qt::black:Qt::gray);
painter.drawText(0,top,getLineNumberWidgetWidth()-3,bottom-top,Qt::AlignRight,QString::number(blockNumber+1));
block = block.next();
top = bottom;
bottom = top +blockBoundingRect(block).height();
blockNumber++;
}
}
void MyCodeEditor::lineNumberWidgetMousePressEvent(QMouseEvent *event)
{
setTextCursor(QTextCursor(document()->findBlockByLineNumber(event->y()/fontMetrics().height()+verticalScrollBar()->value())));
}
void MyCodeEditor::lineNumberWidgetWheelEvent(QWheelEvent *event)
{
if(event->orientation()==Qt::Horizontal){
horizontalScrollBar()->setValue(horizontalScrollBar()->value()-event->delta());
}else {
verticalScrollBar()->setValue(verticalScrollBar()->value()-event->delta());
}
event->accept();
}
bool MyCodeEditor::saveFile()
{
QString fileName;
if(mFileName.isEmpty()){
fileName =QFileDialog::getSaveFileName(this,"保存文件");
mFileName =fileName;
}else{
fileName =mFileName;
}
QFile file(fileName);
if(!file.open(QIODevice::WriteOnly|QFile::Text)){
QMessageBox::warning(this,"警告","无法保存文件:"+file.errorString());
return false;
}
QTextStream out(&file);
out<<toPlainText();
file.close();
isSaved = true;
return true;
}
bool MyCodeEditor::saveAsFile()
{
QString fileName=QFileDialog::getSaveFileName(this,"另存文件");
QFile file(fileName);
if(!file.open(QIODevice::WriteOnly|QFile::Text)){
QMessageBox::warning(this,"警告","无法保存文件:"+file.errorString());
return false;
}
mFileName =fileName;
QTextStream out(&file);
QString text =toPlainText();
out<<text;
file.close();
isSaved = true;
return true;
}
void MyCodeEditor::setFileName(QString fileName)
{
mFileName=fileName;
}
QString MyCodeEditor::getFileName()
{
return mFileName;
}
c++