Commit 73854476 authored by Robert Loehning's avatar Robert Loehning Committed by Eike Ziller
Browse files

Improved editor menus

Access native filemanager and terminal from Open documents view
and Editor menu

Task-number: QTCREATORBUG-389

Change-Id: Id6cd8839cdbd270a4ac53ccad1ae1db94d48e900
Reviewed-on: http://codereview.qt.nokia.com/2974

Reviewed-by: default avatarQt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: default avatarEike Ziller <eike.ziller@nokia.com>
parent d2911d70
......@@ -90,7 +90,8 @@ SOURCES += mainwindow.cpp \
variablechooser.cpp \
mimetypemagicdialog.cpp \
mimetypesettings.cpp \
dialogs/promptoverwritedialog.cpp
dialogs/promptoverwritedialog.cpp \
fileutils.cpp
HEADERS += mainwindow.h \
editmode.h \
......@@ -182,7 +183,8 @@ HEADERS += mainwindow.h \
variablechooser.h \
mimetypemagicdialog.h \
mimetypesettings.h \
dialogs/promptoverwritedialog.h
dialogs/promptoverwritedialog.h \
fileutils.h
FORMS += dialogs/newdialog.ui \
actionmanager/commandmappings.ui \
......
......@@ -58,6 +58,7 @@
#include <coreplugin/settingsdatabase.h>
#include <coreplugin/variablemanager.h>
#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/fileutils.h>
#include <extensionsystem/pluginmanager.h>
......@@ -217,6 +218,8 @@ struct EditorManagerPrivate {
QAction *m_closeCurrentEditorContextAction;
QAction *m_closeAllEditorsContextAction;
QAction *m_closeOtherEditorsContextAction;
QAction *m_openGraphicalShellAction;
QAction *m_openTerminalAction;
QModelIndex m_contextMenuEditorIndex;
Internal::OpenEditorsWindow *m_windowPopup;
......@@ -254,6 +257,8 @@ EditorManagerPrivate::EditorManagerPrivate(ICore *core, QWidget *parent) :
m_closeCurrentEditorContextAction(new QAction(EditorManager::tr("Close"), parent)),
m_closeAllEditorsContextAction(new QAction(EditorManager::tr("Close All"), parent)),
m_closeOtherEditorsContextAction(new QAction(EditorManager::tr("Close Others"), parent)),
m_openGraphicalShellAction(new QAction(FileUtils::msgGraphicalShellAction(), parent)),
m_openTerminalAction(new QAction(FileUtils::msgTerminalAction(), parent)),
m_windowPopup(0),
m_coreListener(0),
m_reloadSetting(IFile::AlwaysAsk),
......@@ -361,6 +366,9 @@ EditorManager::EditorManager(ICore *core, QWidget *parent) :
connect(m_d->m_closeCurrentEditorContextAction, SIGNAL(triggered()), this, SLOT(closeEditorFromContextMenu()));
connect(m_d->m_closeOtherEditorsContextAction, SIGNAL(triggered()), this, SLOT(closeOtherEditorsFromContextMenu()));
connect(m_d->m_openGraphicalShellAction, SIGNAL(triggered()), this, SLOT(showInGraphicalShell()));
connect(m_d->m_openTerminalAction, SIGNAL(triggered()), this, SLOT(openTerminal()));
// Goto Previous In History Action
cmd = am->registerAction(m_d->m_gotoPreviousDocHistoryAction, Constants::GOTOPREVINHISTORY, editDesignContext);
#ifdef Q_WS_MAC
......@@ -782,6 +790,15 @@ void EditorManager::addCloseEditorActions(QMenu *contextMenu, const QModelIndex
contextMenu->addAction(m_d->m_closeOtherEditorsContextAction);
}
void EditorManager::addNativeDirActions(QMenu *contextMenu, const QModelIndex &editorIndex)
{
QTC_ASSERT(contextMenu, return);
m_d->m_openGraphicalShellAction->setEnabled(editorIndex.isValid());
m_d->m_openTerminalAction->setEnabled(editorIndex.isValid());
contextMenu->addAction(m_d->m_openGraphicalShellAction);
contextMenu->addAction(m_d->m_openTerminalAction);
}
void EditorManager::closeEditorFromContextMenu()
{
closeEditor(m_d->m_contextMenuEditorIndex);
......@@ -792,6 +809,18 @@ void EditorManager::closeOtherEditorsFromContextMenu()
closeOtherEditors(m_d->m_contextMenuEditorIndex.data(Qt::UserRole).value<IEditor *>());
}
void EditorManager::showInGraphicalShell()
{
const QString path = m_d->m_contextMenuEditorIndex.data(Qt::UserRole + 1).toString();
Core::Internal::FileUtils::showInGraphicalShell(ICore::instance()->mainWindow(), path);
}
void EditorManager::openTerminal()
{
const QString path = QFileInfo(m_d->m_contextMenuEditorIndex.data(Qt::UserRole + 1).toString()).path();
Core::Internal::FileUtils::openTerminal(path);
}
void EditorManager::closeEditor(Core::IEditor *editor)
{
if (!editor)
......
......@@ -192,6 +192,7 @@ public:
QString windowTitleAddition() const;
void addCloseEditorActions(QMenu *contextMenu, const QModelIndex &editorIndex);
void addNativeDirActions(QMenu *contextMenu, const QModelIndex &editorIndex);
signals:
void currentEditorChanged(Core::IEditor *editor);
......@@ -225,6 +226,9 @@ private slots:
void closeEditorFromContextMenu();
void closeOtherEditorsFromContextMenu();
void showInGraphicalShell();
void openTerminal();
public slots:
void goBackInNavigationHistory();
void goForwardInNavigationHistory();
......
......@@ -205,7 +205,10 @@ void OpenEditorsWidget::closeEditor(const QModelIndex &index)
void OpenEditorsWidget::contextMenuRequested(QPoint pos)
{
QMenu contextMenu;
EditorManager::instance()->addCloseEditorActions(&contextMenu, m_ui.editorList->indexAt(pos));
QModelIndex editorIndex = m_ui.editorList->indexAt(pos);
EditorManager::instance()->addCloseEditorActions(&contextMenu, editorIndex);
contextMenu.addSeparator();
EditorManager::instance()->addNativeDirActions(&contextMenu, editorIndex);
contextMenu.exec(m_ui.editorList->mapToGlobal(pos));
}
......
......@@ -290,7 +290,10 @@ void EditorToolBar::listContextMenu(QPoint pos)
return;
QMenu menu;
QAction *copyPath = menu.addAction(tr("Copy Full Path to Clipboard"));
menu.addSeparator();
EditorManager::instance()->addCloseEditorActions(&menu, index);
menu.addSeparator();
EditorManager::instance()->addNativeDirActions(&menu, index);
QAction *result = menu.exec(d->m_editorList->mapToGlobal(pos));
if (result == copyPath) {
QApplication::clipboard()->setText(QDir::toNativeSeparators(fileName));
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#include "fileutils.h"
#include <utils/environment.h>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QProcess>
#include <QtGui/QApplication>
#include <QtGui/QMessageBox>
#include <QtGui/QWidget>
#ifndef Q_OS_WIN
#include <coreplugin/icore.h>
#include <utils/consoleprocess.h>
#include <utils/qtcprocess.h>
#ifndef Q_OS_MAC
#include <coreplugin/coreconstants.h>
#include <utils/unixutils.h>
#include <QtGui/QPushButton>
#endif
#endif
using namespace Core::Internal;
#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC)
// Show error with option to open settings.
static inline void showGraphicalShellError(QWidget *parent,
const QString &app,
const QString &error)
{
const QString title = QApplication::translate("Core::Internal",
"Launching a file browser failed");
const QString msg = QApplication::translate("Core::Internal",
"Unable to start the file manager:\n\n%1\n\n").arg(app);
QMessageBox mbox(QMessageBox::Warning, title, msg, QMessageBox::Close, parent);
if (!error.isEmpty())
mbox.setDetailedText(QApplication::translate("Core::Internal",
"'%1' returned the following error:\n\n%2").arg(app, error));
QAbstractButton *settingsButton = mbox.addButton(QApplication::translate("Core::Internal", "Settings..."),
QMessageBox::ActionRole);
mbox.exec();
if (mbox.clickedButton() == settingsButton)
Core::ICore::instance()->showOptionsDialog(QLatin1String(Core::Constants::SETTINGS_CATEGORY_CORE),
QLatin1String(Core::Constants::SETTINGS_ID_ENVIRONMENT));
}
#endif
void FileUtils::showInGraphicalShell(QWidget *parent, const QString &pathIn)
{
// Mac, Windows support folder or file.
#if defined(Q_OS_WIN)
const QString explorer = Utils::Environment::systemEnvironment().searchInPath(QLatin1String("explorer.exe"));
if (explorer.isEmpty()) {
QMessageBox::warning(parent,
QApplication::translate("Core::Internal",
"Launching Windows Explorer Failed"),
QApplication::translate("Core::Internal",
"Could not find explorer.exe in path to launch Windows Explorer."));
return;
}
QString param;
if (!QFileInfo(pathIn).isDir())
param = QLatin1String("/select,");
param += QDir::toNativeSeparators(pathIn);
QProcess::startDetached(explorer, QStringList(param));
#elif defined(Q_OS_MAC)
Q_UNUSED(parent)
QStringList scriptArgs;
scriptArgs << QLatin1String("-e")
<< QString::fromLatin1("tell application \"Finder\" to reveal POSIX file \"%1\"")
.arg(pathIn);
QProcess::execute(QLatin1String("/usr/bin/osascript"), scriptArgs);
scriptArgs.clear();
scriptArgs << QLatin1String("-e")
<< QLatin1String("tell application \"Finder\" to activate");
QProcess::execute("/usr/bin/osascript", scriptArgs);
#else
// we cannot select a file here, because no file browser really supports it...
const QFileInfo fileInfo(pathIn);
const QString folder = fileInfo.isDir() ? fileInfo.absoluteFilePath() : fileInfo.filePath();
const QString app = Utils::UnixUtils::fileBrowser(Core::ICore::instance()->settings());
QProcess browserProc;
const QString browserArgs = Utils::UnixUtils::substituteFileBrowserParameters(app, folder);
bool success = browserProc.startDetached(browserArgs);
const QString error = QString::fromLocal8Bit(browserProc.readAllStandardError());
success = success && error.isEmpty();
if (!success)
showGraphicalShellError(parent, app, error);
#endif
}
void FileUtils::openTerminal(const QString &path)
{
// Get terminal application
#ifdef Q_OS_WIN
const QString terminalEmulator = QString::fromLocal8Bit(qgetenv("COMSPEC"));
const QStringList args; // none
#elif defined(Q_WS_MAC)
const QString terminalEmulator = Core::ICore::instance()->resourcePath()
+ QLatin1String("/scripts/openTerminal.command");
QStringList args;
#else
QStringList args = Utils::QtcProcess::splitArgs(
Utils::ConsoleProcess::terminalEmulator(Core::ICore::instance()->settings()));
const QString terminalEmulator = args.takeFirst();
const QString shell = QString::fromLocal8Bit(qgetenv("SHELL"));
args.append(shell);
#endif
// Launch terminal with working directory set.
const QFileInfo fileInfo(path);
const QString pwd = QDir::toNativeSeparators(fileInfo.isDir() ?
fileInfo.absoluteFilePath() :
fileInfo.absolutePath());
QProcess::startDetached(terminalEmulator, args, pwd);
}
QString FileUtils::msgGraphicalShellAction()
{
#if defined(Q_OS_WIN)
return QApplication::translate("Core::Internal", "Show in Explorer...");
#elif defined(Q_OS_MAC)
return QApplication::translate("Core::Internal", "Show in Finder...");
#else
return QApplication::translate("Core::Internal", "Show Containing Folder...");
#endif
}
QString FileUtils::msgTerminalAction()
{
#ifdef Q_OS_WIN
return QApplication::translate("Core::Internal", "Open Command Prompt Here...");
#else
return QApplication::translate("Core::Internal", "Open Terminal Here...");
#endif
}
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/
#ifndef FILEUTILS_H
#define FILEUTILS_H
#include "coreplugin/core_global.h"
class QWidget;
namespace Core {
namespace Internal {
struct CORE_EXPORT FileUtils
{
// Helpers for common directory browser options.
static void showInGraphicalShell(QWidget *parent, const QString &path);
static void openTerminal(const QString &path);
// Platform-dependent action descriptions
static QString msgGraphicalShellAction();
static QString msgTerminalAction();
};
} // namespace Internal
} // namespace Core
#endif // FILEUTILS_H
......@@ -39,16 +39,12 @@
#include <coreplugin/filemanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/fileutils.h>
#include <utils/environment.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/unixutils.h>
#include <utils/consoleprocess.h>
#include <QtCore/QDebug>
#include <QtCore/QProcess>
#include <QtCore/QSize>
#include <QtGui/QFileSystemModel>
#include <QtGui/QVBoxLayout>
......@@ -61,7 +57,6 @@
#include <QtGui/QMenu>
#include <QtGui/QFileDialog>
#include <QtGui/QContextMenuEvent>
#include <QtGui/QMessageBox>
enum { debug = 0 };
......@@ -312,9 +307,9 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev)
QAction *actionOpen = menu.addAction(actionOpenText(m_fileSystemModel, current));
actionOpen->setEnabled(hasCurrentItem);
// Explorer & teminal
QAction *actionExplorer = menu.addAction(msgGraphicalShellAction());
QAction *actionExplorer = menu.addAction(Core::Internal::FileUtils::msgGraphicalShellAction());
actionExplorer->setEnabled(hasCurrentItem);
QAction *actionTerminal = menu.addAction(msgTerminalAction());
QAction *actionTerminal = menu.addAction(Core::Internal::FileUtils::msgTerminalAction());
actionTerminal->setEnabled(hasCurrentItem);
// open with...
......@@ -343,123 +338,17 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev)
return;
}
if (action == actionTerminal) {
openTerminal(m_fileSystemModel->filePath(current));
Core::Internal::FileUtils::openTerminal(m_fileSystemModel->filePath(current));
return;
}
if (action == actionExplorer) {
showInGraphicalShell(this, m_fileSystemModel->filePath(current));
Core::Internal::FileUtils::showInGraphicalShell(this, m_fileSystemModel->filePath(current));
return;
}
ProjectExplorerPlugin::openEditorFromAction(action,
m_fileSystemModel->filePath(current));
}
QString FolderNavigationWidget::msgGraphicalShellAction()
{
#if defined(Q_OS_WIN)
return tr("Show in Explorer...");
#elif defined(Q_OS_MAC)
return tr("Show in Finder...");
#else
return tr("Show Containing Folder...");
#endif
}
QString FolderNavigationWidget::msgTerminalAction()
{
#ifdef Q_OS_WIN
return tr("Open Command Prompt Here...");
#else
return tr("Open Terminal Here...");
#endif
}
// Show error with option to open settings.
static inline void showGraphicalShellError(QWidget *parent,
const QString &app,
const QString &error)
{
const QString title = FolderNavigationWidget::tr("Launching a file browser failed");
const QString msg = FolderNavigationWidget::tr("Unable to start the file manager:\n\n%1\n\n").arg(app);
QMessageBox mbox(QMessageBox::Warning, title, msg, QMessageBox::Close, parent);
if (!error.isEmpty())
mbox.setDetailedText(FolderNavigationWidget::tr("'%1' returned the following error:\n\n%2").arg(app, error));
QAbstractButton *settingsButton = mbox.addButton(FolderNavigationWidget::tr("Settings..."), QMessageBox::ActionRole);
mbox.exec();
if (mbox.clickedButton() == settingsButton)
Core::ICore::instance()->showOptionsDialog(QLatin1String(Core::Constants::SETTINGS_CATEGORY_CORE),
QLatin1String(Core::Constants::SETTINGS_ID_ENVIRONMENT));
}
void FolderNavigationWidget::showInGraphicalShell(QWidget *parent, const QString &pathIn)
{
// Mac, Windows support folder or file.
#if defined(Q_OS_WIN)
const QString explorer = Utils::Environment::systemEnvironment().searchInPath(QLatin1String("explorer.exe"));
if (explorer.isEmpty()) {
QMessageBox::warning(parent,
tr("Launching Windows Explorer Failed"),
tr("Could not find explorer.exe in path to launch Windows Explorer."));
return;
}
QString param;
if (!QFileInfo(pathIn).isDir())
param = QLatin1String("/select,");
param += QDir::toNativeSeparators(pathIn);
QProcess::startDetached(explorer, QStringList(param));
#elif defined(Q_OS_MAC)
Q_UNUSED(parent)
QStringList scriptArgs;
scriptArgs << QLatin1String("-e")
<< QString::fromLatin1("tell application \"Finder\" to reveal POSIX file \"%1\"")
.arg(pathIn);
QProcess::execute(QLatin1String("/usr/bin/osascript"), scriptArgs);
scriptArgs.clear();
scriptArgs << QLatin1String("-e")
<< QLatin1String("tell application \"Finder\" to activate");
QProcess::execute("/usr/bin/osascript", scriptArgs);
#else
// we cannot select a file here, because no file browser really supports it...
const QFileInfo fileInfo(pathIn);
const QString folder = fileInfo.isDir() ? fileInfo.absoluteFilePath() : fileInfo.filePath();
const QString app = Utils::UnixUtils::fileBrowser(Core::ICore::instance()->settings());
QProcess browserProc;
const QString browserArgs = Utils::UnixUtils::substituteFileBrowserParameters(app, folder);
if (debug)
qDebug() << browserArgs;
bool success = browserProc.startDetached(browserArgs);
const QString error = QString::fromLocal8Bit(browserProc.readAllStandardError());
success = success && error.isEmpty();
if (!success)
showGraphicalShellError(parent, app, error);
#endif
}
void FolderNavigationWidget::openTerminal(const QString &path)
{
// Get terminal application
#ifdef Q_OS_WIN
const QString terminalEmulator = QString::fromLocal8Bit(qgetenv("COMSPEC"));
const QStringList args; // none
#elif defined(Q_WS_MAC)
const QString terminalEmulator = Core::ICore::instance()->resourcePath()
+ QLatin1String("/scripts/openTerminal.command");
QStringList args;
#else
QStringList args = Utils::QtcProcess::splitArgs(
Utils::ConsoleProcess::terminalEmulator(Core::ICore::instance()->settings()));
const QString terminalEmulator = args.takeFirst();
const QString shell = QString::fromLocal8Bit(qgetenv("SHELL"));
args.append(shell);
#endif
// Launch terminal with working directory set.
const QFileInfo fileInfo(path);
const QString pwd = QDir::toNativeSeparators(fileInfo.isDir() ?
fileInfo.absoluteFilePath() :
fileInfo.absolutePath());
QProcess::startDetached(terminalEmulator, args, pwd);
}
// --------------------FolderNavigationWidgetFactory
FolderNavigationWidgetFactory::FolderNavigationWidgetFactory()
{
......
......@@ -64,14 +64,6 @@ public:
bool autoSynchronization() const;
// Helpers for common directory browser options.
static void showInGraphicalShell(QWidget *parent, const QString &path);
static void openTerminal(const QString &path);
// Platform-dependent action descriptions
static QString msgGraphicalShellAction();
static QString msgTerminalAction();
public slots:
void setAutoSynchronization(bool sync);
void toggleAutoSynchronization();
......
......@@ -107,6 +107,7 @@
#include <coreplugin/vcsmanager.h>
#include <coreplugin/iversioncontrol.h>
#include <coreplugin/variablemanager.h>
#include <coreplugin/fileutils.h>
#include <extensionsystem/pluginmanager.h>
#include <find/searchresultwindow.h>
#include <utils/consoleprocess.h>
......@@ -583,13 +584,13 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
projecTreeContext);
mfileContextMenu->addAction(cmd, Constants::G_FILE_OPEN);
d->m_showInGraphicalShell = new QAction(FolderNavigationWidget::msgGraphicalShellAction(), this);
d->m_showInGraphicalShell = new QAction(Core::Internal::FileUtils::msgGraphicalShellAction(), this);
cmd = am->registerAction(d->m_showInGraphicalShell, ProjectExplorer::Constants::SHOWINGRAPHICALSHELL,
projecTreeContext);
mfileContextMenu->addAction(cmd, Constants::G_FILE_OPEN);
mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
d->m_openTerminalHere = new QAction(FolderNavigationWidget::msgTerminalAction(), this);
d->m_openTerminalHere = new QAction(Core::Internal::FileUtils::msgTerminalAction(), this);
cmd = am->registerAction(d->m_openTerminalHere, ProjectExplorer::Constants::OPENTERMIANLHERE,
projecTreeContext);
mfileContextMenu->addAction(cmd, Constants::G_FILE_OPEN);
......@@ -2524,14 +2525,14 @@ void ProjectExplorerPlugin::openFile()
void ProjectExplorerPlugin::showInGraphicalShell()
{
QTC_ASSERT(d->m_currentNode, return)
FolderNavigationWidget::showInGraphicalShell(Core::ICore::instance()->mainWindow(),
pathFor(d->m_currentNode));
Core::Internal::FileUtils::showInGraphicalShell(Core::ICore::instance()->mainWindow(),
pathFor(d->m_currentNode));
}
void ProjectExplorerPlugin::openTerminalHere()
{
QTC_ASSERT(d->m_currentNode, return)
FolderNavigationWidget::openTerminal(directoryFor(d->m_currentNode));
Core::Internal::FileUtils::openTerminal(directoryFor(d->m_currentNode));
}
void ProjectExplorerPlugin::removeFile()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment