⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 editorcontainer.cpp

📁 kscope
💻 CPP
字号:
/*************************************************************************** *   Copyright (C) 2007-2009 by Elad Lahav *   elad_lahav@users.sourceforge.net * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the *   Free Software Foundation, Inc., *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. ***************************************************************************/#include <QMdiSubWindow>#include <QFileDialog>#include <QDebug>#include "editorcontainer.h"#include "editorconfigdialog.h"#include "queryresultdialog.h"namespace KScope{namespace App{/** * Class constructor. * @param  parent  Parent widget */EditorContainer::EditorContainer(QWidget* parent)	: QMdiArea(parent),	  activeEditor_(NULL),	  blockWindowActivation_(false),	  newFileIndex_(1){	// Load editor configuration settings.	QSettings settings;	settings.beginGroup("Editor");	config_.load(settings);	settings.endGroup();	// Notify when an active editor is available.	connect(this, SIGNAL(subWindowActivated(QMdiSubWindow*)), this,	        SLOT(windowActivated(QMdiSubWindow*)));}/** * Class destructor. */EditorContainer::~EditorContainer(){}/** * Fills the "Window" menu with a list of all open sub-window titles. * @param  wndMenu  The menu to populate */void EditorContainer::populateWindowMenu(QMenu* wndMenu) const{	// Add an entry for each open sub-window.	QMap<QString, QMdiSubWindow*>::ConstIterator itr;	for (itr = fileMap_.begin(); itr != fileMap_.end(); ++itr)		wndMenu->addAction(itr.key());	// Activate a sub-window when its menu entry is selected.	connect(wndMenu, SIGNAL(triggered(QAction*)), this,	        SLOT(handleWindowAction(QAction*)));}/** * Checks for any unsaved-changes in the currently open editors. * @return true if the application can terminate, false if the user cancels *         the operation due to unsaved changes */bool EditorContainer::canClose(){	// TODO: Saving a file may take too long (e.g., for NFS-mounted files).	// In this case, the application should not terminate until the file has	// been saved. The current behaviour may lead to data loss!	// Iterate over all editor windows.	foreach (QMdiSubWindow* window, fileMap_) {		Editor* editor = static_cast<Editor*>(window->widget());		if (!editor->canClose())			return false;	}	return true;}/** * Stores the locations of all editors in a session object. * @param  session  The session object to use */void EditorContainer::saveSession(Session& session){	Core::LocationList locList;	// Create a list of locations for the open editors.	foreach (QMdiSubWindow* window, fileMap_) {		Editor* editor = static_cast<Editor*>(window->widget());		Core::Location loc;		editor->getCurrentLocation(loc);		locList.append(loc);	}	session.setEditorList(locList);	// Store the path of the currently active editor.	if (activeEditor_ != NULL)		session.setActiveEditor(activeEditor_->path());}/** * Opens editors based on the locations stored in a session object. * @param  session  The session object to use */void EditorContainer::loadSession(Session& session){	const Core::LocationList& locList = session.editorList();	Core::LocationList::ConstIterator itr;	// Do not handle changes to the active editor while loading.	blockWindowActivation_ = true;	// Open an editor for each location.	for (itr = locList.begin(); itr != locList.end(); ++itr)		gotoLocationInternal(*itr);	// Re-enable handling of changes to active windows.	blockWindowActivation_ = false;	// Activate the previously-active editor.	// We have to call windowActivated() explicitly, in the case the active	// window is the last one to be loaded. In that case, the signal will not	// be emitted.	QString activeEditor = session.activeEditor();	if (!activeEditor.isEmpty()) {		QMdiSubWindow* window = getEditor(activeEditor, true);		windowActivated(window);	}}/** * Creates an editor window with an empty, unnamed file. */void EditorContainer::newFile(){	(void)getEditor(QString(), true);}/** * Prompts the user for a file name, and creates an editor window for editing * the selected file. */void EditorContainer::openFile(){	QString path = QFileDialog::getOpenFileName(0, tr("Open File"));	if (!path.isEmpty())		(void)getEditor(path, true);}/** * Creates an editor window for editing the given file. * @param  path  The path of the file to edit */void EditorContainer::openFile(const QString& path){	if (!path.isEmpty())		(void)getEditor(path, true);}/** * Displays the editor configuration dialogue. * Any changes to the configuration are then applied to all open editor windows. */void EditorContainer::configEditor(){	// Show the "Configure Editor" dialogue.	EditorConfigDialog dlg(config_, this);	if (dlg.exec() == QDialog::Rejected)		return;	// Get the configuration parameters from the dialogue.	dlg.getConfig(config_);	// Store the editor configuration.	QSettings settings;	settings.beginGroup("Editor");	config_.store(settings);	settings.endGroup();	foreach (QMdiSubWindow* window, fileMap_) {		Editor* editor = static_cast<Editor*>(window->widget());		editor->applyConfig(config_);	}}/** * Sets the focus to a line in an editor window matching the given location. * @param  loc  The location to go to */void EditorContainer::gotoLocation(const Core::Location& loc){	// Get the current location.	Core::Location curLoc;	bool addCurrent = false;	if (activeEditor_) {		activeEditor_->getCurrentLocation(curLoc);		addCurrent = true;	}	// Go to the new location.	if (!gotoLocationInternal(loc))		return;	// Add both the previous and the new locations to the history list.	if (addCurrent)		history_.add(curLoc);	history_.add(loc);}/** * Sets the focus to a line in an editor window matching the next location in * the history list. */void EditorContainer::gotoNextLocation(){	Core::Location loc;	if (history_.next(loc))		gotoLocationInternal(loc);}/** * Sets the focus to a line in an editor window matching the previous location * in the history list. */void EditorContainer::gotoPrevLocation(){	Core::Location loc;	if (history_.prev(loc))		gotoLocationInternal(loc);}/** * Shows a list of tags defined in the file of currently-active editor. */void EditorContainer::showLocalTags(){	if (!activeEditor_)		return;	// Create a query view dialogue.	QueryResultDialog* dlg = new QueryResultDialog(this);	dlg->setModal(true);	// Go to selected locations.	Core::QueryView* view = dlg->view();	connect(view, SIGNAL(locationRequested(const Core::Location&)),	        this, SLOT(gotoLocation(const Core::Location&)));	dlg->setWindowTitle(tr("Local Tags"));	dlg->show();	try {		// Run the query.		view->model()->setRootPath(ProjectManager::project()->rootPath());		view->model()->setColumns(ProjectManager::engine()			.queryFields(Core::Query::LocalTags));		ProjectManager::engine().query(view,		                               Core::Query(Core::Query::LocalTags,		                                           activeEditor_->path()));	}	catch (Core::Exception* e) {		e->showMessage();		delete e;	}}/** * Shows a dialogue with the list of recently visited locations. */void EditorContainer::browseHistory(){	// Construct the dialogue.	QueryResultDialog dlg(this);	dlg.setWindowTitle(tr("Location History"));	// Add location history entries to the model.	Core::QueryView* view = dlg.view();	view->model()->add(history_.list(), QModelIndex());	view->resizeColumns();	// Setup the model's displayed columns.	QList<Core::Location::Fields> columns;	columns << Core::Location::File << Core::Location::Line	        << Core::Location::Text;	view->model()->setColumns(columns);	try {		// Set the root path.		view->model()->setRootPath(ProjectManager::project()->rootPath());	}	catch (Core::Exception* e) {		e->showMessage();		delete e;	}	// Go to selected locations.	connect(view, SIGNAL(locationRequested(const Core::Location&)),	        this, SLOT(gotoLocation(const Core::Location&)));	// Display the dialogue.	dlg.exec();}/** * Finds an editor window for the given file. * If one does not exist, a new one is created. * @param  path      The path of the file to edit * @param  activate  Whether to also activate the window * @return The found/created editor if successful, NULL otherwise */QMdiSubWindow* EditorContainer::getEditor(const QString& path, bool activate){	// Try to find an existing editor window, based on the path.	QMap<QString, QMdiSubWindow*>::Iterator itr = fileMap_.find(path);	if (itr != fileMap_.end()) {		if (activate)			activateEditor(*itr);		return *itr;	}	// Create a new editor widget.	Editor* editor = new Editor(this);	// Open the given file in the editor.	QString name;	if (!path.isEmpty()) {		if (!editor->load(path)) {			delete editor;			return NULL;		}		name = path;	}	else {		// No path supplied, treat as a new file.		name = QString("Untitled %1").arg(newFileIndex_++);	}	editor->applyConfig(config_);	connect(editor, SIGNAL(closed(const QString&)), this,	        SLOT(editorClosed(const QString&)));	// Create a new sub window for the editor.	QMdiSubWindow* window = addSubWindow(editor);	window->setAttribute(Qt::WA_DeleteOnClose);	window->setWindowTitle(name);	fileMap_[name] = window;	if (activate)		activateEditor(window);	return window;}/** * Closes all editor windows. */void EditorContainer::closeAll(){	// Prompt the user for unsaved changes.	if (!canClose())		return;	// Do not handle changes to the active editor while closing.	blockWindowActivation_ = true;	// Delete all editor windows.	foreach (QMdiSubWindow* window, fileMap_)		delete window;	fileMap_.clear();	// No active editor.	activeEditor_ = NULL;	emit hasActiveEditor(false);	// Re-enable handling of changes to active windows.	blockWindowActivation_ = false;}/** * Makes the given window the active one. * Shows the window and sets the focus to the editor. * @param  window  The window to activate */void EditorContainer::activateEditor(QMdiSubWindow* window){	window->show();	static_cast<Editor*>(window->widget())->setFocus();}/** * Activates an editor window showing the given location. * The file, line and column values of the Location structure are used to open * an editor for the given file (or activate an existing one), and to set the * cursor to the requested coordinates. * @param  loc  The requested location * @return true if successful, false otherwise */bool EditorContainer::gotoLocationInternal(const Core::Location& loc){	QMdiSubWindow* window;	Editor* editor;	// Open/activate an editor window for the requested file.	window = getEditor(loc.file_, true);	if (!window)		return false;	// Set the cursor to the given line and column.	editor = static_cast<Editor*>(window->widget());	editor->setCursorPosition(loc.line_, loc.column_);	return true;}/** * Common handler for the file names in the "Window" menu. * Activates the window corresponding to the chosen file. * @param  action  The triggered action */void EditorContainer::handleWindowAction(QAction* action){	(void)getEditor(action->text(), true);}/** * Emits the hasActiveEditor() signal whenever the active window changes. * Note that this slot is activated whenever the active sub-window changes, * which includes cases where the application or MDI-area lose focus. However, * this method is only concerned with changes to the current editor, so the * parameter is ignored, and instead the method invokes currentSubWindow() to * check if the current window has indeed changed. * @param  window  Ignored */void EditorContainer::windowActivated(QMdiSubWindow* window){	if (blockWindowActivation_)		return;	// Get the new active editor widget, if any.	window = currentSubWindow();	Editor* editor = window ? static_cast<Editor*>(window->widget()) : NULL;	if (editor == activeEditor_)		return;	// Stop forwarding signals to the active editor.	if (activeEditor_)		disconnect(activeEditor_);	// Update the active editor.	activeEditor_ = editor;	qDebug() << "Active editor" << (activeEditor_ ? activeEditor_->path() : "");	if (activeEditor_) {		// Forward signals.		connect(this, SIGNAL(find()), activeEditor_, SLOT(search()));		connect(this, SIGNAL(findNext()), activeEditor_,		        SLOT(searchNext()));		emit hasActiveEditor(true);	}	else {		emit hasActiveEditor(false);	}}/** * Removes an editor from the file map when its window is closed. * @param  path  The path of the file edited in the closed window */void EditorContainer::editorClosed(const QString& path){	fileMap_.remove(path);	qDebug() << path << "removed";}} // namespace App} // namespace KScope

⌨️ 快捷键说明

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