diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h index 799d0bd729d211a29929e90eb98591696ae4caa7..eeb288c5997afb4148c957451ec8211bab5de729 100644 --- a/src/plugins/coreplugin/coreconstants.h +++ b/src/plugins/coreplugin/coreconstants.h @@ -225,6 +225,7 @@ const char * const WIZARD_TR_CATEGORY_QT = QT_TRANSLATE_NOOP("Core", "Qt"); const char * const SETTINGS_CATEGORY_CORE = "A.Core"; const char * const SETTINGS_TR_CATEGORY_CORE = QT_TRANSLATE_NOOP("Core", "Environment"); +const char * const SETTINGS_ID_ENVIRONMENT = "A.General"; } // namespace Constants } // namespace Core diff --git a/src/plugins/coreplugin/generalsettings.cpp b/src/plugins/coreplugin/generalsettings.cpp index 319f4d225ce1b1da4659ec57ca44224532a27bd2..a733a3b03df89bd9949b2f47894167234d928782 100644 --- a/src/plugins/coreplugin/generalsettings.cpp +++ b/src/plugins/coreplugin/generalsettings.cpp @@ -59,7 +59,7 @@ GeneralSettings::GeneralSettings(): QString GeneralSettings::id() const { - return QLatin1String("A.General"); + return QLatin1String(Core::Constants::SETTINGS_ID_ENVIRONMENT); } QString GeneralSettings::displayName() const diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp index 3a766b2b374b40705c86ddb75149472c89b7f933..37b7563516727f95f4e3f9464a82b6bacea25f0f 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.cpp +++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp @@ -30,18 +30,24 @@ #include "foldernavigationwidget.h" #include "projectexplorer.h" #include "projectexplorerconstants.h" +#include "environment.h" #include <coreplugin/icore.h> #include <coreplugin/filemanager.h> #include <coreplugin/editormanager/editormanager.h> +#include <coreplugin/coreconstants.h> #include <utils/pathchooser.h> #include <utils/qtcassert.h> +#include <utils/unixutils.h> +#include <utils/consoleprocess.h> #include <QtCore/QDebug> +#include <QtCore/QProcess> #include <QtGui/QFileSystemModel> #include <QtGui/QVBoxLayout> #include <QtGui/QToolButton> +#include <QtGui/QPushButton> #include <QtGui/QLabel> #include <QtGui/QListView> #include <QtGui/QSortFilterProxyModel> @@ -49,6 +55,7 @@ #include <QtGui/QMenu> #include <QtGui/QFileDialog> #include <QtGui/QContextMenuEvent> +#include <QtGui/QMessageBox> enum { debug = 0 }; @@ -263,8 +270,14 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev) QMenu menu; // Open current item const QModelIndex current = currentItem(); + const bool hasCurrentItem = current.isValid(); QAction *actionOpen = menu.addAction(actionOpenText(m_fileSystemModel, current)); - actionOpen->setEnabled(current.isValid()); + actionOpen->setEnabled(hasCurrentItem); + // Explorer & teminal + QAction *actionExplorer = menu.addAction(msgGraphicalShellAction()); + actionExplorer->setEnabled(hasCurrentItem); + QAction *actionTerminal = menu.addAction(msgTerminalAction()); + actionTerminal->setEnabled(hasCurrentItem); // Open file dialog to choose a path starting from current QAction *actionChooseFolder = menu.addAction(tr("Choose folder...")); @@ -281,7 +294,114 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev) const QString newPath = QFileDialog::getExistingDirectory(this, tr("Choose folder"), currentDirectory()); if (!newPath.isEmpty()) setCurrentDirectory(newPath); + return; + } + if (action == actionTerminal) { + openTerminal(m_fileSystemModel->filePath(current)); + return; + } + if (action == actionExplorer) { + showInGraphicalShell(this, m_fileSystemModel->filePath(current)); + return; + } +} + +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) +{ + Q_UNUSED(parent) + // Mac, Windows support folder or file. +#if defined(Q_OS_WIN) + const QString explorer = 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; } + QProcess::startDetached(explorer, QStringList(QLatin1String("/select,") + QDir::toNativeSeparators(pathIn))); +#elif defined(Q_OS_MAC) + 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.absolutePath(); + 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 +#else + QStringList args = Utils::ConsoleProcess::terminalEmulator( + Core::ICore::instance()->settings()).split(QLatin1Char(' ')); + 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 diff --git a/src/plugins/projectexplorer/foldernavigationwidget.h b/src/plugins/projectexplorer/foldernavigationwidget.h index 07b3f558de93770443b82cd6c50ad239685af510..79f099d7cf82394f533cd9f284d6c53e46ba3f2e 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.h +++ b/src/plugins/projectexplorer/foldernavigationwidget.h @@ -60,7 +60,12 @@ public: bool autoSynchronization() const; void setAutoSynchronization(bool sync); - QString currentFolder() 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 toggleAutoSynchronization(); diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 16e5b53019514d2f268a27836766b0fe65d5142f..ce65dabd9028e0f8d1c34b48b7403e96886972d6 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -86,7 +86,6 @@ #include <utils/consoleprocess.h> #include <utils/qtcassert.h> #include <utils/parameteraction.h> -#include <utils/unixutils.h> #include <QtCore/QtPlugin> #include <QtCore/QDateTime> @@ -489,24 +488,13 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er globalcontext); mfilec->addAction(cmd, Constants::G_FILE_OPEN); -#if defined(Q_OS_WIN) - d->m_showInGraphicalShell = new QAction(tr("Show in Explorer..."), this); -#elif defined(Q_OS_MAC) - d->m_showInGraphicalShell = new QAction(tr("Show in Finder..."), this); -#else - d->m_showInGraphicalShell = new QAction(tr("Show containing folder..."), this); -#endif - -#ifdef Q_OS_WIN - d->m_openTerminalHere = new QAction(tr("Open Command Prompt here..."), this); -#else - d->m_openTerminalHere = new QAction(tr("Open Terminal here..."), this); -#endif + d->m_showInGraphicalShell = new QAction(FolderNavigationWidget::msgGraphicalShellAction(), this); cmd = am->registerAction(d->m_showInGraphicalShell, ProjectExplorer::Constants::SHOWINGRAPHICALSHELL, globalcontext); mfilec->addAction(cmd, Constants::G_FILE_OPEN); mfolder->addAction(cmd, Constants::G_FOLDER_FILES); + d->m_openTerminalHere = new QAction(FolderNavigationWidget::msgTerminalAction(), this); cmd = am->registerAction(d->m_openTerminalHere, ProjectExplorer::Constants::OPENTERMIANLHERE, globalcontext); mfilec->addAction(cmd, Constants::G_FILE_OPEN); @@ -1895,71 +1883,17 @@ void ProjectExplorerPlugin::openFile() em->ensureEditorManagerVisible(); } -void ProjectExplorerPlugin::graphicalShellHasError(const QString &app, const QString &error) -{ - QWidget *w = Core::ICore::instance()->mainWindow(); - QMessageBox mbox(w); - mbox.setIcon(QMessageBox::Warning); - mbox.setWindowTitle(tr("Launching a file browser failed")); - mbox.setText(tr("Unable to start the file manager:\n\n%1\n\n" - "Do you want to change the current file manager?").arg(app)); - if (!error.isEmpty()) { - mbox.setDetailedText(tr("'%1' returned the following error:\n\n%2").arg(app, error)); - } - if (mbox.exec() == QMessageBox::Accepted) - Core::ICore::instance()->showOptionsDialog("environment", QString(), w); -} - void ProjectExplorerPlugin::showInGraphicalShell() { QTC_ASSERT(d->m_currentNode, return) -#if defined(Q_OS_WIN) - const QString explorer = Environment::systemEnvironment().searchInPath("explorer.exe"); - if (explorer.isEmpty()) { - QMessageBox::warning(Core::ICore::instance()->mainWindow(), - tr("Launching Windows Explorer failed"), - tr("Could not find explorer.exe in path to launch Windows Explorer.")); - return; - } - QProcess::startDetached(explorer, QStringList(QLatin1String("/select,") + QDir::toNativeSeparators(d->m_currentNode->path()))); -#elif defined(Q_OS_MAC) - QProcess::execute("/usr/bin/osascript", QStringList() - << "-e" - << QString("tell application \"Finder\" to reveal POSIX file \"%1\"") - .arg(d->m_currentNode->path())); - QProcess::execute("/usr/bin/osascript", QStringList() - << "-e" - << "tell application \"Finder\" to activate"); -#else - // we cannot select a file here, because no file browser really supports it... - const QFileInfo fileInfo(d->m_currentNode->path()); - QString app = Utils::UnixUtils::fileBrowser(Core::ICore::instance()->settings()); - QProcess browserProc; - bool success = browserProc.startDetached(Utils::UnixUtils::substituteFileBrowserParameters(app, fileInfo.filePath())); - QString error = QString::fromLocal8Bit(browserProc.readAllStandardError()); - success = success && error.isEmpty(); - if (!success) { - graphicalShellHasError(app, error); - } -#endif + FolderNavigationWidget::showInGraphicalShell(Core::ICore::instance()->mainWindow(), + d->m_currentNode->path()); } void ProjectExplorerPlugin::openTerminalHere() { -#ifdef Q_OS_WIN - const QString terminalEmulator = QString::fromLocal8Bit(qgetenv("COMSPEC")); - const QStringList args; // none -#else - QStringList args = Utils::ConsoleProcess::terminalEmulator( - Core::ICore::instance()->settings()).split(QLatin1Char(' ')); - const QString terminalEmulator = args.takeFirst(); - const QString shell = QString::fromLocal8Bit(qgetenv("SHELL")); - args.append(shell); -#endif - const QFileInfo fileInfo(d->m_currentNode->path()); - const QString pwd = QDir::toNativeSeparators(fileInfo.path()); - QProcess::startDetached(terminalEmulator, args, pwd); - + QTC_ASSERT(d->m_currentNode, return) + FolderNavigationWidget::openTerminal(d->m_currentNode->path()); } void ProjectExplorerPlugin::removeFile() diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h index c4d647986a3e2434b8f49c94e2efaa6a2af146c3..73859fb83e382964670e786deca89e2f647c4b96 100644 --- a/src/plugins/projectexplorer/projectexplorer.h +++ b/src/plugins/projectexplorer/projectexplorer.h @@ -217,7 +217,6 @@ private slots: void currentModeChanged(Core::IMode *mode); private: - void graphicalShellHasError(const QString &app, const QString &error); void runProjectImpl(Project *pro, QString mode); void executeRunConfiguration(RunConfiguration *, const QString &mode); bool showBuildConfigDialog();