mainwindow.cpp

来自「AIML的实现」· C++ 代码 · 共 539 行

CPP
539
字号
//qtgui includes#include <MainWindow.h>#include <QtGuiCallBacks.h>#include "AIMLEngineThread.h"#include "CustomTextEdit.h"#include "Arguments.h"//QT includes#include <QtGui>//rebecca includes#include <rebecca/all.h>using namespace rebecca;namespace qtgui{void MainWindow::input(){	/*	 * emit that the user entered	 * some text and then clear 	 * the input field	 */	emit userTextEntered(m_userInputField->text());	m_userInputField->clear();}void MainWindow::openDir(){	/*	 * Call the open directory gui box.	 */	QString directory = QFileDialog::getExistingDirectory(                    this,                    "Choose a directory of AIML files to open",                    "../../aiml");   if(!directory.isEmpty())   {		/* 		 * Emit to anyone interested in the relative 		 * path to the AIML directory		 */		emit aimlDirectoryToOpen(directory);				   }}void MainWindow::openFile(){	/*	 * Call the open file gui box.	 */	QStringList fileNames = QFileDialog::getOpenFileNames(                        this,                        "Select one or more AIML files to open",                        "../../aiml",                        "AIML Files (*.aiml)\nAny File (*.*)");	if(!fileNames.empty())	{		/*		 * Iterate over the file(s), getthe 		 * relative paths to the file(s)		 * since RebeccaAIML can only handle		 * relative paths at the time of writing		 * this code, and emit them to anyone		 * listening to handle.		 */		foreach(QString fileName, fileNames)		{		   /* 			* Emit to anyone interested in the relative 			* path to the AIML file(s)			*/            emit aimlFileToOpen(fileName);		}	}}void MainWindow::aimlLoading(){	//Set the cursor to the hour glass to indicate "we're busy"	QApplication::setOverrideCursor(Qt::WaitCursor);		//Show the message that AIML is loading in the bottom of the gui	statusBar()->showMessage(tr("AIML Loading"));	/*	 * Disable the buttons which would cause problems	 * during the loading of AIML if they are pressed.	 */	m_openAct->setEnabled(false);	m_openDirAct->setEnabled(false);	m_newAct->setEnabled(false);	m_saveAct->setEnabled(false);	m_saveAsAct->setEnabled(false);	/*	 * Set the tooltips to let the user know they can't	 * click the buttons while AIML is loading.	 */	m_openDirAct->setToolTip("Cannot open a directory while AIML is loading");	m_openAct->setToolTip("Cannot open a file while AIML is loading");	m_newAct->setToolTip("Cannot clear an AIML session while one is loading");	m_saveAct->setToolTip("Cannot save an AIML session while one is loading");	m_saveAsAct->setToolTip("Cannot save an AIML session while one is loading");}void MainWindow::aimlDoneLoading(){	/*	 * Enable the buttons which would have caused problems	 * during the loading of AIML if they were pressed.	 */	m_openAct->setEnabled(true);	m_openDirAct->setEnabled(true);	m_newAct->setEnabled(true);	m_saveAct->setEnabled(true);	m_saveAsAct->setEnabled(true);	/*	 * Set the tooltips back to "normal".	 */	m_openDirAct->setToolTip("Open a AIML directory");	m_openAct->setToolTip("Open an AIML file");	m_newAct->setToolTip("Clear a current AIML session");	m_saveAct->setToolTip("Save the current AIML session as plain text");	m_saveAsAct->setToolTip("Save the current AIML session as plain text");	//Show the message that AIML is done loading in the bottom of the gui	statusBar()->showMessage(tr("AIML done loading"));	//Set the cursor to the hour glass to indicate "we're *not* busy"	QApplication::restoreOverrideCursor();}bool MainWindow::save(){	/*	 * If we don't have a "current" file that	 * we've been saving to then let's saveAs	 * and get one.  Otherwise, just save to 	 * that "current" file.	 */    if (m_curFile.isEmpty()) 	{        return saveAs();    } 	else 	{        return saveFile(m_curFile);    }}void MainWindow::setCurrentFile(const QString &fileName){	/*	 * Set the object's variable to the fileName	 * and then use the file Name to display in the	 * gui window title bar	 */	m_curFile = fileName;	QString shownName;	if (m_curFile.isEmpty())	{		shownName = "untitled.txt";	}    else	{		shownName = strippedName(m_curFile);	}	setWindowTitle(tr("%1[*] - %2").arg(shownName).arg(tr("AIML Simple Qt GUI")));}QString MainWindow::strippedName(const QString &fullFileName){	//Strip the name    return QFileInfo(fullFileName).fileName();}bool MainWindow::saveAs(){	//Bring up the GUI dialog to select a file    QString fileName = QFileDialog::getSaveFileName(		this,		"Choose a filename to save this AIML session as plain text",		"",		"Text Files(*.txt)\nAll Files (*.*)");		//No file, let's return false	if (fileName.isEmpty())        return false;		//We have a file, return if we could save it okay or not.    return saveFile(fileName);}bool MainWindow::saveFile(const QString &fileName){	/*	 * Try to open the file for writing	 * and throw an error if we can't	 */	QFile file(fileName);    if (!file.open(QFile::WriteOnly | QFile::Text)) 	{        QMessageBox::warning(this, tr("Application"),                                tr("Cannot write file %1:\n%2.")                                .arg(fileName)                                .arg(file.errorString()));        return false;    }		/*	 * Write the conversation out as plain text	 * to the file	 */    QTextStream out(&file);    QApplication::setOverrideCursor(Qt::WaitCursor);	out << m_botOutputField->toPlainText();    QApplication::restoreOverrideCursor();	/* 	 * This file is our "current" file and is to 	 * be saved to each time we save a file unless	 * they select "save as"	 */    setCurrentFile(fileName);	//Show on the bottom part of the gui that the file had been saved	statusBar()->showMessage(tr("File saved"), 2000);    return true;}MainWindow::MainWindow()	: m_okButton(new QPushButton("Enter")),	  m_userInputField(new QLineEdit),	  m_botOutputField(new CustomTextEdit),	  m_botName("No bot name"){	/* 	 * Start our Aiml engine thread.  We start	 * it at lowest priority to give the gui a 	 * bit of extra responsiveness at the expense	 * that the engine will load slower	 */	m_AIMLEngineThread.start(QThread::LowestPriority);	//Setup QT connections to the AIML engine.	setupConnections();	//Setup initial gui properties 	setupInitialProperties();			//Show in the lower part of the gui that "The gui is loaded"	createStatusBar();		//Create the GUI actions from memory	createActions();		//Create our GUI menus	createMenus();		//Create our GUI tool bars	createToolBars();		//Setup the GUI layout	setupLayout();		/*	 * Set the focus to the user input field so the 	 * user doesn't have to click it to start	 * and make it more user friendly	 */	m_userInputField->setFocus();}void MainWindow::setupConnections(){	/*	 * Make all the signal to signal and 	 * signal to slot connections from this 	 * object to the AIMLEngineThread 	 * object.	 */	bool b = connect(m_okButton, SIGNAL(clicked()),                      this, SLOT(input()));	b = connect(this, SIGNAL(userTextEntered(const QString &)),                &m_AIMLEngineThread, SIGNAL(userInput(const QString &)));	b = connect(&m_AIMLEngineThread, SIGNAL(addText(const QString &)),                 m_botOutputField, SLOT(append(const QString &)));	b = connect(m_userInputField, SIGNAL(returnPressed()),                this, SLOT(input()));	b = connect(&m_AIMLEngineThread, SIGNAL(addBotText(const QString &)),		        this, SLOT(addBotText(const QString &)));	b = connect(&m_AIMLEngineThread, SIGNAL(loading()),		        this, SLOT(aimlLoading()));	b = connect(&m_AIMLEngineThread, SIGNAL(doneLoading()),				this, SLOT(aimlDoneLoading()));	b = connect(&m_AIMLEngineThread, SIGNAL(addBotName(const QString &)),		        this, SLOT(addBotName(const QString &)));	b = connect(this, SIGNAL(aimlFileToOpen(const QString &)),		        &m_AIMLEngineThread, SIGNAL(addFile(const QString &)));	b = connect(this, SIGNAL(aimlDirectoryToOpen(const QString &)),			    &m_AIMLEngineThread, SIGNAL(addDirectory(const QString &)));	b = connect(this, SIGNAL(aimlClear()),		        &m_AIMLEngineThread, SIGNAL(clearAIML()));}void MainWindow::addBotText(const QString &text){	/* 	 * Set the color of the bot text and 	 * the name, and the image of our bot,	 * and then send that.  Aftwards set the	 * color back to normal.	 */	m_botOutputField->setTextColor(QColor(Qt::yellow));	QString botOutput = m_botName + " says: " + text;	//Get the global arguments set in main()	Arguments *arguments = Arguments::getInstance();	QString imgSrc = string("<img src=\"" + arguments->getResourcesDirectory() + "/pictures/beckyface.png\">").c_str();	m_botOutputField->append(imgSrc);	m_botOutputField->append(botOutput);	m_botOutputField->setTextColor(QColor(Qt::white));}void MainWindow::addBotName(const QString &text){	//Set our bot name to what we were told it is.	m_botName = text;}void MainWindow::createMenus(){	//Standard QT creating and adding menus	m_fileMenu = menuBar()->addMenu("&File");    m_fileMenu->addAction(m_newAct);    m_fileMenu->addAction(m_openAct);    m_fileMenu->addAction(m_openDirAct);    m_fileMenu->addAction(m_saveAct);    m_fileMenu->addAction(m_saveAsAct);    m_fileMenu->addSeparator();    m_fileMenu->addAction(m_exitAct);	menuBar()->addSeparator();	m_helpMenu = menuBar()->addMenu(tr("&Help"));	m_helpMenu->addAction(m_aboutAct);}void MainWindow::newFile(){	/*	 * New AIML file.  So clear the 	 * previous text and tell the 	 * AIMLEngineThreadthat it should 	 * destroy the AIMLEngine	 */	m_botOutputField->clear();	m_botOutputField->setTextColor(QColor(Qt::white));	emit aimlClear();}void MainWindow::createActions(){	//Standard creating and connecting QT Actions.	Arguments *arguments = Arguments::getInstance();	QString resourceDir = arguments->getResourcesDirectory().c_str();	m_newAct = new QAction(QIcon(resourceDir + "/pictures/new.png"), tr("&New"), this);	m_newAct->setShortcut(tr("Ctrl+N"));	m_newAct->setStatusTip(tr("Unload the current aiml session"));	connect(m_newAct, SIGNAL(triggered()), this, SLOT(newFile()));	m_openAct = new QAction(QIcon(resourceDir + "/pictures/open.png"), tr("&Open"), this);    m_openAct->setShortcut(tr("Ctrl+O"));    m_openAct->setStatusTip("Add an individual AIML file");	connect(m_openAct, SIGNAL(triggered()), this, SLOT(openFile()));	m_openDirAct = new QAction(QIcon(resourceDir + "/pictures/openDir.png"), tr("&OpenDirectory"), this);    m_openDirAct->setShortcut(tr("Ctrl+D"));    m_openDirAct->setStatusTip("Add an entire AIML directory");	connect(m_openDirAct, SIGNAL(triggered()), this, SLOT(openDir()));	m_saveAct = new QAction(QIcon(resourceDir + "/pictures/save.png"), tr("&Save"), this);	m_saveAct->setShortcut(tr("Ctrl+S"));	m_saveAct->setStatusTip(tr("Save the AIML conversation to disk"));	connect(m_saveAct, SIGNAL(triggered()), this, SLOT(save()));	m_saveAsAct = new QAction(tr("Save &As..."), this);	m_saveAsAct->setStatusTip(tr("Save the document under a new name"));	connect(m_saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));	m_exitAct = new QAction(tr("E&xit"), this);	m_exitAct->setShortcut(tr("Ctrl+Q"));	m_exitAct->setStatusTip(tr("Exit the application"));	connect(m_exitAct, SIGNAL(triggered()), this, SLOT(close()));	m_aboutAct = new QAction(tr("&About"), this);	m_aboutAct->setStatusTip(tr("Show the About box"));	bool b = connect(m_aboutAct, SIGNAL(triggered()), this, SLOT(about()));}void MainWindow::createToolBars(){	//Standard QT creating ToolBars	m_fileToolBar = addToolBar(tr("File"));	m_fileToolBar->addAction(m_newAct);	m_fileToolBar->addAction(m_openAct);	m_fileToolBar->addAction(m_openDirAct);	m_fileToolBar->addAction(m_saveAct);}void MainWindow::createStatusBar(){	//Show the gui is loaded, this method is pretty useless actually	statusBar()->showMessage(tr("GUI Loaded"));}void MainWindow::setupInitialProperties(){	//Get the global arguments set in main()	Arguments *arguments = Arguments::getInstance();	//Name of our background file	const QString backgroundFile = string(arguments->getResourcesDirectory() + "/pictures/background.png").c_str();	//Name of the icon file	const QString iconFile = string(arguments->getResourcesDirectory() + "/pictures/beckyface.png").c_str();	//Set the current saved file to default 	setCurrentFile("");	/*	 * Load our icon for the uppper left	 * of the GUI	 */	QPixmap iconPixmap;	iconPixmap.load(iconFile);	if(iconPixmap.load(iconFile))	{		QIcon icon(iconPixmap);		setWindowIcon(icon);	}	//Can't write to the where the bot is talking	m_botOutputField->setReadOnly(true);	//Setup our pretty font.	QFont bookFont("Book Antiqua", 12);	m_botOutputField->setFont(bookFont);	/*	 * Load the background file and setup the 	 * bot output field to the background.	 */	QPixmap pixmap;	if(pixmap.load(backgroundFile))	{	    m_botOutputField->setTextColor(QColor(Qt::white));		m_botOutputField->append("[Loaded pixmap: " + backgroundFile + "]");		QPalette palette;		palette.setBrush(QPalette::Base, QBrush(pixmap));		m_botOutputField->setPalette(palette);	}	else	{	    m_botOutputField->setTextColor(QColor(Qt::black));		m_botOutputField->append("[WARNING Failed to load pixmap: " + backgroundFile + "]"); 	}}void MainWindow::setupLayout(){	/*	 * Setup the layout so when resizing	 * happens it does so with grace with	 * the widgets all moving around together	 * in a choherient way.	 */	QWidget *widget = new QWidget;	QVBoxLayout *vlayout = new QVBoxLayout;	QHBoxLayout *hlayout = new QHBoxLayout;	hlayout->addWidget(m_userInputField);	hlayout->addWidget(m_okButton);	vlayout->addWidget(m_botOutputField);	vlayout->addLayout(hlayout);	widget->setLayout(vlayout);	setCentralWidget(widget);}void MainWindow::about(){	//Display standard about box.	QMessageBox::about(this, tr("Rebecca AIML"),			tr("RebeccaAIML is a Windows/Linux Object Oriented<br>"			"C++ chatter bot api/interpreter for AIML<br>" 			"(Artificial Intelligence Markup Language)<br>" 			"from the ALICE project. It includes comprehensive<br>"			"documentation and samples as well as showcases/teaches<br>"			"popular and recent C++ practices.<br><br>"			"<a href=\"http://rebecca-aiml.sourceforge.net/index.htm\">"			"http://rebecca-aiml.sourceforge.net/index.htm</a>"));}} //end of qtgui namespace 

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?