| /* |
| * Copyright (c) 2013 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.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.cdt.core.CCorePlugin; |
| import org.eclipse.cdt.core.envvar.IEnvironmentVariable; |
| import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsSerializableProvider; |
| import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; |
| import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; |
| import org.eclipse.core.resources.IResource; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| |
| /** |
| * This provider uses persistent cache to store the include paths for different |
| * Qt installations. A Qt installation is uniquely identified by the path to |
| * the qmake binary within the installation. |
| * <p> |
| * This result is shared among all Build Configurations that use the provider |
| * with the same value for the QMAKE environment variable. |
| */ |
| public class QtIncludePathsProvider extends LanguageSettingsSerializableProvider { |
| |
| /** |
| * The provider identifies Qt installations by the absolute path to the qmake binary. The |
| * include paths relevant to the installations are computed and persisted in {@link QtIncludePaths}. |
| */ |
| private final Map<String, QtIncludePaths> qtInstallHeaders = new HashMap<String, QtIncludePaths>(); |
| |
| /** |
| * The build configuration stores the path to the qmake binary as an environment variable. |
| */ |
| private static final String ENVVAR_QMAKE = "QMAKE"; |
| |
| private static final String ELEMENT_QMAKE = "qmake"; |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (!(obj instanceof QtIncludePathsProvider)) |
| return super.equals(obj); |
| |
| /** |
| * Providers are equal when they have the same cached values. |
| */ |
| QtIncludePathsProvider other = (QtIncludePathsProvider) obj; |
| if (qtInstallHeaders == null) |
| return other.qtInstallHeaders == null; |
| return qtInstallHeaders.equals(other.qtInstallHeaders); |
| } |
| |
| @Override |
| public int hashCode() { |
| return qtInstallHeaders == null ? 0 : qtInstallHeaders.hashCode(); |
| } |
| |
| @Override |
| public void loadEntries(Element providerNode) { |
| super.loadEntries(providerNode); |
| |
| // Find and load all qmake child nodes. There will be one node for each Qt |
| // installation that has been used. Qt installations that are no longer valid |
| // are not loaded. This means they will be removed from the file the next time |
| // that the language setting providers are serialized. |
| NodeList children = providerNode.getChildNodes(); |
| for (int i = 0; i < children.getLength(); ++i) { |
| Node child = children.item(i); |
| if (ELEMENT_QMAKE.equals(child.getNodeName())) { |
| QtIncludePaths qtIncludePaths = QtIncludePaths.loadFrom(child); |
| if (qtIncludePaths != null |
| && qtIncludePaths.isValid()) |
| qtInstallHeaders.put(qtIncludePaths.getQMakePath(), qtIncludePaths); |
| } |
| } |
| } |
| |
| @Override |
| public void serializeEntries(Element parent) { |
| // NOTE: This creates its own XML structure where children of the provider node are qmake nodes. |
| // Within each qmake node is a list of include paths for that installation. Calling the |
| // base #serializeEntries here would try to write this instance's (empty) list of settings |
| // to the file. |
| |
| // Each value is serialized into a new element in the XML document. |
| Document document = parent instanceof Document ? (Document)parent : parent.getOwnerDocument(); |
| for(QtIncludePaths qtIncludePaths : qtInstallHeaders.values()) { |
| Element child = document.createElement(ELEMENT_QMAKE); |
| qtIncludePaths.serialize(child); |
| parent.appendChild(child); |
| } |
| } |
| |
| /** |
| * The given build configuration's QMAKE environment variable is used to identify the appropriate |
| * Qt installation. The language settings are then either returned from the previously persisted |
| * data or loaded, serialized, and returned. |
| */ |
| @Override |
| public synchronized List<ICLanguageSettingEntry> getSettingEntries(ICConfigurationDescription configDesc, IResource rc, String languageId) { |
| // Make sure the requested language is in scope for this provider. |
| if (!getLanguageScope().contains(languageId)) |
| return null; |
| |
| // The value of the build configuration's QMAKE environment variable is used to select the |
| // right version of qmake. |
| IEnvironmentVariable qmake_var = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariable(ENVVAR_QMAKE, configDesc, true); |
| if (qmake_var == null) |
| return null; |
| |
| String qmake = qmake_var.getValue(); |
| if (qmake == null) |
| return null; |
| |
| // The path to qmake is used as the key into the in-memory cache of header paths. |
| QtIncludePaths paths = qtInstallHeaders.get(qmake); |
| if (paths == null) { |
| paths = new QtIncludePaths(qmake); |
| qtInstallHeaders.put(qmake, paths); |
| } |
| |
| return paths.getSettingEntries(configDesc, null, languageId); |
| } |
| } |