From 2e6c6216fbd6d40610fa5846c7cfcf15beef08dc Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Wed, 11 Nov 2015 21:55:06 -0500 Subject: [PATCH] Bug 481978 - UI to add Qt installs. Installs are now persisted. Change-Id: I1fa75b71615959df314a9aaca5f01e17069ec35f --- .../META-INF/MANIFEST.MF | 3 +- .../qt/core/{build => }/QtInstall.java | 38 ++-- .../internal/qt/core/QtInstallManager.java | 91 +++++++++ .../cdt/internal/qt/core/QtPlugin.java | 10 +- .../qt/core/build/QtBuildConfiguration.java | 12 +- .../qt/core/build/QtInstallManager.java | 46 ----- .../org/eclipse/cdt/qt/core/IQtInstall.java | 30 +++ .../cdt/qt/core/IQtInstallManager.java | 27 +++ qt/org.eclipse.cdt.qt.ui/.classpath | 2 +- .../.settings/org.eclipse.jdt.core.prefs | 6 +- qt/org.eclipse.cdt.qt.ui/META-INF/MANIFEST.MF | 2 +- qt/org.eclipse.cdt.qt.ui/plugin.properties | 2 + qt/org.eclipse.cdt.qt.ui/plugin.xml | 8 + .../eclipse/cdt/internal/qt/ui/Messages.java | 34 ++++ .../cdt/internal/qt/ui/QtUIPlugin.java | 14 +- .../cdt/internal/qt/ui/messages.properties | 19 ++ .../qt/ui/preferences/NewQtInstallWizard.java | 39 ++++ .../preferences/NewQtInstallWizardPage.java | 129 +++++++++++++ .../qt/ui/preferences/QtPreferencePage.java | 174 ++++++++++++++++++ 19 files changed, 613 insertions(+), 73 deletions(-) rename qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/{build => }/QtInstall.java (62%) create mode 100644 qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtInstallManager.java delete mode 100644 qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtInstallManager.java create mode 100644 qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstall.java create mode 100644 qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstallManager.java create mode 100644 qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/Messages.java create mode 100644 qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/messages.properties create mode 100644 qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/NewQtInstallWizard.java create mode 100644 qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/NewQtInstallWizardPage.java create mode 100644 qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/QtPreferencePage.java diff --git a/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF b/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF index 07bf5f4a613..275c3fdc829 100644 --- a/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF +++ b/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF @@ -24,4 +24,5 @@ Export-Package: org.eclipse.cdt.internal.qt.core;x-friends:="org.eclipse.cdt.qt. org.eclipse.cdt.internal.qt.core.build;x-friends:="org.eclipse.cdt.qt.ui", org.eclipse.cdt.internal.qt.core.index;x-friends:="org.eclipse.cdt.qt.ui.tests", org.eclipse.cdt.internal.qt.core.parser;x-friends:="org.eclipse.cdt.qt.ui", - org.eclipse.cdt.internal.qt.core.project;x-friends:="org.eclipse.cdt.qt.ui" + org.eclipse.cdt.internal.qt.core.project;x-friends:="org.eclipse.cdt.qt.ui", + org.eclipse.cdt.qt.core diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtInstall.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtInstall.java similarity index 62% rename from qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtInstall.java rename to qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtInstall.java index 64096ac6071..fd144ffb9e1 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtInstall.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtInstall.java @@ -5,33 +5,43 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ -package org.eclipse.cdt.internal.qt.core.build; +package org.eclipse.cdt.internal.qt.core; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.nio.file.Path; -import org.eclipse.cdt.internal.qt.core.QtPlugin; +import org.eclipse.cdt.qt.core.IQtInstall; import org.eclipse.core.runtime.Platform; -public class QtInstall { +public class QtInstall implements IQtInstall { + private final String name; private final Path qmakePath; private String spec; - public QtInstall(Path qmakePath) { + public QtInstall(String name, Path qmakePath) { + this.name = name; this.qmakePath = qmakePath; } + @Override + public String getName() { + return name; + } + + @Override public Path getQmakePath() { return qmakePath; } + @Override public Path getLibPath() { return qmakePath.resolve("../lib"); //$NON-NLS-1$ } + @Override public boolean supports(String os, String arch) { switch (getSpec()) { case "macx-clang": //$NON-NLS-1$ @@ -42,16 +52,22 @@ public class QtInstall { return false; } + public static String getSpec(String qmakePath) throws IOException { + Process proc = new ProcessBuilder(qmakePath, "-query", "QMAKE_XSPEC").start(); //$NON-NLS-1$ //$NON-NLS-2$ + try (BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()))) { + String line = reader.readLine(); + if (line != null) { + return line.trim(); + } + } + return null; + } + + @Override public String getSpec() { if (spec == null) { try { - Process proc = new ProcessBuilder(getQmakePath().toString(), "-query", "QMAKE_XSPEC").start(); //$NON-NLS-1$ //$NON-NLS-2$ - try (BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()))) { - String line = reader.readLine(); - if (line != null) { - spec = line.trim(); - } - } + spec = getSpec(getQmakePath().toString()); } catch (IOException e) { QtPlugin.log(e); } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtInstallManager.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtInstallManager.java new file mode 100644 index 00000000000..0d4e074b2b9 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtInstallManager.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2015 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.cdt.internal.qt.core; + +import java.nio.file.Paths; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.cdt.qt.core.IQtInstall; +import org.eclipse.cdt.qt.core.IQtInstallManager; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.osgi.service.prefs.BackingStoreException; +import org.osgi.service.prefs.Preferences; + +public class QtInstallManager implements IQtInstallManager { + + private Map installs; + + private Preferences getPreferences() { + return InstanceScope.INSTANCE.getNode(QtPlugin.ID).node("qtInstalls"); //$NON-NLS-1$ + } + + private void initInstalls() { + if (installs == null) { + installs = new HashMap<>(); + try { + Preferences prefs = getPreferences(); + for (String key : prefs.keys()) { + installs.put(key, new QtInstall(key, Paths.get(prefs.get(key, "/")))); //$NON-NLS-1$ + } + } catch (BackingStoreException e) { + QtPlugin.log(e); + } + } + } + + private void saveInstalls() { + try { + Preferences prefs = getPreferences(); + + // Remove ones that aren't valid + for (String key : prefs.keys()) { + if (installs.get(key) == null) { + prefs.remove(key); + } + } + + // Add new ones + for (String key : installs.keySet()) { + if (prefs.get(key, null) == null) { + prefs.put(key, installs.get(key).getQmakePath().toString()); + } + } + } catch (BackingStoreException e) { + QtPlugin.log(e); + } + } + + @Override + public Collection getInstalls() { + initInstalls(); + return Collections.unmodifiableCollection(installs.values()); + } + + @Override + public void addInstall(IQtInstall qt) { + initInstalls(); + installs.put(qt.getName(), qt); + saveInstalls(); + } + + @Override + public IQtInstall getInstall(String name) { + initInstalls(); + return installs.get(name); + } + + @Override + public void removeInstall(IQtInstall install) { + installs.remove(install.getName()); + saveInstalls(); + } + +} diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtPlugin.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtPlugin.java index ddce9d52034..c4d7dfe98f3 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtPlugin.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtPlugin.java @@ -11,6 +11,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.internal.qt.core.index.QMakeProjectInfoManager; +import org.eclipse.cdt.qt.core.IQtInstallManager; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Plugin; @@ -23,8 +24,8 @@ import org.osgi.framework.ServiceReference; public class QtPlugin extends Plugin { - public static final String ID = "org.eclipse.cdt.qt.core"; - public static final String SIGNAL_SLOT_TAGGER_ID = ID + ".signalslot.tagger"; + public static final String ID = "org.eclipse.cdt.qt.core"; //$NON-NLS-1$ + public static final String SIGNAL_SLOT_TAGGER_ID = ID + ".signalslot.tagger"; //$NON-NLS-1$ public static final int SignalSlot_Mask_signal = 1; public static final int SignalSlot_Mask_slot = 2; @@ -39,7 +40,7 @@ public class QtPlugin extends Plugin { * project from which they are created. This name is used to store the * property. */ - public static final QualifiedName QTINDEX_PROP_NAME = new QualifiedName(ID, "qtindex"); + public static final QualifiedName QTINDEX_PROP_NAME = new QualifiedName(ID, "qtindex"); //$NON-NLS-1$ private static QtPlugin instance; @@ -69,6 +70,9 @@ public class QtPlugin extends Plugin { } }; context.addBundleListener(bundleListener); + + context.registerService(IQtInstallManager.class, new QtInstallManager(), null); + super.start(context); } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfiguration.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfiguration.java index 5f07cca71d1..e86c64a4641 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfiguration.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfiguration.java @@ -26,6 +26,8 @@ import org.eclipse.cdt.core.model.ILanguage; import org.eclipse.cdt.core.model.LanguageManager; import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.cdt.internal.qt.core.QtPlugin; +import org.eclipse.cdt.qt.core.IQtInstall; +import org.eclipse.cdt.qt.core.IQtInstallManager; import org.eclipse.core.resources.IBuildConfiguration; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; @@ -37,7 +39,7 @@ import org.eclipse.core.runtime.IProgressMonitor; public class QtBuildConfiguration extends CBuildConfiguration { - private QtInstall qtInstall; + private IQtInstall qtInstall; private String launchMode; private Map properties; @@ -76,14 +78,14 @@ public class QtBuildConfiguration extends CBuildConfiguration { // return it if it exists already for (IBuildConfiguration config : project.getBuildConfigs()) { QtBuildConfiguration qtConfig = config.getAdapter(QtBuildConfiguration.class); - QtInstall qtInstall = qtConfig.getQtInstall(); + IQtInstall qtInstall = qtConfig.getQtInstall(); if (qtInstall != null && qtInstall.supports(os, arch) && launchMode.equals(qtConfig.getLaunchMode())) { return qtConfig; } } // Nope, create it - for (QtInstall qtInstall : QtInstallManager.instance.getInstalls()) { + for (IQtInstall qtInstall : QtPlugin.getService(IQtInstallManager.class).getInstalls()) { if (qtInstall.supports(os, arch)) { Set configNames = new HashSet<>(); for (IBuildConfiguration config : project.getBuildConfigs()) { @@ -108,7 +110,7 @@ public class QtBuildConfiguration extends CBuildConfiguration { return null; } - public QtInstall getQtInstall() { + public IQtInstall getQtInstall() { if (qtInstall == null) { // TODO set based on settings } @@ -122,7 +124,7 @@ public class QtBuildConfiguration extends CBuildConfiguration { return launchMode; } - private void setup(QtInstall qtInstall, String launchMode) { + private void setup(IQtInstall qtInstall, String launchMode) { this.qtInstall = qtInstall; this.launchMode = launchMode; // TODO save settings diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtInstallManager.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtInstallManager.java deleted file mode 100644 index 39d0a56df81..00000000000 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtInstallManager.java +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ -package org.eclipse.cdt.internal.qt.core.build; - -import java.io.File; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.core.runtime.Platform; - -public class QtInstallManager { - - public static final QtInstallManager instance = new QtInstallManager(); - - private List installs; - - private static boolean isWin = Platform.getOS().equals(Platform.OS_WIN32); - - public List getInstalls() { - if (installs == null) { - installs = new ArrayList<>(); - // TODO hack to get going - File qtDir = new File(System.getProperty("user.home"), "Qt/5.5"); - if (!qtDir.isDirectory() && isWin) { - qtDir = new File("C:/Qt/5.5"); - } - if (qtDir.isDirectory()) { - for (File dir : qtDir.listFiles()) { - Path qmakePath = dir.toPath().resolve(isWin ? "bin/qmake.exe" : "bin/qmake"); - if (qmakePath.toFile().canExecute()) { - installs.add(new QtInstall(qmakePath)); - } - } - } - } - - return installs; - } - -} diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstall.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstall.java new file mode 100644 index 00000000000..93cd5fdb587 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstall.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.cdt.qt.core; + +import java.nio.file.Path; + +/** + * Represents an installation of the Qt SDK. Qt installs are defined by the path + * to the qmake executable. + * + * @noimplement + */ +public interface IQtInstall { + + String getName(); + + Path getQmakePath(); + + String getSpec(); + + boolean supports(String os, String arch); + + Path getLibPath(); + +} diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstallManager.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstallManager.java new file mode 100644 index 00000000000..21d843507f7 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstallManager.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2015 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.cdt.qt.core; + +import java.util.Collection; + +/** + * The manager for Qt installs. + * + * @noimplement + */ +public interface IQtInstallManager { + + public Collection getInstalls(); + + public void addInstall(IQtInstall install); + + public IQtInstall getInstall(String name); + + public void removeInstall(IQtInstall install); + +} diff --git a/qt/org.eclipse.cdt.qt.ui/.classpath b/qt/org.eclipse.cdt.qt.ui/.classpath index 098194ca4b7..eca7bdba8f0 100644 --- a/qt/org.eclipse.cdt.qt.ui/.classpath +++ b/qt/org.eclipse.cdt.qt.ui/.classpath @@ -1,6 +1,6 @@ - + diff --git a/qt/org.eclipse.cdt.qt.ui/.settings/org.eclipse.jdt.core.prefs b/qt/org.eclipse.cdt.qt.ui/.settings/org.eclipse.jdt.core.prefs index f42de363afa..0c68a61dca8 100644 --- a/qt/org.eclipse.cdt.qt.ui/.settings/org.eclipse.jdt.core.prefs +++ b/qt/org.eclipse.cdt.qt.ui/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 -org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.7 +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/qt/org.eclipse.cdt.qt.ui/META-INF/MANIFEST.MF b/qt/org.eclipse.cdt.qt.ui/META-INF/MANIFEST.MF index 059cc598a18..d01b8202fb8 100644 --- a/qt/org.eclipse.cdt.qt.ui/META-INF/MANIFEST.MF +++ b/qt/org.eclipse.cdt.qt.ui/META-INF/MANIFEST.MF @@ -17,7 +17,7 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.cdt.ui, org.eclipse.cdt.core, org.eclipse.cdt.qt.core -Bundle-RequiredExecutionEnvironment: JavaSE-1.7 +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.cdt.internal.qt.ui.assist;x-friends:="org.eclipse.cdt.qt.ui.tests", org.eclipse.cdt.internal.qt.ui.pro.parser;x-friends:="org.eclipse.cdt.qt.ui.tests" diff --git a/qt/org.eclipse.cdt.qt.ui/plugin.properties b/qt/org.eclipse.cdt.qt.ui/plugin.properties index 9a3bdbc7b29..195bc79115e 100644 --- a/qt/org.eclipse.cdt.qt.ui/plugin.properties +++ b/qt/org.eclipse.cdt.qt.ui/plugin.properties @@ -14,3 +14,5 @@ qtHighlighting.extName=Qt Semantic Highlighting qtHighlighting.displayName=Qt Keywords newProject.name=Qt Project + +preferences.qt.name=Qt diff --git a/qt/org.eclipse.cdt.qt.ui/plugin.xml b/qt/org.eclipse.cdt.qt.ui/plugin.xml index 8037089b844..6abb4a83bb7 100644 --- a/qt/org.eclipse.cdt.qt.ui/plugin.xml +++ b/qt/org.eclipse.cdt.qt.ui/plugin.xml @@ -72,4 +72,12 @@ extensions="qml"> + + + + diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/Messages.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/Messages.java new file mode 100644 index 00000000000..b552aa3ca23 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/Messages.java @@ -0,0 +1,34 @@ +package org.eclipse.cdt.internal.qt.ui; + +import org.eclipse.osgi.util.NLS; + +public class Messages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.qt.ui.messages"; //$NON-NLS-1$ + public static String NewQtInstallWizardPage_0; + public static String NewQtInstallWizardPage_1; + public static String NewQtInstallWizardPage_10; + public static String NewQtInstallWizardPage_11; + public static String NewQtInstallWizardPage_2; + public static String NewQtInstallWizardPage_3; + public static String NewQtInstallWizardPage_4; + public static String NewQtInstallWizardPage_5; + public static String NewQtInstallWizardPage_6; + public static String NewQtInstallWizardPage_7; + public static String NewQtInstallWizardPage_8; + public static String NewQtInstallWizardPage_9; + public static String QtPreferencePage_0; + public static String QtPreferencePage_1; + public static String QtPreferencePage_2; + public static String QtPreferencePage_3; + public static String QtPreferencePage_4; + public static String QtPreferencePage_5; + public static String QtPreferencePage_6; + + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/QtUIPlugin.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/QtUIPlugin.java index 4851fca8712..5888ba3cbed 100644 --- a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/QtUIPlugin.java +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/QtUIPlugin.java @@ -19,6 +19,7 @@ import org.eclipse.core.runtime.Status; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; /** * The activator class controls the plug-in life cycle @@ -50,10 +51,12 @@ public class QtUIPlugin extends AbstractUIPlugin { super.start(context); plugin = this; - // Use a save participant to grab any changed resources while this plugin was inactive + // Use a save participant to grab any changed resources while this + // plugin was inactive QtResourceChangeListener resourceManager = new QtResourceChangeListener(); ISaveParticipant saveParticipant = new QtWorkspaceSaveParticipant(); - ISavedState lastState = ResourcesPlugin.getWorkspace().addSaveParticipant(QtUIPlugin.PLUGIN_ID, saveParticipant); + ISavedState lastState = ResourcesPlugin.getWorkspace().addSaveParticipant(QtUIPlugin.PLUGIN_ID, + saveParticipant); if (lastState != null) { lastState.processResourceChangeEvents(resourceManager); } @@ -115,4 +118,11 @@ public class QtUIPlugin extends AbstractUIPlugin { public static void log(int code, String msg, Throwable e) { getDefault().getLog().log(new Status(code, PLUGIN_ID, msg, e)); } + + public static T getService(Class service) { + BundleContext context = plugin.getBundle().getBundleContext(); + ServiceReference ref = context.getServiceReference(service); + return ref != null ? context.getService(ref) : null; + } + } diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/messages.properties b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/messages.properties new file mode 100644 index 00000000000..cdf9f362646 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/messages.properties @@ -0,0 +1,19 @@ +NewQtInstallWizardPage_0=NewQtInstall +NewQtInstallWizardPage_1=New Qt Install +NewQtInstallWizardPage_10=Must specify a name for the install +NewQtInstallWizardPage_11=Install name already exists +NewQtInstallWizardPage_2=Name: +NewQtInstallWizardPage_3=Location: +NewQtInstallWizardPage_4=Browse... +NewQtInstallWizardPage_5=Select location of qmake +NewQtInstallWizardPage_6=qmake.exe +NewQtInstallWizardPage_7=qmake +NewQtInstallWizardPage_8=Get Qt Spec +NewQtInstallWizardPage_9=mkspec: +QtPreferencePage_0=Qt Installs +QtPreferencePage_1=Name +QtPreferencePage_2=Location +QtPreferencePage_3=Add +QtPreferencePage_4=Remove +QtPreferencePage_5=Remove Qt Install +QtPreferencePage_6=Are you sure you want to remove the selected Qt installs? diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/NewQtInstallWizard.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/NewQtInstallWizard.java new file mode 100644 index 00000000000..98345cab2b4 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/NewQtInstallWizard.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2015 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.cdt.internal.qt.ui.preferences; + +import java.util.Map; + +import org.eclipse.cdt.qt.core.IQtInstall; +import org.eclipse.jface.wizard.Wizard; + +public class NewQtInstallWizard extends Wizard { + + private final NewQtInstallWizardPage page; + private IQtInstall install; + + public NewQtInstallWizard(Map existing) { + page = new NewQtInstallWizardPage(existing); + } + + @Override + public void addPages() { + addPage(page); + } + + @Override + public boolean performFinish() { + install = page.getInstall(); + return true; + } + + public IQtInstall getInstall() { + return install; + } + +} diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/NewQtInstallWizardPage.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/NewQtInstallWizardPage.java new file mode 100644 index 00000000000..1debcc9326f --- /dev/null +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/NewQtInstallWizardPage.java @@ -0,0 +1,129 @@ +package org.eclipse.cdt.internal.qt.ui.preferences; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Map; + +import org.eclipse.cdt.internal.qt.core.QtInstall; +import org.eclipse.cdt.internal.qt.ui.Messages; +import org.eclipse.cdt.qt.core.IQtInstall; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +public class NewQtInstallWizardPage extends WizardPage { + + private Text nameText; + private Text locationText; + private Text specText; + + private final Map existing; + + public NewQtInstallWizardPage(Map existing) { + super(Messages.NewQtInstallWizardPage_0, Messages.NewQtInstallWizardPage_1, null); + this.existing = existing; + } + + @Override + public void createControl(Composite parent) { + Composite comp = new Composite(parent, SWT.NONE); + comp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + comp.setLayout(new GridLayout(2, false)); + + Label nameLabel = new Label(comp, SWT.NONE); + nameLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); + nameLabel.setText(Messages.NewQtInstallWizardPage_2); + + nameText = new Text(comp, SWT.BORDER); + nameText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + nameText.addModifyListener(e -> validate()); + + Label locationLabel = new Label(comp, SWT.NONE); + locationLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); + locationLabel.setText(Messages.NewQtInstallWizardPage_3); + + Composite locationComp = new Composite(comp, SWT.NONE); + locationComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + GridLayout layout = new GridLayout(2, false); + layout.marginHeight = layout.marginWidth = 0; + locationComp.setLayout(layout); + + locationText = new Text(locationComp, SWT.BORDER); + locationText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + locationText.addModifyListener(e -> validate()); + + Button locationButton = new Button(locationComp, SWT.PUSH); + locationButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); + locationButton.setText(Messages.NewQtInstallWizardPage_4); + locationButton.addListener(SWT.Selection, e -> { + FileDialog dialog = new FileDialog(getShell(), SWT.OPEN); + dialog.setText(Messages.NewQtInstallWizardPage_5); + dialog.setFilterExtensions( + new String[] { Platform.getOS().equals(Platform.OS_WIN32) ? Messages.NewQtInstallWizardPage_6 : Messages.NewQtInstallWizardPage_7 }); + String selected = dialog.open(); + if (selected != null) { + locationText.setText(selected); + new Job(Messages.NewQtInstallWizardPage_8) { + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + String spec = QtInstall.getSpec(selected); + getControl().getDisplay().asyncExec(() -> { + specText.setText(spec); + if (nameText.getText().isEmpty() && !existing.containsKey(spec)) { + nameText.setText(spec); + } + }); + return Status.OK_STATUS; + } catch (IOException e) { + return Status.CANCEL_STATUS; + } + } + }.schedule(); + } + }); + + Label specLabel = new Label(comp, SWT.NONE); + specLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); + specLabel.setText(Messages.NewQtInstallWizardPage_9); + + specText = new Text(comp, SWT.READ_ONLY | SWT.BORDER); + specText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + + setControl(comp); + validate(); + } + + private void validate() { + setPageComplete(false); + String name = nameText.getText().trim(); + if (name.isEmpty()) { + setErrorMessage(Messages.NewQtInstallWizardPage_10); + return; + } + + if (existing.containsKey(name)) { + setErrorMessage(Messages.NewQtInstallWizardPage_11); + return; + } + + setPageComplete(true); + setErrorMessage(null); + } + + IQtInstall getInstall() { + return new QtInstall(nameText.getText(), Paths.get(locationText.getText())); + } + +} diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/QtPreferencePage.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/QtPreferencePage.java new file mode 100644 index 00000000000..2b84f7bfb74 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/QtPreferencePage.java @@ -0,0 +1,174 @@ +/******************************************************************************* + * Copyright (c) 2015 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.qt.ui.preferences; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.cdt.internal.qt.ui.Messages; +import org.eclipse.cdt.internal.qt.ui.QtUIPlugin; +import org.eclipse.cdt.qt.core.IQtInstall; +import org.eclipse.cdt.qt.core.IQtInstallManager; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.window.Window; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +public class QtPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { + + private IQtInstallManager manager; + private Table installTable; + private Button removeButton; + + private Map installsToAdd = new HashMap<>(); + private Map installsToRemove = new HashMap<>(); + + @Override + public void init(IWorkbench workbench) { + manager = QtUIPlugin.getService(IQtInstallManager.class); + } + + @Override + protected Control createContents(Composite parent) { + Composite control = new Composite(parent, SWT.NONE); + control.setLayout(new GridLayout()); + + Group installsGroup = new Group(control, SWT.NONE); + installsGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + installsGroup.setText(Messages.QtPreferencePage_0); + installsGroup.setLayout(new GridLayout(2, false)); + + Composite installTableComp = new Composite(installsGroup, SWT.NONE); + installTableComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + installTable = new Table(installTableComp, SWT.SINGLE | SWT.BORDER | SWT.V_SCROLL | SWT.FULL_SELECTION); + installTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + installTable.setHeaderVisible(true); + installTable.setLinesVisible(true); + installTable.addListener(SWT.Selection, e -> { + TableItem[] items = installTable.getSelection(); + removeButton.setEnabled(items.length > 0); + }); + + TableColumn nameColumn = new TableColumn(installTable, SWT.NONE); + nameColumn.setText(Messages.QtPreferencePage_1); + + TableColumn locationColumn = new TableColumn(installTable, SWT.NONE); + locationColumn.setText(Messages.QtPreferencePage_2); + + TableColumnLayout tableLayout = new TableColumnLayout(); + tableLayout.setColumnData(nameColumn, new ColumnWeightData(25, 50, true)); + tableLayout.setColumnData(locationColumn, new ColumnWeightData(75, 150, true)); + installTableComp.setLayout(tableLayout); + + Composite buttonsComp = new Composite(installsGroup, SWT.NONE); + buttonsComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true)); + buttonsComp.setLayout(new GridLayout()); + + Button addButton = new Button(buttonsComp, SWT.PUSH); + addButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); + addButton.setText(Messages.QtPreferencePage_3); + addButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + NewQtInstallWizard wizard = new NewQtInstallWizard(getInstalls()); + WizardDialog dialog = new WizardDialog(getShell(), wizard); + if (dialog.open() == Window.OK) { + IQtInstall install = wizard.getInstall(); + installsToAdd.put(install.getName(), install); + updateTable(); + } + } + }); + + removeButton = new Button(buttonsComp, SWT.PUSH); + removeButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); + removeButton.setText(Messages.QtPreferencePage_4); + removeButton.setEnabled(false); + removeButton.addListener(SWT.Selection, e -> { + if (MessageDialog.openConfirm(getShell(), Messages.QtPreferencePage_5, + Messages.QtPreferencePage_6)) { + for (TableItem item : installTable.getSelection()) { + IQtInstall install = (IQtInstall) item.getData(); + installsToRemove.put(install.getName(), install); + updateTable(); + } + } + }); + + updateTable(); + + return control; + } + + private Map getInstalls() { + Map installs = new HashMap<>(); + for (IQtInstall install : manager.getInstalls()) { + installs.put(install.getName(), install); + } + + for (IQtInstall install : installsToAdd.values()) { + installs.put(install.getName(), install); + } + + for (IQtInstall install : installsToRemove.values()) { + installs.remove(install.getName()); + } + + return installs; + } + + private void updateTable() { + List sorted = new ArrayList<>(getInstalls().values()); + Collections.sort(sorted, (o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName())); + + installTable.clearAll(); + for (IQtInstall install : sorted) { + TableItem item = new TableItem(installTable, SWT.NONE); + item.setText(0, install.getName()); + item.setText(1, install.getQmakePath().toString()); + item.setData(install); + } + } + + @Override + public boolean performOk() { + for (IQtInstall install : installsToAdd.values()) { + manager.addInstall(install); + } + + for (IQtInstall install : installsToRemove.values()) { + manager.removeInstall(install); + } + + return true; + } + +}