#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mdichild.h"
#include <QMdiSubWindow>
#include <QFileDialog>
#include <QSignalMapper>
#include <QMessageBox>
#include <QSettings>
#include <QCloseEvent>
#include <QLabel>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//创建间隔器动作并设置
actionSeparator=new QAction(this);
actionSeparator->setSeparator(true);
//更新菜单
updateMenus();
//当有活动窗口时更新菜单
connect(ui->mdiArea,SIGNAL(subWindowActivated(QMdiSubWindow*)),this,SLOT(updateMenus()));
//创建信号映射器
windowMapper =new QSignalMapper(this);
//映射器重新发射信号,根据信号设置活动窗口
connect(windowMapper,SIGNAL(mapped(QWidget*)),this,SLOT(setActiveSubWindow(QWidget*)));
//更新窗口菜单,并设置当前菜单将要显示的时候更新菜单栏
updateWindowMenu();
connect(ui->menuW,SIGNAL(aboutToShow()),this,SLOT(updateWindowMenu()));
//初始窗口时读取窗口设置信息
readSettings();
initWindow();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_action_New_triggered()
{
//创建MDIChild
MdiChild *child=createMdiChild();
//多文档区域添加窗
//新建文件
child->newFile();
//显示子窗口
child->show();
}
MdiChild *MainWindow::createMdiChild()
{
//创建MdiChild部件
MdiChild *child=new MdiChild;
//向多文档区域添加子窗口,child为中心部件
ui->mdiArea->addSubWindow(child);
//根据QTextEdit类的是否可一复制信号设置剪贴复制动作是否可用
connect(child,SIGNAL(copyAvailable(bool)),ui->action_Cut,SLOT(setEnabled(bool)));
connect(child,SIGNAL(copyAvailable(bool)),ui->action_Copy,SLOT(setEnabled(bool)));
//根据QTextDocument类的是否可以撤销恢复信号设置撤销恢复动作是否可用
connect(child->document(),SIGNAL(undoAvailable(bool)),ui->action_Undo,SLOT(setEnabled(bool)));
connect(child->document(),SIGNAL(undoAvailable(bool)),ui->action_Redo,SLOT(setEnabled(bool)));
//每当编辑器的光标位置发生变化,就显示行号和列号
connect(child,SIGNAL(cursorPositionChanged()),this,SLOT(showTextRowAndCol()));
return child;
}
MdiChild *MainWindow::activeMdiChild()
{
//如果有活动窗口,则将其内的中心部件转换为MdiChild类型,没有则直接返回0
if(QMdiSubWindow *activeSubWindow=ui->mdiArea->activeSubWindow())
return qobject_cast<MdiChild*>(activeSubWindow->widget());
return 0;
}
void MainWindow::updateMenus(){
//根据是否有活动窗口设置各个动作是否可用
bool hasMdiChild=(activeMdiChild()!=0);
ui->action_Save->setEnabled(hasMdiChild);
ui->action_SaveAs->setEnabled(hasMdiChild);
ui->action_Paste->setEnabled(hasMdiChild);
ui->action_Close->setEnabled(hasMdiChild);
ui->action_CloseAll->setEnabled(hasMdiChild);
ui->action_Tile->setEnabled(hasMdiChild);
ui->action_Cascade->setEnabled(hasMdiChild);
ui->action_Next->setEnabled(hasMdiChild);
ui->action_Previous->setEnabled(hasMdiChild);
//设置间隔器是否显示
actionSeparator->setVisible(hasMdiChild);
//有活动窗口且有被选中的文本剪贴复制才有用
bool hasSelection =(activeMdiChild()&&activeMdiChild()->textCursor().hasSelection());
ui->action_Cut->setEnabled(hasSelection);
ui->action_Copy->setEnabled(hasSelection);
//有活动窗口且文档有撤销操作时撤销操作才有用
ui->action_Undo->setEnabled(activeMdiChild()&&activeMdiChild()->document()->isUndoAvailable());
//有活动窗口且文档有恢复操作时恢复动作可用
ui->action_Redo->setEnabled(activeMdiChild()&&activeMdiChild()->document()->isRedoAvailable());
}
void MainWindow::on_action_Open_triggered()
{
//获取文件路径
QString fileName=QFileDialog::getOpenFileName(this);
//如果路径不为空,则查看该文件是否被打开
if(!fileName.isEmpty()){
QMdiSubWindow *existing=findMdiChild(fileName);
//如果已经存在,则将对应窗口设定为活跃窗口
if(existing){
ui->mdiArea->setActiveSubWindow(existing);
return;
}
//如果没有被打开,则创建子窗口
MdiChild *child=createMdiChild();
if(child->loadFile(fileName)){
ui->statusBar->showMessage(tr("打开文件成功"),2000);
child->show();
}else{
child->close();
}
}
}
void MainWindow::updateWindowMenu()
{
//先清空菜单,再添加各个菜单动作
ui->menuW->clear();
ui->menuW->addAction(ui->action_Close);
ui->menuW->addAction(ui->action_CloseAll);
ui->menuW->addSeparator();
ui->menuW->addAction(ui->action_Tile);
ui->menuW->addAction(ui->action_Cascade);
ui->menuW->addSeparator();
ui->menuW->addAction(ui->action_Next);
ui->menuW->addAction(ui->action_Previous);
ui->menuW->addAction(actionSeparator);
// 如果有活动窗口,直接显示间隔器
QList<QMdiSubWindow *>windows=ui->mdiArea->subWindowList();
actionSeparator->setVisible(!windows.isEmpty());
//遍历各个窗口
for(int i=0;i<windows.size();++i){
MdiChild *child =qobject_cast<MdiChild *>(windows.at(i)->widget());
QString text;
//如果窗口数小于9,设置编号为快捷键
if(i<9){
text=tr("&%1 %2").arg(i+1).arg(child->userFriendlyCurrentFile());
}else{
text=tr("%1 %2").arg(i+1).arg(child->userFriendlyCurrentFile());
}
//添加动作到菜单栏,设置动作可以选择
QAction *action=ui->menuW->addAction(text);
action->setCheckable(true);
action->setChecked(child==activeMdiChild());
//关联动作的触发信号到信号映射器的map()槽,这个槽发射mapped()信号
connect(action,SIGNAL(triggered(bool)),windowMapper,SLOT(map()));
windowMapper->setMapping(action,windows.at(i));
}
}
QMdiSubWindow *MainWindow::findMdiChild(const QString &fileName){
QString canonicalFilePath=QFileInfo(fileName).canonicalFilePath();
//利用foreach语句遍历子窗口列表,如果其文件路径和要查找的文件路径相同,则返回该窗口
foreach(QMdiSubWindow *window,ui->mdiArea->subWindowList()){
MdiChild *mdiChild=qobject_cast<MdiChild*>(window->widget());
if(mdiChild->currentFile()==canonicalFilePath)
return window;
}
return 0;
}
void MainWindow::readSettings()
{
QSettings settings(tr("倩倩你个傻姑娘"),"mysave");
QPoint pos=settings.value("pos",QPoint(200,200)).toPoint();
QSize size=settings.value("size",QSize(400,400)).toSize();
move(pos);
resize(size);
}
void MainWindow::writeSettings()
{
QSettings settings(tr("倩倩你个傻姑娘"),"mysave");
//写入位置信息和大小信息
settings.setValue("pos",pos());
settings.setValue("size",size());
}
void MainWindow::initWindow()
{
setWindowTitle(tr("多文档编辑器"));
//当多文档区域的内容超出视野范围,出现滚动条
ui->mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
ui->mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
ui->statusBar->showMessage(tr("欢迎使用多文档编辑器"));
QLabel *label=new QLabel(this);
label->setFrameStyle(QFrame::Box|QFrame::Sunken);
label->setText(tr("<a href=\"http://www.baidu.com\">baidu.com</a>"));
//标签文本为富文本
label->setTextFormat(Qt::RichText);
//可以打开外部链接
label->setOpenExternalLinks(true);
评论0
最新资源