2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
2016-01-15 14:57:40 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** GNU General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
2010-12-17 16:01:08 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2008-12-02 16:19:05 +01:00
|
|
|
|
2013-10-16 12:10:22 +02:00
|
|
|
#include "qmakenodes.h"
|
|
|
|
|
#include "qmakeproject.h"
|
|
|
|
|
#include "qmakeprojectmanager.h"
|
|
|
|
|
#include "qmakeprojectmanagerconstants.h"
|
|
|
|
|
#include "qmakebuildconfiguration.h"
|
2012-04-24 15:49:09 +02:00
|
|
|
#include "qmakerunconfigurationfactory.h"
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
#include <projectexplorer/nodesvisitor.h>
|
2014-10-24 15:43:15 +02:00
|
|
|
#include <projectexplorer/projectexplorer.h>
|
2016-04-22 15:42:30 +02:00
|
|
|
#include <projectexplorer/projectexplorerconstants.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <coreplugin/editormanager/editormanager.h>
|
2009-10-01 16:38:08 +02:00
|
|
|
#include <coreplugin/editormanager/ieditor.h>
|
2009-01-27 12:40:49 +01:00
|
|
|
#include <coreplugin/fileiconprovider.h>
|
2012-02-14 16:43:51 +01:00
|
|
|
#include <coreplugin/documentmanager.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <coreplugin/icore.h>
|
|
|
|
|
#include <coreplugin/iversioncontrol.h>
|
|
|
|
|
#include <coreplugin/vcsmanager.h>
|
2012-10-15 11:53:22 +02:00
|
|
|
#include <coreplugin/dialogs/readonlyfilesdialog.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-01-15 16:12:54 +01:00
|
|
|
#include <extensionsystem/pluginmanager.h>
|
|
|
|
|
|
2009-04-28 14:30:17 +02:00
|
|
|
#include <projectexplorer/buildmanager.h>
|
2012-04-24 15:49:09 +02:00
|
|
|
#include <projectexplorer/projectexplorer.h>
|
|
|
|
|
#include <projectexplorer/target.h>
|
2015-01-09 15:50:06 +01:00
|
|
|
#include <projectexplorer/projecttree.h>
|
2011-05-20 21:40:53 +02:00
|
|
|
#include <qtsupport/profilereader.h>
|
2012-09-03 18:31:44 +02:00
|
|
|
#include <qtsupport/qtkitinformation.h>
|
2016-01-15 16:12:54 +01:00
|
|
|
#include <cpptools/generatedcodemodelsupport.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2014-02-18 21:38:03 +01:00
|
|
|
#include <resourceeditor/resourcenode.h>
|
|
|
|
|
|
2014-09-15 00:12:27 +02:00
|
|
|
#include <cpptools/cppmodelmanager.h>
|
2013-07-01 16:13:48 +02:00
|
|
|
#include <cpptools/cpptoolsconstants.h>
|
2013-04-09 10:40:18 +02:00
|
|
|
|
2014-06-16 18:25:52 +04:00
|
|
|
#include <utils/algorithm.h>
|
2015-02-02 00:37:38 +02:00
|
|
|
#include <utils/fileutils.h>
|
2012-08-23 15:53:58 +02:00
|
|
|
#include <utils/hostosinfo.h>
|
2014-11-03 12:29:43 +01:00
|
|
|
#include <utils/qtcprocess.h>
|
2015-02-04 09:32:46 +01:00
|
|
|
#include <utils/mimetypes/mimedatabase.h>
|
2010-08-24 18:22:57 +02:00
|
|
|
#include <utils/stringutils.h>
|
Implement theming for QtCreator
Adds a 'Theme' tab to the environment settings and a '-theme' command
line option.
A theme is a combination of colors, gradients, flags and style
information.
There are two themes:
- 'default': preserves the current default look
- 'dark': uses a more flat for many widgets, dark color theme
for everything
This does not use a stylesheet (too limited), but rather sets
the palette via C++ and modifies drawing behavior.
Overall, the look is more flat (removed some gradients and bevels).
Tested on Ubuntu 14.04 using Qt 5.4 and running on a KDE
Desktop (Oxygen base style).
For a screenshot, see
https://gist.github.com/thorbenk/5ab06bea726de0aa7473
Changes:
- Introduce class Theme, defining the interface how to access theme
specific settings. The class reads a .creatortheme file (INI file, via
QSettings)
- Define named colors in the [Palette] section
(see dark.creatortheme for example usage)
- Use either named colors of AARRGGBB (hex) in the [Colors]
section
- A file ending with .creatortheme may be supplied
to the '-theme' command line option
- A global Theme instance can be accessed via creatorTheme()
- Query colors, gradients, icons and flags from the theme
were possible (TODO: use this in more places...)
- There are very many color roles. It seems better to me
to describe the role clearly, and then to consolidate later
in the actual theme by assigning the same color.
For example, one can set the text color of the output pane button
individualy.
- Many elements are also drawn differently.
For the dark theme, I wanted to have a flatter look.
- Introduce Theme::WidgetStyle enum, for now {Original, Flat}.
- The theme specifies which kind of widget style it wants.
- The drawing code queries the theme's style flag and
switches between the original, gradient based look and
the new, flat look.
- Create some custom icons which look better on dark background
(wip, currently folder/file icons)
- Let ManhattanStyle draw some elements for non-panelwidgets, too
(open/close arrows in QTreeView, custom folder/file icons)
- For the welcomescreen, pass the WelcomeTheme class.
WelcomeTheme exposes theme colors as Q_PROPERTY accessible from
.qml
- Themes can be modified via the 'Themes' tab in the environment
settings.
TODO:
* Unify image handling
* Avoid style name references
* Fix gradients
Change-Id: I92c2050ab0fb327649ea1eff4adec973d2073944
Reviewed-by: Thomas Hartmann <Thomas.Hartmann@digia.com>
Reviewed-by: hjk <hjk121@nokiamail.com>
2014-10-14 19:09:48 +02:00
|
|
|
#include <utils/theme/theme.h>
|
2011-05-20 21:40:53 +02:00
|
|
|
#include <proparser/prowriter.h>
|
2013-05-29 20:18:51 +02:00
|
|
|
#include <proparser/qmakevfs.h>
|
2008-12-09 15:25:01 +01:00
|
|
|
|
2016-03-01 11:07:10 +02:00
|
|
|
#include <QApplication>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QDebug>
|
|
|
|
|
#include <QDir>
|
|
|
|
|
#include <QFile>
|
|
|
|
|
#include <QFileInfo>
|
|
|
|
|
#include <QXmlStreamReader>
|
2008-12-09 15:25:01 +01:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QMessageBox>
|
2012-02-09 09:35:03 +01:00
|
|
|
#include <utils/QtConcurrentTools>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2014-09-20 21:52:56 +02:00
|
|
|
using namespace Core;
|
2015-02-01 18:44:47 +02:00
|
|
|
using namespace ProjectExplorer;
|
Implement theming for QtCreator
Adds a 'Theme' tab to the environment settings and a '-theme' command
line option.
A theme is a combination of colors, gradients, flags and style
information.
There are two themes:
- 'default': preserves the current default look
- 'dark': uses a more flat for many widgets, dark color theme
for everything
This does not use a stylesheet (too limited), but rather sets
the palette via C++ and modifies drawing behavior.
Overall, the look is more flat (removed some gradients and bevels).
Tested on Ubuntu 14.04 using Qt 5.4 and running on a KDE
Desktop (Oxygen base style).
For a screenshot, see
https://gist.github.com/thorbenk/5ab06bea726de0aa7473
Changes:
- Introduce class Theme, defining the interface how to access theme
specific settings. The class reads a .creatortheme file (INI file, via
QSettings)
- Define named colors in the [Palette] section
(see dark.creatortheme for example usage)
- Use either named colors of AARRGGBB (hex) in the [Colors]
section
- A file ending with .creatortheme may be supplied
to the '-theme' command line option
- A global Theme instance can be accessed via creatorTheme()
- Query colors, gradients, icons and flags from the theme
were possible (TODO: use this in more places...)
- There are very many color roles. It seems better to me
to describe the role clearly, and then to consolidate later
in the actual theme by assigning the same color.
For example, one can set the text color of the output pane button
individualy.
- Many elements are also drawn differently.
For the dark theme, I wanted to have a flatter look.
- Introduce Theme::WidgetStyle enum, for now {Original, Flat}.
- The theme specifies which kind of widget style it wants.
- The drawing code queries the theme's style flag and
switches between the original, gradient based look and
the new, flat look.
- Create some custom icons which look better on dark background
(wip, currently folder/file icons)
- Let ManhattanStyle draw some elements for non-panelwidgets, too
(open/close arrows in QTreeView, custom folder/file icons)
- For the welcomescreen, pass the WelcomeTheme class.
WelcomeTheme exposes theme colors as Q_PROPERTY accessible from
.qml
- Themes can be modified via the 'Themes' tab in the environment
settings.
TODO:
* Unify image handling
* Avoid style name references
* Fix gradients
Change-Id: I92c2050ab0fb327649ea1eff4adec973d2073944
Reviewed-by: Thomas Hartmann <Thomas.Hartmann@digia.com>
Reviewed-by: hjk <hjk121@nokiamail.com>
2014-10-14 19:09:48 +02:00
|
|
|
using namespace Utils;
|
2014-09-20 21:52:56 +02:00
|
|
|
|
2013-10-29 16:08:37 +01:00
|
|
|
// Static cached data in struct QmakeNodeStaticData providing information and icons
|
2010-02-12 12:40:32 +01:00
|
|
|
// for file types and the project. Do some magic via qAddPostRoutine()
|
|
|
|
|
// to make sure the icons do not outlive QApplication, triggering warnings on X11.
|
|
|
|
|
|
|
|
|
|
struct FileTypeDataStorage {
|
2015-02-01 18:44:47 +02:00
|
|
|
FileType type;
|
2015-11-02 17:00:46 +01:00
|
|
|
Theme::ImageFile themeImage;
|
2010-02-12 12:40:32 +01:00
|
|
|
const char *typeName;
|
|
|
|
|
const char *icon;
|
2015-11-02 17:00:46 +01:00
|
|
|
const char *addFileFilter;
|
2010-02-12 12:40:32 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const FileTypeDataStorage fileTypeDataStorage[] = {
|
2015-11-02 17:00:46 +01:00
|
|
|
{ HeaderType, Theme::ProjectExplorerHeader, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Headers"),
|
2016-04-22 15:42:30 +02:00
|
|
|
ProjectExplorer::Constants::FILEOVERLAY_H, "*.h; *.hh; *.hpp; *.hxx;"},
|
2015-11-02 17:00:46 +01:00
|
|
|
{ SourceType, Theme::ProjectExplorerSource, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Sources"),
|
2016-04-22 15:42:30 +02:00
|
|
|
ProjectExplorer::Constants::FILEOVERLAY_CPP, "*.c; *.cc; *.cpp; *.cp; *.cxx; *.c++;" },
|
2015-11-02 17:00:46 +01:00
|
|
|
{ FormType, Theme::ProjectExplorerForm, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Forms"),
|
2016-04-22 15:42:30 +02:00
|
|
|
Constants::FILEOVERLAY_UI, "*.ui;" },
|
2016-04-05 11:22:49 +02:00
|
|
|
{ StateChartType, Theme::ProjectExplorerForm, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "State charts"),
|
2016-04-22 15:42:30 +02:00
|
|
|
ProjectExplorer::Constants::FILEOVERLAY_SCXML, "*.scxml;" },
|
2015-11-02 17:00:46 +01:00
|
|
|
{ ResourceType, Theme::ProjectExplorerResource, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Resources"),
|
2016-04-22 15:42:30 +02:00
|
|
|
ProjectExplorer::Constants::FILEOVERLAY_QRC, "*.qrc;" },
|
2015-11-02 17:00:46 +01:00
|
|
|
{ QMLType, Theme::ProjectExplorerQML, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "QML"),
|
2016-04-22 15:42:30 +02:00
|
|
|
ProjectExplorer::Constants::FILEOVERLAY_QML, "*.qml;" },
|
2015-11-02 17:00:46 +01:00
|
|
|
{ UnknownFileType, Theme::ProjectExplorerOtherFiles, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Other files"),
|
2016-04-22 15:42:30 +02:00
|
|
|
ProjectExplorer::Constants::FILEOVERLAY_UNKNOWN, "*;" }
|
2010-02-12 12:40:32 +01:00
|
|
|
};
|
|
|
|
|
|
2014-02-10 16:05:35 +01:00
|
|
|
class SortByPath
|
2012-05-04 11:49:37 +02:00
|
|
|
{
|
2014-02-10 16:05:35 +01:00
|
|
|
public:
|
2015-02-01 18:44:47 +02:00
|
|
|
bool operator()(Node *a, Node *b)
|
2015-10-29 17:53:47 +01:00
|
|
|
{ return operator()(a->filePath(), b->filePath()); }
|
2015-02-02 00:37:38 +02:00
|
|
|
bool operator()(Node *a, const FileName &b)
|
2015-10-29 17:53:47 +01:00
|
|
|
{ return operator()(a->filePath(), b); }
|
2015-02-02 00:37:38 +02:00
|
|
|
bool operator()(const FileName &a, Node *b)
|
2015-10-29 17:53:47 +01:00
|
|
|
{ return operator()(a, b->filePath()); }
|
2015-02-17 10:10:35 +02:00
|
|
|
// Compare as strings to correctly detect case-only file rename
|
2015-02-02 00:37:38 +02:00
|
|
|
bool operator()(const FileName &a, const FileName &b)
|
2015-02-17 10:10:35 +02:00
|
|
|
{ return a.toString() < b.toString(); }
|
2014-02-10 16:05:35 +01:00
|
|
|
};
|
2012-05-04 11:49:37 +02:00
|
|
|
|
2013-10-29 16:08:37 +01:00
|
|
|
class QmakeNodeStaticData {
|
2012-03-27 16:37:33 +02:00
|
|
|
public:
|
|
|
|
|
class FileTypeData {
|
|
|
|
|
public:
|
2015-02-01 18:44:47 +02:00
|
|
|
FileTypeData(FileType t = UnknownFileType,
|
2010-02-12 12:40:32 +01:00
|
|
|
const QString &tN = QString(),
|
2015-11-02 17:00:46 +01:00
|
|
|
const QString &aff = QString(),
|
2010-02-12 12:40:32 +01:00
|
|
|
const QIcon &i = QIcon()) :
|
2015-11-02 17:00:46 +01:00
|
|
|
type(t), typeName(tN), addFileFilter(aff), icon(i) { }
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
FileType type;
|
2010-02-12 12:40:32 +01:00
|
|
|
QString typeName;
|
2015-11-02 17:00:46 +01:00
|
|
|
QString addFileFilter;
|
2010-02-12 12:40:32 +01:00
|
|
|
QIcon icon;
|
|
|
|
|
};
|
|
|
|
|
|
2013-10-29 16:08:37 +01:00
|
|
|
QmakeNodeStaticData();
|
2012-03-27 16:37:33 +02:00
|
|
|
|
2010-02-12 12:40:32 +01:00
|
|
|
QVector<FileTypeData> fileTypeData;
|
|
|
|
|
QIcon projectIcon;
|
|
|
|
|
};
|
|
|
|
|
|
2013-10-29 16:08:37 +01:00
|
|
|
static void clearQmakeNodeStaticData();
|
2010-02-12 12:40:32 +01:00
|
|
|
|
2013-10-29 16:08:37 +01:00
|
|
|
QmakeNodeStaticData::QmakeNodeStaticData()
|
2012-03-27 16:37:33 +02:00
|
|
|
{
|
2010-02-12 12:40:32 +01:00
|
|
|
// File type data
|
|
|
|
|
const unsigned count = sizeof(fileTypeDataStorage)/sizeof(FileTypeDataStorage);
|
2012-03-27 16:37:33 +02:00
|
|
|
fileTypeData.reserve(count);
|
2010-02-12 12:40:32 +01:00
|
|
|
|
|
|
|
|
// Overlay the SP_DirIcon with the custom icons
|
|
|
|
|
const QSize desiredSize = QSize(16, 16);
|
|
|
|
|
|
2016-03-01 11:07:10 +02:00
|
|
|
const QPixmap dirPixmap = qApp->style()->standardIcon(QStyle::SP_DirIcon).pixmap(desiredSize);
|
2011-04-19 15:42:14 +02:00
|
|
|
for (unsigned i = 0 ; i < count; ++i) {
|
Implement theming for QtCreator
Adds a 'Theme' tab to the environment settings and a '-theme' command
line option.
A theme is a combination of colors, gradients, flags and style
information.
There are two themes:
- 'default': preserves the current default look
- 'dark': uses a more flat for many widgets, dark color theme
for everything
This does not use a stylesheet (too limited), but rather sets
the palette via C++ and modifies drawing behavior.
Overall, the look is more flat (removed some gradients and bevels).
Tested on Ubuntu 14.04 using Qt 5.4 and running on a KDE
Desktop (Oxygen base style).
For a screenshot, see
https://gist.github.com/thorbenk/5ab06bea726de0aa7473
Changes:
- Introduce class Theme, defining the interface how to access theme
specific settings. The class reads a .creatortheme file (INI file, via
QSettings)
- Define named colors in the [Palette] section
(see dark.creatortheme for example usage)
- Use either named colors of AARRGGBB (hex) in the [Colors]
section
- A file ending with .creatortheme may be supplied
to the '-theme' command line option
- A global Theme instance can be accessed via creatorTheme()
- Query colors, gradients, icons and flags from the theme
were possible (TODO: use this in more places...)
- There are very many color roles. It seems better to me
to describe the role clearly, and then to consolidate later
in the actual theme by assigning the same color.
For example, one can set the text color of the output pane button
individualy.
- Many elements are also drawn differently.
For the dark theme, I wanted to have a flatter look.
- Introduce Theme::WidgetStyle enum, for now {Original, Flat}.
- The theme specifies which kind of widget style it wants.
- The drawing code queries the theme's style flag and
switches between the original, gradient based look and
the new, flat look.
- Create some custom icons which look better on dark background
(wip, currently folder/file icons)
- Let ManhattanStyle draw some elements for non-panelwidgets, too
(open/close arrows in QTreeView, custom folder/file icons)
- For the welcomescreen, pass the WelcomeTheme class.
WelcomeTheme exposes theme colors as Q_PROPERTY accessible from
.qml
- Themes can be modified via the 'Themes' tab in the environment
settings.
TODO:
* Unify image handling
* Avoid style name references
* Fix gradients
Change-Id: I92c2050ab0fb327649ea1eff4adec973d2073944
Reviewed-by: Thomas Hartmann <Thomas.Hartmann@digia.com>
Reviewed-by: hjk <hjk121@nokiamail.com>
2014-10-14 19:09:48 +02:00
|
|
|
QIcon overlayIcon;
|
2014-10-15 23:07:33 +02:00
|
|
|
const QString iconFile = creatorTheme()->imageFile(fileTypeDataStorage[i].themeImage,
|
|
|
|
|
QString::fromLatin1(fileTypeDataStorage[i].icon));
|
Implement theming for QtCreator
Adds a 'Theme' tab to the environment settings and a '-theme' command
line option.
A theme is a combination of colors, gradients, flags and style
information.
There are two themes:
- 'default': preserves the current default look
- 'dark': uses a more flat for many widgets, dark color theme
for everything
This does not use a stylesheet (too limited), but rather sets
the palette via C++ and modifies drawing behavior.
Overall, the look is more flat (removed some gradients and bevels).
Tested on Ubuntu 14.04 using Qt 5.4 and running on a KDE
Desktop (Oxygen base style).
For a screenshot, see
https://gist.github.com/thorbenk/5ab06bea726de0aa7473
Changes:
- Introduce class Theme, defining the interface how to access theme
specific settings. The class reads a .creatortheme file (INI file, via
QSettings)
- Define named colors in the [Palette] section
(see dark.creatortheme for example usage)
- Use either named colors of AARRGGBB (hex) in the [Colors]
section
- A file ending with .creatortheme may be supplied
to the '-theme' command line option
- A global Theme instance can be accessed via creatorTheme()
- Query colors, gradients, icons and flags from the theme
were possible (TODO: use this in more places...)
- There are very many color roles. It seems better to me
to describe the role clearly, and then to consolidate later
in the actual theme by assigning the same color.
For example, one can set the text color of the output pane button
individualy.
- Many elements are also drawn differently.
For the dark theme, I wanted to have a flatter look.
- Introduce Theme::WidgetStyle enum, for now {Original, Flat}.
- The theme specifies which kind of widget style it wants.
- The drawing code queries the theme's style flag and
switches between the original, gradient based look and
the new, flat look.
- Create some custom icons which look better on dark background
(wip, currently folder/file icons)
- Let ManhattanStyle draw some elements for non-panelwidgets, too
(open/close arrows in QTreeView, custom folder/file icons)
- For the welcomescreen, pass the WelcomeTheme class.
WelcomeTheme exposes theme colors as Q_PROPERTY accessible from
.qml
- Themes can be modified via the 'Themes' tab in the environment
settings.
TODO:
* Unify image handling
* Avoid style name references
* Fix gradients
Change-Id: I92c2050ab0fb327649ea1eff4adec973d2073944
Reviewed-by: Thomas Hartmann <Thomas.Hartmann@digia.com>
Reviewed-by: hjk <hjk121@nokiamail.com>
2014-10-14 19:09:48 +02:00
|
|
|
overlayIcon = QIcon(iconFile);
|
2010-02-12 12:40:32 +01:00
|
|
|
QIcon folderIcon;
|
2016-03-01 11:07:10 +02:00
|
|
|
folderIcon.addPixmap(FileIconProvider::overlayIcon(dirPixmap, overlayIcon));
|
2015-01-09 15:50:06 +01:00
|
|
|
const QString desc = QCoreApplication::translate("QmakeProjectManager::QmakePriFileNode", fileTypeDataStorage[i].typeName);
|
2015-11-02 17:00:46 +01:00
|
|
|
const QString filter = QString::fromUtf8(fileTypeDataStorage[i].addFileFilter);
|
2013-10-29 16:08:37 +01:00
|
|
|
fileTypeData.push_back(QmakeNodeStaticData::FileTypeData(fileTypeDataStorage[i].type,
|
2015-11-02 17:00:46 +01:00
|
|
|
desc, filter, folderIcon));
|
2010-02-12 12:40:32 +01:00
|
|
|
}
|
|
|
|
|
// Project icon
|
2014-10-15 23:07:33 +02:00
|
|
|
const QString fileName = creatorTheme()->imageFile(Theme::ProjectFileIcon,
|
2016-04-22 15:42:30 +02:00
|
|
|
QLatin1String(ProjectExplorer::Constants::FILEOVERLAY_QT));
|
2014-10-15 23:07:33 +02:00
|
|
|
const QIcon projectBaseIcon(fileName);
|
2016-03-01 11:07:10 +02:00
|
|
|
const QPixmap projectPixmap = FileIconProvider::overlayIcon(dirPixmap, projectBaseIcon);
|
2012-03-27 16:37:33 +02:00
|
|
|
projectIcon.addPixmap(projectPixmap);
|
2010-02-12 12:40:32 +01:00
|
|
|
|
2013-10-29 16:08:37 +01:00
|
|
|
qAddPostRoutine(clearQmakeNodeStaticData);
|
2012-03-27 16:37:33 +02:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 17:37:39 +01:00
|
|
|
Q_GLOBAL_STATIC(QmakeNodeStaticData, qmakeNodeStaticData)
|
2010-02-12 12:40:32 +01:00
|
|
|
|
2013-10-29 16:08:37 +01:00
|
|
|
static void clearQmakeNodeStaticData()
|
2010-02-12 12:40:32 +01:00
|
|
|
{
|
2013-10-29 17:37:39 +01:00
|
|
|
qmakeNodeStaticData()->fileTypeData.clear();
|
|
|
|
|
qmakeNodeStaticData()->projectIcon = QIcon();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2010-02-12 12:40:32 +01:00
|
|
|
enum { debug = 0 };
|
|
|
|
|
|
2013-10-16 11:02:37 +02:00
|
|
|
using namespace QmakeProjectManager;
|
|
|
|
|
using namespace QmakeProjectManager::Internal;
|
2010-01-20 14:47:08 +01:00
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
namespace QmakeProjectManager {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
class EvalInput
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
QString projectDir;
|
2015-02-02 00:37:38 +02:00
|
|
|
FileName projectFilePath;
|
2014-09-10 12:53:55 +02:00
|
|
|
QString buildDirectory;
|
|
|
|
|
QtSupport::ProFileReader *readerExact;
|
|
|
|
|
QtSupport::ProFileReader *readerCumulative;
|
|
|
|
|
ProFileGlobals *qmakeGlobals;
|
|
|
|
|
QMakeVfs *qmakeVfs;
|
|
|
|
|
bool isQt5;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class PriFileEvalResult
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
QStringList folders;
|
2015-02-01 18:44:47 +02:00
|
|
|
QSet<FileName> recursiveEnumerateFiles;
|
|
|
|
|
QMap<FileType, QSet<FileName> > foundFiles;
|
2014-09-10 12:53:55 +02:00
|
|
|
};
|
|
|
|
|
|
2015-08-12 12:59:38 +02:00
|
|
|
class IncludedPriFile
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
Utils::FileName name;
|
|
|
|
|
PriFileEvalResult result;
|
|
|
|
|
QMap<Utils::FileName, IncludedPriFile *> children;
|
|
|
|
|
QVector<ProFile *> proFilesExact;
|
|
|
|
|
QVector<ProFile *> proFilesCumulative;
|
|
|
|
|
|
|
|
|
|
~IncludedPriFile()
|
|
|
|
|
{
|
|
|
|
|
qDeleteAll(children);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
class EvalResult
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
enum EvalResultState { EvalAbort, EvalFail, EvalPartial, EvalOk };
|
|
|
|
|
EvalResultState state;
|
|
|
|
|
QmakeProjectType projectType;
|
|
|
|
|
|
|
|
|
|
QStringList subProjectsNotToDeploy;
|
2015-02-02 00:37:38 +02:00
|
|
|
QSet<FileName> exactSubdirs;
|
2015-08-12 12:59:38 +02:00
|
|
|
IncludedPriFile includedFiles;
|
2014-09-10 12:53:55 +02:00
|
|
|
TargetInformation targetInformation;
|
|
|
|
|
InstallsList installsList;
|
|
|
|
|
QHash<QmakeVariable, QStringList> newVarValues;
|
|
|
|
|
bool isDeployable;
|
|
|
|
|
QStringList errors;
|
|
|
|
|
};
|
2015-11-02 17:00:46 +01:00
|
|
|
|
|
|
|
|
QString ProVirtualFolderNode::displayName() const
|
|
|
|
|
{
|
|
|
|
|
return m_typeName;
|
2014-09-10 12:53:55 +02:00
|
|
|
}
|
2015-11-02 17:00:46 +01:00
|
|
|
|
|
|
|
|
QString ProVirtualFolderNode::addFileFilter() const
|
|
|
|
|
{
|
|
|
|
|
return m_addFileFilter;
|
2014-09-10 12:53:55 +02:00
|
|
|
}
|
2015-01-09 15:50:06 +01:00
|
|
|
|
2015-11-02 17:00:46 +01:00
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace QMakeProjectManager
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QmakePriFile::QmakePriFile(QmakeProjectManager::QmakePriFileNode *qmakePriFile)
|
2015-01-09 15:50:06 +01:00
|
|
|
: IDocument(0), m_priFile(qmakePriFile)
|
2010-01-20 14:47:08 +01:00
|
|
|
{
|
2014-03-05 15:58:12 +01:00
|
|
|
setId("Qmake.PriFile");
|
2014-06-26 02:15:34 +02:00
|
|
|
setMimeType(QLatin1String(QmakeProjectManager::Constants::PROFILE_MIMETYPE));
|
2015-10-29 17:53:47 +01:00
|
|
|
setFilePath(m_priFile->filePath());
|
2010-01-20 14:47:08 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
Core::IDocument::ReloadBehavior QmakePriFile::reloadBehavior(ChangeTrigger state, ChangeType type) const
|
2010-01-20 14:47:08 +01:00
|
|
|
{
|
2010-03-19 10:28:05 +01:00
|
|
|
Q_UNUSED(state)
|
|
|
|
|
Q_UNUSED(type)
|
|
|
|
|
return BehaviorSilent;
|
2010-01-20 14:47:08 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakePriFile::reload(QString *errorString, ReloadFlag flag, ChangeType type)
|
2010-03-19 10:28:05 +01:00
|
|
|
{
|
2011-04-04 15:24:13 +02:00
|
|
|
Q_UNUSED(errorString)
|
2010-03-19 10:28:05 +01:00
|
|
|
Q_UNUSED(flag)
|
|
|
|
|
if (type == TypePermissions)
|
2011-04-04 15:24:13 +02:00
|
|
|
return true;
|
2010-03-19 10:28:05 +01:00
|
|
|
m_priFile->scheduleUpdate();
|
2011-04-04 15:24:13 +02:00
|
|
|
return true;
|
2010-03-19 10:28:05 +01:00
|
|
|
}
|
2010-01-20 14:47:08 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
/*!
|
2013-10-29 16:08:37 +01:00
|
|
|
\class QmakePriFileNode
|
2008-12-02 12:01:29 +01:00
|
|
|
Implements abstract ProjectNode class
|
|
|
|
|
*/
|
|
|
|
|
|
2013-10-16 11:02:37 +02:00
|
|
|
namespace QmakeProjectManager {
|
2011-11-22 13:10:10 +01:00
|
|
|
|
2015-02-02 00:37:38 +02:00
|
|
|
QmakePriFileNode::QmakePriFileNode(QmakeProject *project, QmakeProFileNode *qmakeProFileNode,
|
|
|
|
|
const FileName &filePath)
|
2008-12-02 12:01:29 +01:00
|
|
|
: ProjectNode(filePath),
|
|
|
|
|
m_project(project),
|
2013-10-29 17:37:39 +01:00
|
|
|
m_qmakeProFileNode(qmakeProFileNode),
|
2015-02-02 00:37:38 +02:00
|
|
|
m_projectFilePath(filePath),
|
2015-06-18 15:14:06 +02:00
|
|
|
m_projectDir(filePath.toFileInfo().absolutePath())
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2008-12-17 15:51:48 +01:00
|
|
|
Q_ASSERT(project);
|
2013-10-29 14:22:31 +01:00
|
|
|
m_qmakePriFile = new QmakePriFile(this);
|
|
|
|
|
Core::DocumentManager::addDocument(m_qmakePriFile);
|
2010-01-20 14:47:08 +01:00
|
|
|
|
2015-02-02 00:37:38 +02:00
|
|
|
setDisplayName(filePath.toFileInfo().completeBaseName());
|
2013-10-29 17:37:39 +01:00
|
|
|
setIcon(qmakeNodeStaticData()->projectIcon);
|
2008-12-09 17:17:12 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QmakePriFileNode::~QmakePriFileNode()
|
2012-03-13 15:44:59 +01:00
|
|
|
{
|
|
|
|
|
watchFolders(QSet<QString>());
|
2015-01-09 15:50:06 +01:00
|
|
|
delete m_qmakePriFile;
|
2012-03-13 15:44:59 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakePriFileNode::scheduleUpdate()
|
2008-12-09 17:17:12 +01:00
|
|
|
{
|
2015-02-02 00:37:38 +02:00
|
|
|
QtSupport::ProFileCacheManager::instance()->discardFile(m_projectFilePath.toString());
|
2014-10-24 12:43:14 +02:00
|
|
|
m_qmakeProFileNode->scheduleUpdate(QmakeProFileNode::ParseLater);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2011-09-07 11:52:04 +02:00
|
|
|
namespace Internal {
|
2010-02-12 12:40:32 +01:00
|
|
|
struct InternalNode
|
2010-02-26 12:55:17 +01:00
|
|
|
{
|
2012-05-04 11:49:37 +02:00
|
|
|
QList<InternalNode *> virtualfolders;
|
|
|
|
|
QMap<QString, InternalNode *> subnodes;
|
2015-02-02 00:37:38 +02:00
|
|
|
FileNameList files;
|
2015-06-18 15:14:06 +02:00
|
|
|
FileType type = UnknownFileType;
|
|
|
|
|
int priority = 0;
|
2010-08-10 16:27:35 +02:00
|
|
|
QString displayName;
|
2012-05-04 11:49:37 +02:00
|
|
|
QString typeName;
|
2015-11-02 17:00:46 +01:00
|
|
|
QString addFileFilter;
|
2010-02-26 12:55:17 +01:00
|
|
|
QString fullPath;
|
|
|
|
|
QIcon icon;
|
2009-08-17 17:59:57 +02:00
|
|
|
|
2010-02-26 12:55:17 +01:00
|
|
|
~InternalNode()
|
|
|
|
|
{
|
2012-05-04 11:49:37 +02:00
|
|
|
qDeleteAll(virtualfolders);
|
2010-02-26 12:55:17 +01:00
|
|
|
qDeleteAll(subnodes);
|
|
|
|
|
}
|
2009-08-17 17:59:57 +02:00
|
|
|
|
2013-02-18 18:47:54 +01:00
|
|
|
// Creates: a tree structure from a list of absolute file paths.
|
2010-02-26 12:55:17 +01:00
|
|
|
// Empty directories are compressed into a single entry with a longer path.
|
|
|
|
|
// * project
|
|
|
|
|
// * /absolute/path
|
|
|
|
|
// * file1
|
|
|
|
|
// * relative
|
|
|
|
|
// * path1
|
|
|
|
|
// * file1
|
|
|
|
|
// * file2
|
|
|
|
|
// * path2
|
|
|
|
|
// * file1
|
2013-10-07 13:34:40 +02:00
|
|
|
// The function first creates a tree that looks like the directory structure, i.e.
|
2010-02-26 12:55:17 +01:00
|
|
|
// * /
|
|
|
|
|
// * absolute
|
|
|
|
|
// * path
|
|
|
|
|
// ...
|
|
|
|
|
// and afterwards calls compress() which merges directory nodes with single children, i.e. to
|
|
|
|
|
// * /absolute/path
|
2015-02-01 18:44:47 +02:00
|
|
|
void create(const QString &projectDir, const QSet<FileName> &newFilePaths, FileType type)
|
2010-02-26 12:55:17 +01:00
|
|
|
{
|
2012-01-13 14:20:45 +01:00
|
|
|
static const QChar separator = QLatin1Char('/');
|
2015-02-01 18:44:47 +02:00
|
|
|
const FileName projectDirFileName = FileName::fromString(projectDir);
|
|
|
|
|
foreach (const FileName &file, newFilePaths) {
|
|
|
|
|
FileName fileWithoutPrefix;
|
2010-02-26 12:55:17 +01:00
|
|
|
bool isRelative;
|
2011-11-25 13:17:52 +01:00
|
|
|
if (file.isChildOf(projectDirFileName)) {
|
2010-02-26 12:55:17 +01:00
|
|
|
isRelative = true;
|
2011-11-25 13:17:52 +01:00
|
|
|
fileWithoutPrefix = file.relativeChildPath(projectDirFileName);
|
2010-02-26 12:55:17 +01:00
|
|
|
} else {
|
|
|
|
|
isRelative = false;
|
|
|
|
|
fileWithoutPrefix = file;
|
|
|
|
|
}
|
2011-11-08 18:53:51 +01:00
|
|
|
QStringList parts = fileWithoutPrefix.toString().split(separator, QString::SkipEmptyParts);
|
2015-02-01 18:44:47 +02:00
|
|
|
if (!HostOsInfo::isWindowsHost() && !isRelative && parts.count() > 0)
|
2010-02-26 12:55:17 +01:00
|
|
|
parts[0].prepend(separator);
|
|
|
|
|
QStringListIterator it(parts);
|
|
|
|
|
InternalNode *currentNode = this;
|
2012-01-13 14:20:45 +01:00
|
|
|
QString path = (isRelative ? (projectDirFileName.toString() + QLatin1Char('/')) : QString());
|
2010-02-26 12:55:17 +01:00
|
|
|
while (it.hasNext()) {
|
|
|
|
|
const QString &key = it.next();
|
|
|
|
|
if (it.hasNext()) { // key is directory
|
|
|
|
|
path += key;
|
2010-08-10 16:27:35 +02:00
|
|
|
if (!currentNode->subnodes.contains(path)) {
|
2010-02-26 12:55:17 +01:00
|
|
|
InternalNode *val = new InternalNode;
|
|
|
|
|
val->type = type;
|
|
|
|
|
val->fullPath = path;
|
2010-08-10 16:27:35 +02:00
|
|
|
val->displayName = key;
|
|
|
|
|
currentNode->subnodes.insert(path, val);
|
2010-02-26 12:55:17 +01:00
|
|
|
currentNode = val;
|
|
|
|
|
} else {
|
2010-08-10 16:27:35 +02:00
|
|
|
currentNode = currentNode->subnodes.value(path);
|
2009-08-17 17:59:57 +02:00
|
|
|
}
|
2010-02-26 12:55:17 +01:00
|
|
|
path += separator;
|
|
|
|
|
} else { // key is filename
|
2015-02-02 00:37:38 +02:00
|
|
|
currentNode->files.append(file);
|
2009-08-17 17:59:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-02-26 12:55:17 +01:00
|
|
|
this->compress();
|
|
|
|
|
}
|
2009-08-17 17:59:57 +02:00
|
|
|
|
2010-02-26 12:55:17 +01:00
|
|
|
// Removes folder nodes with only a single sub folder in it
|
|
|
|
|
void compress()
|
|
|
|
|
{
|
|
|
|
|
QMap<QString, InternalNode*> newSubnodes;
|
|
|
|
|
QMapIterator<QString, InternalNode*> i(subnodes);
|
|
|
|
|
while (i.hasNext()) {
|
|
|
|
|
i.next();
|
|
|
|
|
i.value()->compress();
|
|
|
|
|
if (i.value()->files.isEmpty() && i.value()->subnodes.size() == 1) {
|
2010-08-10 16:27:35 +02:00
|
|
|
// replace i.value() by i.value()->subnodes.begin()
|
2010-02-26 12:55:17 +01:00
|
|
|
QString key = i.value()->subnodes.begin().key();
|
2010-08-10 16:27:35 +02:00
|
|
|
InternalNode *keep = i.value()->subnodes.value(key);
|
2015-09-02 15:27:45 +02:00
|
|
|
keep->displayName = i.value()->displayName + QDir::separator() + keep->displayName;
|
2010-08-10 16:27:35 +02:00
|
|
|
newSubnodes.insert(key, keep);
|
2010-02-26 12:55:17 +01:00
|
|
|
i.value()->subnodes.clear();
|
|
|
|
|
delete i.value();
|
|
|
|
|
} else {
|
|
|
|
|
newSubnodes.insert(i.key(), i.value());
|
2009-08-17 17:59:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
2010-02-26 12:55:17 +01:00
|
|
|
subnodes = newSubnodes;
|
|
|
|
|
}
|
2009-08-17 17:59:57 +02:00
|
|
|
|
2012-05-04 11:49:37 +02:00
|
|
|
FolderNode *createFolderNode(InternalNode *node)
|
|
|
|
|
{
|
|
|
|
|
FolderNode *newNode = 0;
|
2015-02-02 00:37:38 +02:00
|
|
|
if (node->typeName.isEmpty()) {
|
|
|
|
|
newNode = new FolderNode(FileName::fromString(node->fullPath));
|
|
|
|
|
} else {
|
2015-11-02 17:00:46 +01:00
|
|
|
auto n = new ProVirtualFolderNode(FileName::fromString(node->fullPath),
|
|
|
|
|
node->priority, node->typeName);
|
|
|
|
|
n->setAddFileFilter(node->addFileFilter);
|
|
|
|
|
newNode = n;
|
2015-02-02 00:37:38 +02:00
|
|
|
}
|
2012-05-04 11:49:37 +02:00
|
|
|
|
|
|
|
|
newNode->setDisplayName(node->displayName);
|
|
|
|
|
if (!node->icon.isNull())
|
|
|
|
|
newNode->setIcon(node->icon);
|
|
|
|
|
return newNode;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-26 12:55:17 +01:00
|
|
|
// Makes the projectNode's subtree below the given folder match this internal node's subtree
|
2015-02-01 18:44:47 +02:00
|
|
|
void updateSubFolders(FolderNode *folder)
|
2010-02-26 12:55:17 +01:00
|
|
|
{
|
2015-02-01 18:44:47 +02:00
|
|
|
if (type == ResourceType)
|
2014-02-18 21:38:03 +01:00
|
|
|
updateResourceFiles(folder);
|
|
|
|
|
else
|
|
|
|
|
updateFiles(folder, type);
|
2009-08-17 17:59:57 +02:00
|
|
|
|
2012-05-04 11:49:37 +02:00
|
|
|
// updateFolders
|
|
|
|
|
QMultiMap<QString, FolderNode *> existingFolderNodes;
|
|
|
|
|
foreach (FolderNode *node, folder->subFolderNodes())
|
2015-01-09 15:50:06 +01:00
|
|
|
if (node->nodeType() != ProjectNodeType && !dynamic_cast<ResourceEditor::ResourceTopLevelNode *>(node))
|
2015-10-29 17:53:47 +01:00
|
|
|
existingFolderNodes.insert(node->filePath().toString(), node);
|
2010-08-10 16:27:35 +02:00
|
|
|
|
2010-02-26 12:55:17 +01:00
|
|
|
QList<FolderNode *> foldersToRemove;
|
|
|
|
|
QList<FolderNode *> foldersToAdd;
|
|
|
|
|
typedef QPair<InternalNode *, FolderNode *> NodePair;
|
|
|
|
|
QList<NodePair> nodesToUpdate;
|
|
|
|
|
|
2012-05-04 11:49:37 +02:00
|
|
|
// Check virtual
|
|
|
|
|
{
|
|
|
|
|
QList<InternalNode *>::const_iterator it = virtualfolders.constBegin();
|
|
|
|
|
QList<InternalNode *>::const_iterator end = virtualfolders.constEnd();
|
|
|
|
|
for ( ; it != end; ++it) {
|
|
|
|
|
bool found = false;
|
|
|
|
|
QString path = (*it)->fullPath;
|
|
|
|
|
QMultiMap<QString, FolderNode *>::const_iterator oldit
|
|
|
|
|
= existingFolderNodes.constFind(path);
|
2012-05-08 14:38:20 +02:00
|
|
|
while (oldit != existingFolderNodes.constEnd() && oldit.key() == path) {
|
2015-02-01 18:44:47 +02:00
|
|
|
if (oldit.value()->nodeType() == VirtualFolderNodeType) {
|
|
|
|
|
VirtualFolderNode *vfn = dynamic_cast<VirtualFolderNode *>(oldit.value());
|
2012-05-04 11:49:37 +02:00
|
|
|
if (vfn->priority() == (*it)->priority) {
|
|
|
|
|
found = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
++oldit;
|
|
|
|
|
}
|
|
|
|
|
if (found) {
|
|
|
|
|
nodesToUpdate << NodePair(*it, *oldit);
|
|
|
|
|
} else {
|
|
|
|
|
FolderNode *newNode = createFolderNode(*it);
|
|
|
|
|
foldersToAdd << newNode;
|
|
|
|
|
nodesToUpdate << NodePair(*it, newNode);
|
|
|
|
|
}
|
2009-08-17 17:59:57 +02:00
|
|
|
}
|
2010-02-26 12:55:17 +01:00
|
|
|
}
|
2012-05-04 11:49:37 +02:00
|
|
|
// Check subnodes
|
|
|
|
|
{
|
|
|
|
|
QMap<QString, InternalNode *>::const_iterator it = subnodes.constBegin();
|
|
|
|
|
QMap<QString, InternalNode *>::const_iterator end = subnodes.constEnd();
|
|
|
|
|
|
|
|
|
|
for ( ; it != end; ++it) {
|
|
|
|
|
bool found = false;
|
|
|
|
|
QString path = it.value()->fullPath;
|
|
|
|
|
QMultiMap<QString, FolderNode *>::const_iterator oldit
|
|
|
|
|
= existingFolderNodes.constFind(path);
|
2012-05-08 14:38:20 +02:00
|
|
|
while (oldit != existingFolderNodes.constEnd() && oldit.key() == path) {
|
2015-02-01 18:44:47 +02:00
|
|
|
if (oldit.value()->nodeType() == FolderNodeType) {
|
2012-05-04 11:49:37 +02:00
|
|
|
found = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
++oldit;
|
|
|
|
|
}
|
|
|
|
|
if (found) {
|
|
|
|
|
nodesToUpdate << NodePair(it.value(), *oldit);
|
|
|
|
|
} else {
|
|
|
|
|
FolderNode *newNode = createFolderNode(it.value());
|
|
|
|
|
foldersToAdd << newNode;
|
|
|
|
|
nodesToUpdate << NodePair(it.value(), newNode);
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-02-26 12:55:17 +01:00
|
|
|
}
|
2009-08-17 17:59:57 +02:00
|
|
|
|
2012-05-04 11:49:37 +02:00
|
|
|
QSet<FolderNode *> toKeep;
|
|
|
|
|
foreach (const NodePair &np, nodesToUpdate)
|
|
|
|
|
toKeep << np.second;
|
|
|
|
|
|
|
|
|
|
QMultiMap<QString, FolderNode *>::const_iterator jit = existingFolderNodes.constBegin();
|
|
|
|
|
QMultiMap<QString, FolderNode *>::const_iterator jend = existingFolderNodes.constEnd();
|
|
|
|
|
for ( ; jit != jend; ++jit)
|
|
|
|
|
if (!toKeep.contains(jit.value()))
|
|
|
|
|
foldersToRemove << jit.value();
|
|
|
|
|
|
2010-02-26 12:55:17 +01:00
|
|
|
if (!foldersToRemove.isEmpty())
|
2014-02-18 19:49:55 +01:00
|
|
|
folder->removeFolderNodes(foldersToRemove);
|
2010-02-26 12:55:17 +01:00
|
|
|
if (!foldersToAdd.isEmpty())
|
2014-02-18 19:49:55 +01:00
|
|
|
folder->addFolderNodes(foldersToAdd);
|
2009-08-17 17:59:57 +02:00
|
|
|
|
2010-02-26 12:55:17 +01:00
|
|
|
foreach (const NodePair &np, nodesToUpdate)
|
2014-02-18 19:49:55 +01:00
|
|
|
np.first->updateSubFolders(np.second);
|
2010-02-26 12:55:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Makes the folder's files match this internal node's file list
|
2014-02-18 19:49:55 +01:00
|
|
|
void updateFiles(FolderNode *folder, FileType type)
|
2010-02-26 12:55:17 +01:00
|
|
|
{
|
|
|
|
|
QList<FileNode*> existingFileNodes;
|
|
|
|
|
foreach (FileNode *fileNode, folder->fileNodes()) {
|
|
|
|
|
if (fileNode->fileType() == type && !fileNode->isGenerated())
|
|
|
|
|
existingFileNodes << fileNode;
|
2009-08-17 17:59:57 +02:00
|
|
|
}
|
|
|
|
|
|
2010-02-26 12:55:17 +01:00
|
|
|
QList<FileNode*> filesToRemove;
|
2015-02-02 00:37:38 +02:00
|
|
|
FileNameList filesToAdd;
|
2014-02-10 16:05:35 +01:00
|
|
|
|
|
|
|
|
SortByPath sortByPath;
|
2014-06-16 18:25:52 +04:00
|
|
|
Utils::sort(files, sortByPath);
|
|
|
|
|
Utils::sort(existingFileNodes, sortByPath);
|
2014-02-10 16:05:35 +01:00
|
|
|
|
|
|
|
|
ProjectExplorer::compareSortedLists(existingFileNodes, files, filesToRemove, filesToAdd, sortByPath);
|
|
|
|
|
|
|
|
|
|
QList<FileNode *> nodesToAdd;
|
2015-02-02 00:37:38 +02:00
|
|
|
foreach (const FileName &file, filesToAdd)
|
2015-02-01 18:44:47 +02:00
|
|
|
nodesToAdd << new FileNode(file, type, false);
|
2010-02-26 12:55:17 +01:00
|
|
|
|
2014-02-10 16:05:35 +01:00
|
|
|
folder->removeFileNodes(filesToRemove);
|
|
|
|
|
folder->addFileNodes(nodesToAdd);
|
2010-02-26 12:55:17 +01:00
|
|
|
}
|
2014-02-18 21:38:03 +01:00
|
|
|
|
|
|
|
|
// Makes the folder's files match this internal node's file list
|
|
|
|
|
void updateResourceFiles(FolderNode *folder)
|
|
|
|
|
{
|
2015-02-01 18:44:47 +02:00
|
|
|
QList<FolderNode *> existingResourceNodes; // for resource special handling
|
2014-02-18 21:38:03 +01:00
|
|
|
foreach (FolderNode *folderNode, folder->subFolderNodes()) {
|
2015-01-09 15:50:06 +01:00
|
|
|
if (ResourceEditor::ResourceTopLevelNode *rn = dynamic_cast<ResourceEditor::ResourceTopLevelNode *>(folderNode))
|
2014-02-18 21:38:03 +01:00
|
|
|
existingResourceNodes << rn;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
QList<FolderNode *> resourcesToRemove;
|
2015-02-02 00:37:38 +02:00
|
|
|
FileNameList resourcesToAdd;
|
2014-02-18 21:38:03 +01:00
|
|
|
|
|
|
|
|
SortByPath sortByPath;
|
2014-06-16 18:25:52 +04:00
|
|
|
Utils::sort(files, sortByPath);
|
|
|
|
|
Utils::sort(existingResourceNodes, sortByPath);
|
2014-02-18 21:38:03 +01:00
|
|
|
|
|
|
|
|
ProjectExplorer::compareSortedLists(existingResourceNodes, files, resourcesToRemove, resourcesToAdd, sortByPath);
|
|
|
|
|
|
|
|
|
|
QList<FolderNode *> nodesToAdd;
|
|
|
|
|
nodesToAdd.reserve(resourcesToAdd.size());
|
|
|
|
|
|
2015-02-02 00:37:38 +02:00
|
|
|
foreach (const FileName &file, resourcesToAdd)
|
2014-02-18 21:38:03 +01:00
|
|
|
nodesToAdd.append(new ResourceEditor::ResourceTopLevelNode(file, folder));
|
|
|
|
|
|
|
|
|
|
folder->removeFolderNodes(resourcesToRemove);
|
|
|
|
|
folder->addFolderNodes(nodesToAdd);
|
|
|
|
|
|
|
|
|
|
foreach (FolderNode *fn, nodesToAdd)
|
2015-01-09 15:50:06 +01:00
|
|
|
dynamic_cast<ResourceEditor::ResourceTopLevelNode *>(fn)->update();
|
2014-02-18 21:38:03 +01:00
|
|
|
}
|
2010-02-26 12:55:17 +01:00
|
|
|
};
|
2011-09-07 11:52:04 +02:00
|
|
|
}
|
2010-03-10 16:55:37 +01:00
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
QStringList QmakePriFileNode::baseVPaths(QtSupport::ProFileReader *reader, const QString &projectDir, const QString &buildDir)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-03-10 16:55:37 +01:00
|
|
|
QStringList result;
|
|
|
|
|
if (!reader)
|
|
|
|
|
return result;
|
2012-01-13 14:20:45 +01:00
|
|
|
result += reader->absolutePathValues(QLatin1String("VPATH"), projectDir);
|
2010-03-10 16:55:37 +01:00
|
|
|
result << projectDir; // QMAKE_ABSOLUTE_SOURCE_PATH
|
2012-11-28 13:46:49 +01:00
|
|
|
result << buildDir;
|
2010-03-10 16:55:37 +01:00
|
|
|
result.removeDuplicates();
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QStringList QmakePriFileNode::fullVPaths(const QStringList &baseVPaths, QtSupport::ProFileReader *reader,
|
2014-09-10 12:53:55 +02:00
|
|
|
const QString &qmakeVariable, const QString &projectDir)
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
|
|
|
|
QStringList vPaths;
|
|
|
|
|
if (!reader)
|
|
|
|
|
return vPaths;
|
2012-11-28 13:46:49 +01:00
|
|
|
vPaths = reader->absolutePathValues(QLatin1String("VPATH_") + qmakeVariable, projectDir);
|
2010-03-10 16:55:37 +01:00
|
|
|
vPaths += baseVPaths;
|
|
|
|
|
vPaths.removeDuplicates();
|
|
|
|
|
return vPaths;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
QSet<FileName> QmakePriFileNode::recursiveEnumerate(const QString &folder)
|
2010-08-10 16:27:35 +02:00
|
|
|
{
|
2015-02-01 18:44:47 +02:00
|
|
|
QSet<FileName> result;
|
2010-08-10 16:27:35 +02:00
|
|
|
QFileInfo fi(folder);
|
|
|
|
|
if (fi.isDir()) {
|
|
|
|
|
QDir dir(folder);
|
|
|
|
|
dir.setFilter(dir.filter() | QDir::NoDotAndDotDot);
|
|
|
|
|
|
|
|
|
|
foreach (const QFileInfo &file, dir.entryInfoList()) {
|
2012-01-05 15:16:26 +01:00
|
|
|
if (file.isDir() && !file.isSymLink())
|
2010-08-10 16:27:35 +02:00
|
|
|
result += recursiveEnumerate(file.absoluteFilePath());
|
2013-08-12 16:17:37 +02:00
|
|
|
else if (!Core::EditorManager::isAutoSaveFile(file.fileName()))
|
2015-02-01 18:44:47 +02:00
|
|
|
result += FileName(file);
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
|
} else if (fi.exists()) {
|
2015-02-01 18:44:47 +02:00
|
|
|
result << FileName(fi);
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2010-03-10 16:55:37 +01:00
|
|
|
|
2015-08-12 12:59:38 +02:00
|
|
|
PriFileEvalResult QmakePriFileNode::extractValues(const EvalInput &input,
|
|
|
|
|
QVector<ProFile *> includeFilesExact,
|
|
|
|
|
QVector<ProFile *> includeFilesCumlative,
|
2014-09-10 12:53:55 +02:00
|
|
|
const QList<QList<VariableAndVPathInformation>> &variableAndVPathInformation)
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
2014-09-10 12:53:55 +02:00
|
|
|
PriFileEvalResult result;
|
2012-09-07 12:35:18 +02:00
|
|
|
|
2010-08-10 16:27:35 +02:00
|
|
|
// Figure out DEPLOYMENT and INSTALL folders
|
2014-09-10 12:53:55 +02:00
|
|
|
QStringList dynamicVariables = dynamicVarNames(input.readerExact, input.readerCumulative, input.isQt5);
|
2015-08-12 12:59:38 +02:00
|
|
|
foreach (ProFile *includeFileExact, includeFilesExact)
|
2011-02-09 14:59:07 +01:00
|
|
|
foreach (const QString &dynamicVar, dynamicVariables) {
|
2014-09-10 12:53:55 +02:00
|
|
|
result.folders += input.readerExact->values(dynamicVar, includeFileExact);
|
2011-02-09 14:59:07 +01:00
|
|
|
// Ignore stuff from cumulative parse
|
|
|
|
|
// we are recursively enumerating all the files from those folders
|
2014-09-10 12:53:55 +02:00
|
|
|
// and add watchers for them, that's too dangerous if we get the folders
|
2011-02-09 14:59:07 +01:00
|
|
|
// wrong and enumerate the whole project tree multiple times
|
|
|
|
|
}
|
2010-08-10 16:27:35 +02:00
|
|
|
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
for (int i=0; i < result.folders.size(); ++i) {
|
|
|
|
|
const QFileInfo fi(result.folders.at(i));
|
2010-08-10 16:27:35 +02:00
|
|
|
if (fi.isRelative())
|
2014-09-10 12:53:55 +02:00
|
|
|
result.folders[i] = QDir::cleanPath(input.projectDir + QLatin1Char('/') + result.folders.at(i));
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
result.folders.removeDuplicates();
|
2010-08-12 15:04:24 +02:00
|
|
|
|
2010-08-12 13:38:21 +02:00
|
|
|
// Remove non existing items and non folders
|
2014-09-10 12:53:55 +02:00
|
|
|
QStringList::iterator it = result.folders.begin();
|
|
|
|
|
while (it != result.folders.end()) {
|
2010-08-11 15:25:56 +02:00
|
|
|
QFileInfo fi(*it);
|
2010-08-12 15:04:24 +02:00
|
|
|
if (fi.exists()) {
|
|
|
|
|
if (fi.isDir()) {
|
|
|
|
|
// keep directories
|
|
|
|
|
++it;
|
|
|
|
|
} else {
|
2014-09-10 12:53:55 +02:00
|
|
|
// move files directly to recursiveEnumerateFiles
|
2015-02-01 18:44:47 +02:00
|
|
|
result.recursiveEnumerateFiles << FileName::fromString(*it);
|
2014-09-10 12:53:55 +02:00
|
|
|
it = result.folders.erase(it);
|
2010-08-12 15:04:24 +02:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// do remove non exsting stuff
|
2014-09-10 12:53:55 +02:00
|
|
|
it = result.folders.erase(it);
|
2010-08-12 15:04:24 +02:00
|
|
|
}
|
2010-08-11 15:25:56 +02:00
|
|
|
}
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
foreach (const QString &folder, result.folders)
|
|
|
|
|
result.recursiveEnumerateFiles += recursiveEnumerate(folder);
|
2010-08-10 16:27:35 +02:00
|
|
|
|
2013-10-29 17:37:39 +01:00
|
|
|
const QVector<QmakeNodeStaticData::FileTypeData> &fileTypes = qmakeNodeStaticData()->fileTypeData;
|
2008-12-02 12:01:29 +01:00
|
|
|
// update files
|
2013-09-09 14:05:06 +02:00
|
|
|
QFileInfo tmpFi;
|
2009-08-17 17:59:57 +02:00
|
|
|
for (int i = 0; i < fileTypes.size(); ++i) {
|
2010-02-12 12:40:32 +01:00
|
|
|
FileType type = fileTypes.at(i).type;
|
2014-09-09 15:38:48 +02:00
|
|
|
const QList<VariableAndVPathInformation> &qmakeVariables = variableAndVPathInformation.at(i);
|
2015-02-01 18:44:47 +02:00
|
|
|
QSet<FileName> newFilePaths;
|
2014-09-09 15:38:48 +02:00
|
|
|
foreach (const VariableAndVPathInformation &qmakeVariable, qmakeVariables) {
|
2015-08-12 12:59:38 +02:00
|
|
|
foreach (ProFile *includeFileExact, includeFilesExact) {
|
2014-09-10 12:53:55 +02:00
|
|
|
QStringList tmp = input.readerExact->absoluteFileValues(qmakeVariable.variable, input.projectDir, qmakeVariable.vPathsExact, includeFileExact);
|
2013-09-09 14:05:06 +02:00
|
|
|
foreach (const QString &t, tmp) {
|
|
|
|
|
tmpFi.setFile(t);
|
|
|
|
|
if (tmpFi.isFile())
|
2015-02-01 18:44:47 +02:00
|
|
|
newFilePaths += FileName::fromString(t);
|
2013-09-09 14:05:06 +02:00
|
|
|
}
|
2011-02-09 14:59:07 +01:00
|
|
|
}
|
2015-08-12 12:59:38 +02:00
|
|
|
foreach (ProFile *includeFileCumlative, includeFilesCumlative) {
|
2014-09-10 12:53:55 +02:00
|
|
|
QStringList tmp = input.readerCumulative->absoluteFileValues(qmakeVariable.variable, input.projectDir, qmakeVariable.vPathsCumulative, includeFileCumlative);
|
2013-09-09 14:05:06 +02:00
|
|
|
foreach (const QString &t, tmp) {
|
|
|
|
|
tmpFi.setFile(t);
|
|
|
|
|
if (tmpFi.isFile())
|
2015-02-01 18:44:47 +02:00
|
|
|
newFilePaths += FileName::fromString(t);
|
2013-09-09 14:05:06 +02:00
|
|
|
}
|
2011-02-09 14:59:07 +01:00
|
|
|
}
|
2009-07-10 13:37:02 +02:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
result.foundFiles[type] = newFilePaths;
|
|
|
|
|
result.recursiveEnumerateFiles.subtract(newFilePaths);
|
2010-10-25 13:57:45 +02:00
|
|
|
}
|
|
|
|
|
|
2013-09-09 14:05:06 +02:00
|
|
|
|
2010-10-25 13:57:45 +02:00
|
|
|
for (int i = 0; i < fileTypes.size(); ++i) {
|
|
|
|
|
FileType type = fileTypes.at(i).type;
|
2015-02-01 18:44:47 +02:00
|
|
|
QSet<FileName> newFilePaths = filterFilesProVariables(type, result.foundFiles[type]);
|
2014-09-10 12:53:55 +02:00
|
|
|
newFilePaths += filterFilesRecursiveEnumerata(type, result.recursiveEnumerateFiles);
|
|
|
|
|
result.foundFiles[type] = newFilePaths;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmakePriFileNode::update(const Internal::PriFileEvalResult &result)
|
|
|
|
|
{
|
|
|
|
|
// add project file node
|
|
|
|
|
if (m_fileNodes.isEmpty())
|
2015-02-01 18:44:47 +02:00
|
|
|
addFileNodes(QList<FileNode *>() << new FileNode(m_projectFilePath, ProjectFileType, false));
|
2010-08-10 16:27:35 +02:00
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
m_recursiveEnumerateFiles = result.recursiveEnumerateFiles;
|
|
|
|
|
watchFolders(result.folders.toSet());
|
|
|
|
|
|
|
|
|
|
InternalNode contents;
|
|
|
|
|
const QVector<QmakeNodeStaticData::FileTypeData> &fileTypes = qmakeNodeStaticData()->fileTypeData;
|
|
|
|
|
for (int i = 0; i < fileTypes.size(); ++i) {
|
|
|
|
|
FileType type = fileTypes.at(i).type;
|
2015-02-01 18:44:47 +02:00
|
|
|
const QSet<FileName> &newFilePaths = result.foundFiles.value(type);
|
2010-08-10 16:27:35 +02:00
|
|
|
// We only need to save this information if
|
|
|
|
|
// we are watching folders
|
2014-09-10 12:53:55 +02:00
|
|
|
if (!result.folders.isEmpty())
|
2010-08-10 16:27:35 +02:00
|
|
|
m_files[type] = newFilePaths;
|
|
|
|
|
else
|
|
|
|
|
m_files[type].clear();
|
|
|
|
|
|
2009-08-17 17:59:57 +02:00
|
|
|
if (!newFilePaths.isEmpty()) {
|
|
|
|
|
InternalNode *subfolder = new InternalNode;
|
|
|
|
|
subfolder->type = type;
|
2010-02-12 12:40:32 +01:00
|
|
|
subfolder->icon = fileTypes.at(i).icon;
|
2012-05-04 11:49:37 +02:00
|
|
|
subfolder->fullPath = m_projectDir;
|
|
|
|
|
subfolder->typeName = fileTypes.at(i).typeName;
|
2015-11-02 17:00:46 +01:00
|
|
|
subfolder->addFileFilter = fileTypes.at(i).addFileFilter;
|
2012-05-04 11:49:37 +02:00
|
|
|
subfolder->priority = -i;
|
2010-08-10 16:27:35 +02:00
|
|
|
subfolder->displayName = fileTypes.at(i).typeName;
|
2012-05-04 11:49:37 +02:00
|
|
|
contents.virtualfolders.append(subfolder);
|
2009-08-17 17:59:57 +02:00
|
|
|
// create the hierarchy with subdirectories
|
2011-11-08 18:53:51 +01:00
|
|
|
subfolder->create(m_projectDir, newFilePaths, type);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
}
|
2010-08-10 16:27:35 +02:00
|
|
|
|
2014-02-18 19:49:55 +01:00
|
|
|
contents.updateSubFolders(this);
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakePriFileNode::watchFolders(const QSet<QString> &folders)
|
2010-08-10 16:27:35 +02:00
|
|
|
{
|
|
|
|
|
QSet<QString> toUnwatch = m_watchedFolders;
|
|
|
|
|
toUnwatch.subtract(folders);
|
|
|
|
|
|
|
|
|
|
QSet<QString> toWatch = folders;
|
|
|
|
|
toWatch.subtract(m_watchedFolders);
|
|
|
|
|
|
|
|
|
|
if (!toUnwatch.isEmpty())
|
2011-08-18 16:46:44 +02:00
|
|
|
m_project->unwatchFolders(toUnwatch.toList(), this);
|
2010-08-10 16:27:35 +02:00
|
|
|
if (!toWatch.isEmpty())
|
2011-08-18 16:46:44 +02:00
|
|
|
m_project->watchFolders(toWatch.toList(), this);
|
2010-08-10 16:27:35 +02:00
|
|
|
|
|
|
|
|
m_watchedFolders = folders;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
bool QmakePriFileNode::folderChanged(const QString &changedFolder, const QSet<FileName> &newFiles)
|
2010-08-10 16:27:35 +02:00
|
|
|
{
|
2013-10-29 16:08:37 +01:00
|
|
|
//qDebug()<<"########## QmakePriFileNode::folderChanged";
|
2013-07-01 11:35:38 +02:00
|
|
|
// So, we need to figure out which files changed.
|
|
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
QSet<FileName> addedFiles = newFiles;
|
2013-07-01 11:35:38 +02:00
|
|
|
addedFiles.subtract(m_recursiveEnumerateFiles);
|
|
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
QSet<FileName> removedFiles = m_recursiveEnumerateFiles;
|
2013-07-01 11:35:38 +02:00
|
|
|
removedFiles.subtract(newFiles);
|
|
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
foreach (const FileName &file, removedFiles) {
|
|
|
|
|
if (!file.isChildOf(FileName::fromString(changedFolder)))
|
2013-07-01 11:35:38 +02:00
|
|
|
removedFiles.remove(file);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (addedFiles.isEmpty() && removedFiles.isEmpty())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
m_recursiveEnumerateFiles = newFiles;
|
|
|
|
|
|
|
|
|
|
// Apply the differences
|
|
|
|
|
// per file type
|
2013-10-29 17:37:39 +01:00
|
|
|
const QVector<QmakeNodeStaticData::FileTypeData> &fileTypes = qmakeNodeStaticData()->fileTypeData;
|
2013-07-01 11:35:38 +02:00
|
|
|
for (int i = 0; i < fileTypes.size(); ++i) {
|
|
|
|
|
FileType type = fileTypes.at(i).type;
|
2015-02-01 18:44:47 +02:00
|
|
|
QSet<FileName> add = filterFilesRecursiveEnumerata(type, addedFiles);
|
|
|
|
|
QSet<FileName> remove = filterFilesRecursiveEnumerata(type, removedFiles);
|
2013-07-01 11:35:38 +02:00
|
|
|
|
|
|
|
|
if (!add.isEmpty() || !remove.isEmpty()) {
|
|
|
|
|
// Scream :)
|
|
|
|
|
// qDebug()<<"For type"<<fileTypes.at(i).typeName<<"\n"
|
|
|
|
|
// <<"added files"<<add<<"\n"
|
|
|
|
|
// <<"removed files"<<remove;
|
|
|
|
|
|
|
|
|
|
m_files[type].unite(add);
|
|
|
|
|
m_files[type].subtract(remove);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now apply stuff
|
|
|
|
|
InternalNode contents;
|
|
|
|
|
for (int i = 0; i < fileTypes.size(); ++i) {
|
|
|
|
|
FileType type = fileTypes.at(i).type;
|
|
|
|
|
if (!m_files[type].isEmpty()) {
|
|
|
|
|
InternalNode *subfolder = new InternalNode;
|
|
|
|
|
subfolder->type = type;
|
|
|
|
|
subfolder->icon = fileTypes.at(i).icon;
|
|
|
|
|
subfolder->fullPath = m_projectDir;
|
|
|
|
|
subfolder->typeName = fileTypes.at(i).typeName;
|
|
|
|
|
subfolder->priority = -i;
|
|
|
|
|
subfolder->displayName = fileTypes.at(i).typeName;
|
|
|
|
|
contents.virtualfolders.append(subfolder);
|
|
|
|
|
// create the hierarchy with subdirectories
|
|
|
|
|
subfolder->create(m_projectDir, m_files[type], type);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-18 19:49:55 +01:00
|
|
|
contents.updateSubFolders(this);
|
2013-07-01 11:35:38 +02:00
|
|
|
return true;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakePriFileNode::deploysFolder(const QString &folder) const
|
2010-08-24 17:17:11 +02:00
|
|
|
{
|
|
|
|
|
QString f = folder;
|
2012-01-13 14:20:45 +01:00
|
|
|
const QChar slash = QLatin1Char('/');
|
|
|
|
|
if (!f.endsWith(slash))
|
|
|
|
|
f.append(slash);
|
2014-07-07 19:02:26 +02:00
|
|
|
|
2010-08-24 17:17:11 +02:00
|
|
|
foreach (const QString &wf, m_watchedFolders) {
|
|
|
|
|
if (f.startsWith(wf)
|
2012-01-13 14:20:45 +01:00
|
|
|
&& (wf.endsWith(slash)
|
|
|
|
|
|| (wf.length() < f.length() && f.at(wf.length()) == slash)))
|
2010-08-24 17:17:11 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
QList<RunConfiguration *> QmakePriFileNode::runConfigurations() const
|
2011-01-20 18:05:58 +01:00
|
|
|
{
|
2012-04-24 15:49:09 +02:00
|
|
|
QmakeRunConfigurationFactory *factory = QmakeRunConfigurationFactory::find(m_project->activeTarget());
|
|
|
|
|
if (factory)
|
2014-04-29 08:35:00 +02:00
|
|
|
return factory->runConfigurationsForNode(m_project->activeTarget(), this);
|
2015-02-01 18:44:47 +02:00
|
|
|
return QList<RunConfiguration *>();
|
2011-01-20 18:05:58 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QList<QmakePriFileNode *> QmakePriFileNode::subProjectNodesExact() const
|
2011-09-06 17:21:51 +02:00
|
|
|
{
|
2013-10-29 14:22:31 +01:00
|
|
|
QList<QmakePriFileNode *> nodes;
|
2011-09-06 17:21:51 +02:00
|
|
|
foreach (ProjectNode *node, subProjectNodes()) {
|
2015-01-09 15:50:06 +01:00
|
|
|
QmakePriFileNode *n = dynamic_cast<QmakePriFileNode *>(node);
|
2011-09-06 17:21:51 +02:00
|
|
|
if (n && n->includedInExactParse())
|
|
|
|
|
nodes << n;
|
|
|
|
|
}
|
|
|
|
|
return nodes;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QmakeProFileNode *QmakePriFileNode::proFileNode() const
|
2013-10-28 19:42:56 +02:00
|
|
|
{
|
2013-10-29 14:22:31 +01:00
|
|
|
return m_qmakeProFileNode;
|
2013-10-28 19:42:56 +02:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakePriFileNode::includedInExactParse() const
|
2011-09-06 17:21:51 +02:00
|
|
|
{
|
|
|
|
|
return m_includedInExactParse;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakePriFileNode::setIncludedInExactParse(bool b)
|
2011-09-06 17:21:51 +02:00
|
|
|
{
|
|
|
|
|
m_includedInExactParse = b;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
QList<ProjectAction> QmakePriFileNode::supportedActions(Node *node) const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2015-02-01 18:44:47 +02:00
|
|
|
QList<ProjectAction> actions;
|
2008-12-05 14:29:18 +01:00
|
|
|
|
|
|
|
|
const FolderNode *folderNode = this;
|
2013-10-29 14:22:31 +01:00
|
|
|
const QmakeProFileNode *proFileNode;
|
2015-01-09 15:50:06 +01:00
|
|
|
while (!(proFileNode = dynamic_cast<const QmakeProFileNode*>(folderNode)))
|
2008-12-05 14:29:18 +01:00
|
|
|
folderNode = folderNode->parentFolderNode();
|
2008-12-17 15:51:48 +01:00
|
|
|
Q_ASSERT(proFileNode);
|
2008-12-05 14:29:18 +01:00
|
|
|
|
|
|
|
|
switch (proFileNode->projectType()) {
|
|
|
|
|
case ApplicationTemplate:
|
2015-03-17 11:39:48 +02:00
|
|
|
case StaticLibraryTemplate:
|
|
|
|
|
case SharedLibraryTemplate:
|
2011-05-05 17:42:35 +02:00
|
|
|
case AuxTemplate: {
|
|
|
|
|
// TODO: Some of the file types don't make much sense for aux
|
|
|
|
|
// projects (e.g. cpp). It'd be nice if the "add" action could
|
|
|
|
|
// work on a subset of the file types according to project type.
|
|
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
actions << AddNewFile;
|
2015-10-29 17:53:47 +01:00
|
|
|
if (m_recursiveEnumerateFiles.contains(node->filePath()))
|
2015-02-01 18:44:47 +02:00
|
|
|
actions << EraseFile;
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
else
|
2015-02-01 18:44:47 +02:00
|
|
|
actions << RemoveFile;
|
2010-08-24 17:17:11 +02:00
|
|
|
|
2010-08-24 18:22:57 +02:00
|
|
|
bool addExistingFiles = true;
|
2015-02-01 18:44:47 +02:00
|
|
|
if (node->nodeType() == VirtualFolderNodeType) {
|
2010-08-24 18:22:57 +02:00
|
|
|
// A virtual folder, we do what the projectexplorer does
|
2015-02-18 13:10:40 +01:00
|
|
|
FolderNode *folder = node->asFolderNode();
|
2010-08-24 18:22:57 +02:00
|
|
|
if (folder) {
|
|
|
|
|
QStringList list;
|
|
|
|
|
foreach (FolderNode *f, folder->subFolderNodes())
|
2015-10-29 17:53:47 +01:00
|
|
|
list << f->filePath().toString() + QLatin1Char('/');
|
2010-08-24 18:22:57 +02:00
|
|
|
if (deploysFolder(Utils::commonPath(list)))
|
|
|
|
|
addExistingFiles = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-29 17:53:47 +01:00
|
|
|
addExistingFiles = addExistingFiles && !deploysFolder(node->filePath().toString());
|
2010-08-24 18:22:57 +02:00
|
|
|
|
|
|
|
|
if (addExistingFiles)
|
2015-02-01 18:44:47 +02:00
|
|
|
actions << AddExistingFile << AddExistingDirectory;
|
2010-08-24 17:17:11 +02:00
|
|
|
|
2008-12-05 14:29:18 +01:00
|
|
|
break;
|
2010-08-24 18:22:57 +02:00
|
|
|
}
|
2008-12-05 14:29:18 +01:00
|
|
|
case SubDirsTemplate:
|
2015-02-01 18:44:47 +02:00
|
|
|
actions << AddSubProject << RemoveSubProject;
|
2008-12-05 14:29:18 +01:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2010-05-11 14:13:38 +02:00
|
|
|
|
2015-02-18 13:10:40 +01:00
|
|
|
FileNode *fileNode = node->asFileNode();
|
2015-02-01 18:44:47 +02:00
|
|
|
if ((fileNode && fileNode->fileType() != ProjectFileType)
|
2016-04-08 16:25:29 +02:00
|
|
|
|| dynamic_cast<ResourceEditor::ResourceTopLevelNode *>(node)) {
|
2015-02-01 18:44:47 +02:00
|
|
|
actions << Rename;
|
2016-04-08 16:25:29 +02:00
|
|
|
actions << DuplicateFile;
|
|
|
|
|
}
|
2010-05-11 14:13:38 +02:00
|
|
|
|
2011-10-28 10:15:04 +00:00
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
Target *target = m_project->activeTarget();
|
2012-04-24 15:49:09 +02:00
|
|
|
QmakeRunConfigurationFactory *factory = QmakeRunConfigurationFactory::find(target);
|
|
|
|
|
if (factory && !factory->runConfigurationsForNode(target, node).isEmpty())
|
2015-02-01 18:44:47 +02:00
|
|
|
actions << HasSubProjectRunConfigurations;
|
2011-01-20 18:05:58 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
return actions;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakePriFileNode::canAddSubProject(const QString &proFilePath) const
|
2010-08-26 18:33:16 +02:00
|
|
|
{
|
|
|
|
|
QFileInfo fi(proFilePath);
|
|
|
|
|
if (fi.suffix() == QLatin1String("pro")
|
|
|
|
|
|| fi.suffix() == QLatin1String("pri"))
|
|
|
|
|
return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-27 15:44:15 +02:00
|
|
|
static QString simplifyProFilePath(const QString &proFilePath)
|
|
|
|
|
{
|
|
|
|
|
// if proFilePath is like: _path_/projectName/projectName.pro
|
|
|
|
|
// we simplify it to: _path_/projectName
|
|
|
|
|
QFileInfo fi(proFilePath);
|
|
|
|
|
const QString parentPath = fi.absolutePath();
|
|
|
|
|
QFileInfo parentFi(parentPath);
|
|
|
|
|
if (parentFi.fileName() == fi.completeBaseName())
|
|
|
|
|
return parentPath;
|
|
|
|
|
return proFilePath;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakePriFileNode::addSubProjects(const QStringList &proFilePaths)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2015-02-01 18:44:47 +02:00
|
|
|
FindAllFilesVisitor visitor;
|
2010-08-26 18:33:16 +02:00
|
|
|
accept(&visitor);
|
2015-02-28 21:45:07 +02:00
|
|
|
const FileNameList &allFiles = visitor.filePaths();
|
2010-08-26 18:33:16 +02:00
|
|
|
|
|
|
|
|
QStringList uniqueProFilePaths;
|
2010-08-27 15:44:15 +02:00
|
|
|
foreach (const QString &proFile, proFilePaths)
|
2015-02-28 21:45:07 +02:00
|
|
|
if (!allFiles.contains(FileName::fromString(proFile)))
|
2010-08-27 15:44:15 +02:00
|
|
|
uniqueProFilePaths.append(simplifyProFilePath(proFile));
|
2010-08-26 18:33:16 +02:00
|
|
|
|
|
|
|
|
QStringList failedFiles;
|
2013-07-01 16:13:48 +02:00
|
|
|
changeFiles(QLatin1String(Constants::PROFILE_MIMETYPE), uniqueProFilePaths, &failedFiles, AddToProFile);
|
2010-08-26 18:33:16 +02:00
|
|
|
|
|
|
|
|
return failedFiles.isEmpty();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakePriFileNode::removeSubProjects(const QStringList &proFilePaths)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-08-27 15:44:15 +02:00
|
|
|
QStringList failedOriginalFiles;
|
2013-07-01 16:13:48 +02:00
|
|
|
changeFiles(QLatin1String(Constants::PROFILE_MIMETYPE), proFilePaths, &failedOriginalFiles, RemoveFromProFile);
|
2010-08-27 15:44:15 +02:00
|
|
|
|
2014-07-07 19:02:26 +02:00
|
|
|
QStringList simplifiedProFiles = Utils::transform(failedOriginalFiles, &simplifyProFilePath);
|
2010-08-27 15:44:15 +02:00
|
|
|
|
|
|
|
|
QStringList failedSimplifiedFiles;
|
2013-07-01 16:13:48 +02:00
|
|
|
changeFiles(QLatin1String(Constants::PROFILE_MIMETYPE), simplifiedProFiles, &failedSimplifiedFiles, RemoveFromProFile);
|
2010-08-27 15:44:15 +02:00
|
|
|
|
|
|
|
|
return failedSimplifiedFiles.isEmpty();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakePriFileNode::addFiles(const QStringList &filePaths, QStringList *notAdded)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-05-18 16:29:41 +02:00
|
|
|
// If a file is already referenced in the .pro file then we don't add them.
|
|
|
|
|
// That ignores scopes and which variable was used to reference the file
|
|
|
|
|
// So it's obviously a bit limited, but in those cases you need to edit the
|
|
|
|
|
// project files manually anyway.
|
|
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
FindAllFilesVisitor visitor;
|
2010-05-18 16:29:41 +02:00
|
|
|
accept(&visitor);
|
2015-02-28 21:45:07 +02:00
|
|
|
const FileNameList &allFiles = visitor.filePaths();
|
2010-05-18 16:29:41 +02:00
|
|
|
|
2013-07-01 16:13:48 +02:00
|
|
|
typedef QMap<QString, QStringList> TypeFileMap;
|
|
|
|
|
// Split into lists by file type and bulk-add them.
|
|
|
|
|
TypeFileMap typeFileMap;
|
2015-02-04 09:32:46 +01:00
|
|
|
Utils::MimeDatabase mdb;
|
2014-07-24 11:44:35 +02:00
|
|
|
foreach (const QString &file, filePaths) {
|
2015-02-04 09:32:46 +01:00
|
|
|
const Utils::MimeType mt = mdb.mimeTypeForFile(file);
|
|
|
|
|
typeFileMap[mt.name()] << file;
|
2010-06-08 12:15:43 +02:00
|
|
|
}
|
|
|
|
|
|
2013-07-01 16:13:48 +02:00
|
|
|
QStringList failedFiles;
|
|
|
|
|
foreach (const QString &type, typeFileMap.keys()) {
|
|
|
|
|
const QStringList typeFiles = typeFileMap.value(type);
|
|
|
|
|
QStringList qrcFiles; // the list of qrc files referenced from ui files
|
|
|
|
|
if (type == QLatin1String(ProjectExplorer::Constants::RESOURCE_MIMETYPE)) {
|
|
|
|
|
foreach (const QString &formFile, typeFiles) {
|
|
|
|
|
QStringList resourceFiles = formResources(formFile);
|
|
|
|
|
foreach (const QString &resourceFile, resourceFiles)
|
|
|
|
|
if (!qrcFiles.contains(resourceFile))
|
|
|
|
|
qrcFiles.append(resourceFile);
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-06-08 12:15:43 +02:00
|
|
|
|
2013-07-01 16:13:48 +02:00
|
|
|
QStringList uniqueQrcFiles;
|
|
|
|
|
foreach (const QString &file, qrcFiles) {
|
2015-02-28 21:45:07 +02:00
|
|
|
if (!allFiles.contains(FileName::fromString(file)))
|
2013-07-01 16:13:48 +02:00
|
|
|
uniqueQrcFiles.append(file);
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-07-01 16:13:48 +02:00
|
|
|
QStringList uniqueFilePaths;
|
|
|
|
|
foreach (const QString &file, typeFiles) {
|
2015-02-28 21:45:07 +02:00
|
|
|
if (!allFiles.contains(FileName::fromString(file)))
|
2013-07-01 16:13:48 +02:00
|
|
|
uniqueFilePaths.append(file);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
changeFiles(type, uniqueFilePaths, &failedFiles, AddToProFile);
|
|
|
|
|
if (notAdded)
|
|
|
|
|
*notAdded += failedFiles;
|
|
|
|
|
changeFiles(QLatin1String(ProjectExplorer::Constants::RESOURCE_MIMETYPE), uniqueQrcFiles, &failedFiles, AddToProFile);
|
|
|
|
|
if (notAdded)
|
|
|
|
|
*notAdded += failedFiles;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
return failedFiles.isEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakePriFileNode::removeFiles(const QStringList &filePaths,
|
2008-12-02 12:01:29 +01:00
|
|
|
QStringList *notRemoved)
|
|
|
|
|
{
|
|
|
|
|
QStringList failedFiles;
|
2013-07-01 16:13:48 +02:00
|
|
|
typedef QMap<QString, QStringList> TypeFileMap;
|
|
|
|
|
// Split into lists by file type and bulk-add them.
|
|
|
|
|
TypeFileMap typeFileMap;
|
2015-02-04 09:32:46 +01:00
|
|
|
Utils::MimeDatabase mdb;
|
2014-07-24 11:44:35 +02:00
|
|
|
foreach (const QString &file, filePaths) {
|
2015-02-04 09:32:46 +01:00
|
|
|
const Utils::MimeType mt = mdb.mimeTypeForFile(file);
|
|
|
|
|
typeFileMap[mt.name()] << file;
|
2013-07-01 16:13:48 +02:00
|
|
|
}
|
|
|
|
|
foreach (const QString &type, typeFileMap.keys()) {
|
|
|
|
|
const QStringList typeFiles = typeFileMap.value(type);
|
|
|
|
|
changeFiles(type, typeFiles, &failedFiles, RemoveFromProFile);
|
|
|
|
|
if (notRemoved)
|
|
|
|
|
*notRemoved = failedFiles;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
return failedFiles.isEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakePriFileNode::deleteFiles(const QStringList &filePaths)
|
2010-08-10 16:27:35 +02:00
|
|
|
{
|
2014-02-26 10:36:59 +02:00
|
|
|
removeFiles(filePaths);
|
2010-08-10 16:27:35 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-14 15:33:50 +02:00
|
|
|
bool QmakePriFileNode::canRenameFile(const QString &filePath, const QString &newFilePath)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2008-12-05 14:29:18 +01:00
|
|
|
if (newFilePath.isEmpty())
|
2008-12-02 12:01:29 +01:00
|
|
|
return false;
|
|
|
|
|
|
2012-04-18 11:50:32 +02:00
|
|
|
bool changeProFileOptional = deploysFolder(QFileInfo(filePath).absolutePath());
|
2015-09-14 15:33:50 +02:00
|
|
|
if (changeProFileOptional)
|
|
|
|
|
return true;
|
2015-02-04 09:32:46 +01:00
|
|
|
Utils::MimeDatabase mdb;
|
|
|
|
|
const Utils::MimeType mt = mdb.mimeTypeForFile(newFilePath);
|
2013-07-01 16:13:48 +02:00
|
|
|
|
2015-09-14 15:33:50 +02:00
|
|
|
return renameFile(filePath, newFilePath, mt.name(), Change::TestOnly);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool QmakePriFileNode::renameFile(const QString &filePath, const QString &newFilePath)
|
|
|
|
|
{
|
|
|
|
|
if (newFilePath.isEmpty())
|
2008-12-02 12:01:29 +01:00
|
|
|
return false;
|
2015-09-14 15:33:50 +02:00
|
|
|
|
|
|
|
|
bool changeProFileOptional = deploysFolder(QFileInfo(filePath).absolutePath());
|
|
|
|
|
Utils::MimeDatabase mdb;
|
|
|
|
|
const Utils::MimeType mt = mdb.mimeTypeForFile(newFilePath);
|
|
|
|
|
|
|
|
|
|
if (renameFile(filePath, newFilePath, mt.name()))
|
|
|
|
|
return true;
|
|
|
|
|
return changeProFileOptional;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
FolderNode::AddNewInformation QmakePriFileNode::addNewInformation(const QStringList &files, Node *context) const
|
2014-02-18 16:31:36 +01:00
|
|
|
{
|
|
|
|
|
Q_UNUSED(files)
|
2015-10-29 17:53:47 +01:00
|
|
|
return FolderNode::AddNewInformation(filePath().fileName(), context && context->projectNode() == this ? 120 : 90);
|
2014-02-18 16:31:36 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakePriFileNode::priFileWritable(const QString &path)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2014-09-20 21:52:56 +02:00
|
|
|
ReadOnlyFilesDialog roDialog(path, ICore::mainWindow());
|
2012-10-15 11:53:22 +02:00
|
|
|
roDialog.setShowFailWarning(true);
|
2014-09-20 21:52:56 +02:00
|
|
|
return roDialog.exec() != ReadOnlyFilesDialog::RO_Cancel;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakePriFileNode::saveModifiedEditors()
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2013-07-18 12:26:23 +02:00
|
|
|
Core::IDocument *document
|
2015-02-02 00:37:38 +02:00
|
|
|
= Core::DocumentModel::documentForFilePath(m_projectFilePath.toString());
|
2013-07-18 12:26:23 +02:00
|
|
|
if (!document || !document->isModified())
|
|
|
|
|
return true;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2014-11-10 22:26:54 +02:00
|
|
|
if (!Core::DocumentManager::saveDocument(document))
|
2013-07-18 12:26:23 +02:00
|
|
|
return false;
|
2014-11-10 22:26:54 +02:00
|
|
|
|
2013-07-18 12:26:23 +02:00
|
|
|
// force instant reload of ourselves
|
2015-02-02 00:37:38 +02:00
|
|
|
QtSupport::ProFileCacheManager::instance()->discardFile(m_projectFilePath.toString());
|
2016-01-08 11:31:06 +01:00
|
|
|
m_project->projectManager()->notifyChanged(m_projectFilePath);
|
2008-12-02 12:01:29 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QStringList QmakePriFileNode::formResources(const QString &formFile) const
|
2010-06-08 12:15:43 +02:00
|
|
|
{
|
|
|
|
|
QStringList resourceFiles;
|
|
|
|
|
QFile file(formFile);
|
2013-02-12 10:13:43 +01:00
|
|
|
if (!file.open(QIODevice::ReadOnly))
|
|
|
|
|
return resourceFiles;
|
|
|
|
|
|
2010-06-08 12:15:43 +02:00
|
|
|
QXmlStreamReader reader(&file);
|
|
|
|
|
|
|
|
|
|
QFileInfo fi(formFile);
|
|
|
|
|
QDir formDir = fi.absoluteDir();
|
|
|
|
|
while (!reader.atEnd()) {
|
|
|
|
|
reader.readNext();
|
|
|
|
|
if (reader.isStartElement()) {
|
|
|
|
|
if (reader.name() == QLatin1String("iconset")) {
|
|
|
|
|
const QXmlStreamAttributes attributes = reader.attributes();
|
|
|
|
|
if (attributes.hasAttribute(QLatin1String("resource")))
|
|
|
|
|
resourceFiles.append(QDir::cleanPath(formDir.absoluteFilePath(
|
|
|
|
|
attributes.value(QLatin1String("resource")).toString())));
|
|
|
|
|
} else if (reader.name() == QLatin1String("include")) {
|
|
|
|
|
const QXmlStreamAttributes attributes = reader.attributes();
|
|
|
|
|
if (attributes.hasAttribute(QLatin1String("location")))
|
|
|
|
|
resourceFiles.append(QDir::cleanPath(formDir.absoluteFilePath(
|
|
|
|
|
attributes.value(QLatin1String("location")).toString())));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (reader.hasError())
|
|
|
|
|
qWarning() << "Could not read form file:" << formFile;
|
|
|
|
|
|
|
|
|
|
return resourceFiles;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakePriFileNode::ensureWriteableProFile(const QString &file)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-05-18 13:48:57 +02:00
|
|
|
// Ensure that the file is not read only
|
2013-09-26 18:38:44 +02:00
|
|
|
QFileInfo fi(file);
|
2010-05-18 13:48:57 +02:00
|
|
|
if (!fi.isWritable()) {
|
|
|
|
|
// Try via vcs manager
|
2013-08-30 17:13:29 +02:00
|
|
|
Core::IVersionControl *versionControl = Core::VcsManager::findVersionControlForDirectory(fi.absolutePath());
|
2014-08-18 17:30:35 +02:00
|
|
|
if (!versionControl || !versionControl->vcsOpen(file)) {
|
2013-09-26 18:38:44 +02:00
|
|
|
bool makeWritable = QFile::setPermissions(file, fi.permissions() | QFile::WriteUser);
|
2010-05-18 13:48:57 +02:00
|
|
|
if (!makeWritable) {
|
2012-01-24 15:36:40 +01:00
|
|
|
QMessageBox::warning(Core::ICore::mainWindow(),
|
2015-01-09 15:50:06 +01:00
|
|
|
QCoreApplication::translate("QmakePriFileNode", "Failed"),
|
|
|
|
|
QCoreApplication::translate("QmakePriFileNode", "Could not write project file %1.").arg(file));
|
2013-09-26 18:38:44 +02:00
|
|
|
return false;
|
2010-05-18 13:48:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-09-26 18:38:44 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
2010-05-18 13:48:57 +02:00
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QPair<ProFile *, QStringList> QmakePriFileNode::readProFile(const QString &file)
|
2013-09-26 18:38:44 +02:00
|
|
|
{
|
2010-01-14 22:58:55 +01:00
|
|
|
QStringList lines;
|
2013-09-26 18:38:44 +02:00
|
|
|
ProFile *includeFile = 0;
|
2010-01-14 22:58:55 +01:00
|
|
|
{
|
|
|
|
|
QString contents;
|
|
|
|
|
{
|
2015-02-01 18:44:47 +02:00
|
|
|
FileReader reader;
|
2013-09-26 18:38:44 +02:00
|
|
|
if (!reader.fetch(file, QIODevice::Text)) {
|
2013-10-29 14:22:31 +01:00
|
|
|
QmakeProject::proFileParseError(reader.errorString());
|
2013-09-26 18:38:44 +02:00
|
|
|
return qMakePair(includeFile, lines);
|
2010-01-14 22:58:55 +01:00
|
|
|
}
|
2011-03-30 15:15:15 +02:00
|
|
|
contents = QString::fromLocal8Bit(reader.data());
|
|
|
|
|
lines = contents.split(QLatin1Char('\n'));
|
2010-01-14 22:58:55 +01:00
|
|
|
}
|
|
|
|
|
|
2013-05-29 20:18:51 +02:00
|
|
|
QMakeVfs vfs;
|
2011-05-20 21:40:53 +02:00
|
|
|
QtSupport::ProMessageHandler handler;
|
2013-05-29 20:18:51 +02:00
|
|
|
QMakeParser parser(0, &vfs, &handler);
|
2016-05-13 15:32:50 +02:00
|
|
|
includeFile = parser.parsedProBlock(QStringRef(&contents), file, 1);
|
2008-12-05 14:29:18 +01:00
|
|
|
}
|
2013-09-26 18:38:44 +02:00
|
|
|
return qMakePair(includeFile, lines);
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-14 15:33:50 +02:00
|
|
|
bool QmakePriFileNode::prepareForChange()
|
|
|
|
|
{
|
|
|
|
|
return saveModifiedEditors() && ensureWriteableProFile(m_projectFilePath.toString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool QmakePriFileNode::renameFile(const QString &oldName,
|
|
|
|
|
const QString &newName,
|
|
|
|
|
const QString &mimeType,
|
|
|
|
|
Change mode)
|
|
|
|
|
{
|
|
|
|
|
if (!prepareForChange())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
QPair<ProFile *, QStringList> pair = readProFile(m_projectFilePath.toString());
|
|
|
|
|
ProFile *includeFile = pair.first;
|
|
|
|
|
QStringList lines = pair.second;
|
|
|
|
|
|
|
|
|
|
if (!includeFile)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
QDir priFileDir = QDir(m_qmakeProFileNode->m_projectDir);
|
|
|
|
|
QStringList notChanged = ProWriter::removeFiles(includeFile, &lines, priFileDir,
|
|
|
|
|
QStringList(oldName), varNamesForRemoving());
|
2015-10-27 18:08:39 +01:00
|
|
|
|
|
|
|
|
includeFile->deref();
|
|
|
|
|
if (!notChanged.isEmpty())
|
2015-09-14 15:33:50 +02:00
|
|
|
return false;
|
2015-10-27 18:08:39 +01:00
|
|
|
|
|
|
|
|
// We need to re-parse here: The file has changed.
|
|
|
|
|
QMakeParser parser(0, 0, 0);
|
2016-05-13 15:32:50 +02:00
|
|
|
QString contents = lines.join(QLatin1Char('\n'));
|
|
|
|
|
includeFile = parser.parsedProBlock(QStringRef(&contents),
|
2015-10-27 18:08:39 +01:00
|
|
|
m_projectFilePath.toString(), 1, QMakeParser::FullGrammar);
|
|
|
|
|
QTC_ASSERT(includeFile, return false); // The file should still be valid after what we did.
|
2015-09-14 15:33:50 +02:00
|
|
|
|
|
|
|
|
ProWriter::addFiles(includeFile, &lines,
|
|
|
|
|
QStringList(newName),
|
|
|
|
|
varNameForAdding(mimeType));
|
|
|
|
|
if (mode == Change::Save)
|
|
|
|
|
save(lines);
|
|
|
|
|
includeFile->deref();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakePriFileNode::changeFiles(const QString &mimeType,
|
2013-09-26 18:38:44 +02:00
|
|
|
const QStringList &filePaths,
|
|
|
|
|
QStringList *notChanged,
|
2015-09-14 15:33:50 +02:00
|
|
|
ChangeType change, Change mode)
|
2013-09-26 18:38:44 +02:00
|
|
|
{
|
|
|
|
|
if (filePaths.isEmpty())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
*notChanged = filePaths;
|
|
|
|
|
|
|
|
|
|
// Check for modified editors
|
2015-09-14 15:33:50 +02:00
|
|
|
if (!prepareForChange())
|
2013-09-26 18:38:44 +02:00
|
|
|
return;
|
|
|
|
|
|
2015-02-02 00:37:38 +02:00
|
|
|
QPair<ProFile *, QStringList> pair = readProFile(m_projectFilePath.toString());
|
2013-09-26 18:38:44 +02:00
|
|
|
ProFile *includeFile = pair.first;
|
|
|
|
|
QStringList lines = pair.second;
|
|
|
|
|
|
|
|
|
|
if (!includeFile)
|
|
|
|
|
return;
|
2008-12-05 14:29:18 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
if (change == AddToProFile) {
|
2010-05-18 14:59:51 +02:00
|
|
|
// Use the first variable for adding.
|
2014-04-11 15:59:56 +02:00
|
|
|
ProWriter::addFiles(includeFile, &lines, filePaths, varNameForAdding(mimeType));
|
2010-01-14 22:58:55 +01:00
|
|
|
notChanged->clear();
|
2008-12-02 12:01:29 +01:00
|
|
|
} else { // RemoveFromProFile
|
2014-04-11 15:59:56 +02:00
|
|
|
QDir priFileDir = QDir(m_qmakeProFileNode->m_projectDir);
|
2013-08-08 19:32:33 +02:00
|
|
|
*notChanged = ProWriter::removeFiles(includeFile, &lines, priFileDir, filePaths, varNamesForRemoving());
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// save file
|
2015-09-14 15:33:50 +02:00
|
|
|
if (mode == Change::Save)
|
|
|
|
|
save(lines);
|
2013-09-26 18:38:44 +02:00
|
|
|
includeFile->deref();
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-07 12:56:59 +01:00
|
|
|
bool QmakePriFileNode::setProVariable(const QString &var, const QStringList &values, const QString &scope, int flags)
|
2013-09-26 18:38:44 +02:00
|
|
|
{
|
2015-09-14 15:33:50 +02:00
|
|
|
if (!prepareForChange())
|
2013-09-26 18:38:44 +02:00
|
|
|
return false;
|
|
|
|
|
|
2015-02-02 00:37:38 +02:00
|
|
|
QPair<ProFile *, QStringList> pair = readProFile(m_projectFilePath.toString());
|
2013-09-26 18:38:44 +02:00
|
|
|
ProFile *includeFile = pair.first;
|
|
|
|
|
QStringList lines = pair.second;
|
|
|
|
|
|
2014-03-07 12:56:59 +01:00
|
|
|
ProWriter::putVarValues(includeFile, &lines, values, var,
|
|
|
|
|
ProWriter::PutFlags(flags),
|
|
|
|
|
scope);
|
2013-09-26 18:38:44 +02:00
|
|
|
|
|
|
|
|
if (!includeFile)
|
|
|
|
|
return false;
|
|
|
|
|
save(lines);
|
|
|
|
|
includeFile->deref();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakePriFileNode::save(const QStringList &lines)
|
2013-09-26 18:38:44 +02:00
|
|
|
{
|
2016-07-18 10:04:42 +02:00
|
|
|
{
|
|
|
|
|
FileChangeBlocker changeGuard(m_projectFilePath.toString());
|
|
|
|
|
FileSaver saver(m_projectFilePath.toString(), QIODevice::Text);
|
|
|
|
|
saver.write(lines.join(QLatin1Char('\n')).toLocal8Bit());
|
|
|
|
|
saver.finalize(Core::ICore::mainWindow());
|
|
|
|
|
|
|
|
|
|
m_project->projectManager()->notifyChanged(m_projectFilePath);
|
|
|
|
|
}
|
2010-01-14 21:51:34 +01:00
|
|
|
|
2010-05-18 15:02:53 +02:00
|
|
|
// This is a hack.
|
|
|
|
|
// We are saving twice in a very short timeframe, once the editor and once the ProFile.
|
|
|
|
|
// So the modification time might not change between those two saves.
|
|
|
|
|
// We manually tell each editor to reload it's file.
|
|
|
|
|
// (The .pro files are notified by the file system watcher.)
|
2011-04-04 15:24:13 +02:00
|
|
|
QStringList errorStrings;
|
2015-02-02 00:37:38 +02:00
|
|
|
Core::IDocument *document = Core::DocumentModel::documentForFilePath(m_projectFilePath.toString());
|
2013-07-18 12:26:23 +02:00
|
|
|
if (document) {
|
|
|
|
|
QString errorString;
|
|
|
|
|
if (!document->reload(&errorString, Core::IDocument::FlagReload, Core::IDocument::TypeContents))
|
|
|
|
|
errorStrings << errorString;
|
2010-01-22 16:49:57 +01:00
|
|
|
}
|
2011-04-04 15:24:13 +02:00
|
|
|
if (!errorStrings.isEmpty())
|
2015-01-09 15:50:06 +01:00
|
|
|
QMessageBox::warning(Core::ICore::mainWindow(), QCoreApplication::translate("QmakePriFileNode", "File Error"),
|
2014-08-23 01:19:53 +02:00
|
|
|
errorStrings.join(QLatin1Char('\n')));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
QStringList QmakePriFileNode::varNames(FileType type, QtSupport::ProFileReader *readerExact)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
|
QStringList vars;
|
|
|
|
|
switch (type) {
|
2015-02-01 18:44:47 +02:00
|
|
|
case HeaderType:
|
2008-12-02 12:01:29 +01:00
|
|
|
vars << QLatin1String("HEADERS");
|
2013-11-11 14:49:59 +01:00
|
|
|
vars << QLatin1String("PRECOMPILED_HEADER");
|
2008-12-02 12:01:29 +01:00
|
|
|
break;
|
2015-02-01 18:44:47 +02:00
|
|
|
case SourceType: {
|
2008-12-02 12:01:29 +01:00
|
|
|
vars << QLatin1String("SOURCES");
|
2014-01-24 15:16:06 +01:00
|
|
|
QStringList listOfExtraCompilers = readerExact->values(QLatin1String("QMAKE_EXTRA_COMPILERS"));
|
|
|
|
|
foreach (const QString &var, listOfExtraCompilers) {
|
|
|
|
|
QStringList inputs = readerExact->values(var + QLatin1String(".input"));
|
|
|
|
|
foreach (const QString &input, inputs)
|
2016-01-15 16:00:09 +01:00
|
|
|
// FORMS, RESOURCES, and STATECHARTS are handled below, HEADERS above
|
2014-02-13 12:01:28 +01:00
|
|
|
if (input != QLatin1String("FORMS")
|
2016-01-15 16:00:09 +01:00
|
|
|
&& input != QLatin1String("STATECHARTS")
|
2014-02-13 12:01:28 +01:00
|
|
|
&& input != QLatin1String("RESOURCES")
|
|
|
|
|
&& input != QLatin1String("HEADERS"))
|
2014-01-24 15:16:06 +01:00
|
|
|
vars << input;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
break;
|
2014-01-24 15:16:06 +01:00
|
|
|
}
|
2015-02-01 18:44:47 +02:00
|
|
|
case ResourceType:
|
2008-12-02 12:01:29 +01:00
|
|
|
vars << QLatin1String("RESOURCES");
|
|
|
|
|
break;
|
2015-02-01 18:44:47 +02:00
|
|
|
case FormType:
|
2008-12-02 12:01:29 +01:00
|
|
|
vars << QLatin1String("FORMS");
|
|
|
|
|
break;
|
2016-01-15 16:00:09 +01:00
|
|
|
case StateChartType:
|
|
|
|
|
vars << QLatin1String("STATECHARTS");
|
|
|
|
|
break;
|
2015-02-01 18:44:47 +02:00
|
|
|
case ProjectFileType:
|
2010-08-26 18:33:16 +02:00
|
|
|
vars << QLatin1String("SUBDIRS");
|
|
|
|
|
break;
|
2015-02-01 18:44:47 +02:00
|
|
|
case QMLType:
|
2011-06-20 16:10:42 +02:00
|
|
|
vars << QLatin1String("OTHER_FILES");
|
2014-08-06 14:03:11 +02:00
|
|
|
vars << QLatin1String("DISTFILES");
|
2010-08-10 16:27:35 +02:00
|
|
|
break;
|
2008-12-02 12:01:29 +01:00
|
|
|
default:
|
|
|
|
|
vars << QLatin1String("OTHER_FILES");
|
2014-08-06 14:03:11 +02:00
|
|
|
vars << QLatin1String("DISTFILES");
|
2010-11-22 15:10:20 +01:00
|
|
|
vars << QLatin1String("ICON");
|
2014-08-06 15:00:26 +02:00
|
|
|
vars << QLatin1String("QMAKE_INFO_PLIST");
|
2008-12-02 12:01:29 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return vars;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-01 16:13:48 +02:00
|
|
|
//!
|
2013-10-29 16:08:37 +01:00
|
|
|
//! \brief QmakePriFileNode::varNames
|
2013-07-01 16:13:48 +02:00
|
|
|
//! \param mimeType
|
|
|
|
|
//! \return the qmake variable name for the mime type
|
2013-08-08 19:32:33 +02:00
|
|
|
//! Note: Only used for adding.
|
2013-07-01 16:13:48 +02:00
|
|
|
//!
|
2013-10-29 14:22:31 +01:00
|
|
|
QString QmakePriFileNode::varNameForAdding(const QString &mimeType)
|
2013-07-01 16:13:48 +02:00
|
|
|
{
|
|
|
|
|
if (mimeType == QLatin1String(ProjectExplorer::Constants::CPP_HEADER_MIMETYPE)
|
|
|
|
|
|| mimeType == QLatin1String(ProjectExplorer::Constants::C_HEADER_MIMETYPE)) {
|
2013-08-08 19:32:33 +02:00
|
|
|
return QLatin1String("HEADERS");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mimeType == QLatin1String(ProjectExplorer::Constants::CPP_SOURCE_MIMETYPE)
|
2013-07-01 16:13:48 +02:00
|
|
|
|| mimeType == QLatin1String(ProjectExplorer::Constants::C_SOURCE_MIMETYPE)) {
|
2013-08-08 19:32:33 +02:00
|
|
|
return QLatin1String("SOURCES");
|
2013-07-01 16:13:48 +02:00
|
|
|
}
|
2013-08-08 19:32:33 +02:00
|
|
|
|
|
|
|
|
if (mimeType == QLatin1String(CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE))
|
|
|
|
|
return QLatin1String("OBJECTIVE_SOURCES");
|
|
|
|
|
|
|
|
|
|
if (mimeType == QLatin1String(ProjectExplorer::Constants::RESOURCE_MIMETYPE))
|
|
|
|
|
return QLatin1String("RESOURCES");
|
|
|
|
|
|
|
|
|
|
if (mimeType == QLatin1String(ProjectExplorer::Constants::FORM_MIMETYPE))
|
|
|
|
|
return QLatin1String("FORMS");
|
|
|
|
|
|
|
|
|
|
if (mimeType == QLatin1String(ProjectExplorer::Constants::QML_MIMETYPE))
|
2014-08-06 15:07:33 +02:00
|
|
|
return QLatin1String("DISTFILES");
|
2013-08-08 19:32:33 +02:00
|
|
|
|
2016-07-13 15:10:21 +02:00
|
|
|
if (mimeType == QLatin1String(ProjectExplorer::Constants::SCXML_MIMETYPE))
|
|
|
|
|
return QLatin1String("STATECHARTS");
|
|
|
|
|
|
2013-08-08 19:32:33 +02:00
|
|
|
if (mimeType == QLatin1String(Constants::PROFILE_MIMETYPE))
|
|
|
|
|
return QLatin1String("SUBDIRS");
|
|
|
|
|
|
2014-08-06 15:07:33 +02:00
|
|
|
return QLatin1String("DISTFILES");
|
2013-07-01 16:13:48 +02:00
|
|
|
}
|
|
|
|
|
|
2013-08-08 19:32:33 +02:00
|
|
|
//!
|
2013-10-29 16:08:37 +01:00
|
|
|
//! \brief QmakePriFileNode::varNamesForRemoving
|
2013-08-08 19:32:33 +02:00
|
|
|
//! \return all qmake variables which are displayed in the project tree
|
|
|
|
|
//! Note: Only used for removing.
|
|
|
|
|
//!
|
2013-10-29 14:22:31 +01:00
|
|
|
QStringList QmakePriFileNode::varNamesForRemoving()
|
2013-08-08 19:32:33 +02:00
|
|
|
{
|
|
|
|
|
QStringList vars;
|
|
|
|
|
vars << QLatin1String("HEADERS");
|
|
|
|
|
vars << QLatin1String("OBJECTIVE_HEADERS");
|
2013-11-11 14:49:59 +01:00
|
|
|
vars << QLatin1String("PRECOMPILED_HEADER");
|
2013-08-08 19:32:33 +02:00
|
|
|
vars << QLatin1String("SOURCES");
|
|
|
|
|
vars << QLatin1String("OBJECTIVE_SOURCES");
|
|
|
|
|
vars << QLatin1String("RESOURCES");
|
|
|
|
|
vars << QLatin1String("FORMS");
|
|
|
|
|
vars << QLatin1String("OTHER_FILES");
|
|
|
|
|
vars << QLatin1String("SUBDIRS");
|
2014-08-06 15:07:33 +02:00
|
|
|
vars << QLatin1String("DISTFILES");
|
2013-08-08 19:32:33 +02:00
|
|
|
vars << QLatin1String("ICON");
|
2014-08-06 15:00:26 +02:00
|
|
|
vars << QLatin1String("QMAKE_INFO_PLIST");
|
2016-07-13 15:10:21 +02:00
|
|
|
vars << QLatin1String("STATECHARTS");
|
2013-08-08 19:32:33 +02:00
|
|
|
return vars;
|
|
|
|
|
}
|
2010-08-10 16:27:35 +02:00
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QStringList QmakePriFileNode::dynamicVarNames(QtSupport::ProFileReader *readerExact, QtSupport::ProFileReader *readerCumulative,
|
2014-09-10 12:53:55 +02:00
|
|
|
bool isQt5)
|
2010-08-10 16:27:35 +02:00
|
|
|
{
|
|
|
|
|
QStringList result;
|
2012-09-07 12:35:18 +02:00
|
|
|
|
2010-08-10 16:27:35 +02:00
|
|
|
// Figure out DEPLOYMENT and INSTALLS
|
2012-01-13 14:20:45 +01:00
|
|
|
const QString deployment = QLatin1String("DEPLOYMENT");
|
2014-09-10 12:53:55 +02:00
|
|
|
const QString sources = QLatin1String(isQt5 ? ".files" : ".sources");
|
2012-01-13 14:20:45 +01:00
|
|
|
QStringList listOfVars = readerExact->values(deployment);
|
2010-08-10 16:27:35 +02:00
|
|
|
foreach (const QString &var, listOfVars) {
|
2012-01-13 14:20:45 +01:00
|
|
|
result << (var + sources);
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
|
if (readerCumulative) {
|
2012-01-13 14:20:45 +01:00
|
|
|
QStringList listOfVars = readerCumulative->values(deployment);
|
2010-08-10 16:27:35 +02:00
|
|
|
foreach (const QString &var, listOfVars) {
|
2012-01-13 14:20:45 +01:00
|
|
|
result << (var + sources);
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-13 14:20:45 +01:00
|
|
|
const QString installs = QLatin1String("INSTALLS");
|
|
|
|
|
const QString files = QLatin1String(".files");
|
|
|
|
|
listOfVars = readerExact->values(installs);
|
2010-08-10 16:27:35 +02:00
|
|
|
foreach (const QString &var, listOfVars) {
|
2012-01-13 14:20:45 +01:00
|
|
|
result << (var + files);
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
|
if (readerCumulative) {
|
2012-01-13 14:20:45 +01:00
|
|
|
QStringList listOfVars = readerCumulative->values(installs);
|
2010-08-10 16:27:35 +02:00
|
|
|
foreach (const QString &var, listOfVars) {
|
2012-01-13 14:20:45 +01:00
|
|
|
result << (var + files);
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
|
}
|
2013-09-09 14:05:06 +02:00
|
|
|
result.removeDuplicates();
|
2010-08-10 16:27:35 +02:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
QSet<FileName> QmakePriFileNode::filterFilesProVariables(FileType fileType, const QSet<FileName> &files)
|
2011-06-30 17:57:52 +02:00
|
|
|
{
|
2015-02-01 18:44:47 +02:00
|
|
|
if (fileType != QMLType && fileType != UnknownFileType)
|
2011-06-30 17:57:52 +02:00
|
|
|
return files;
|
2015-02-01 18:44:47 +02:00
|
|
|
QSet<FileName> result;
|
|
|
|
|
if (fileType == QMLType) {
|
|
|
|
|
foreach (const FileName &file, files)
|
2013-04-23 12:36:44 +02:00
|
|
|
if (file.toString().endsWith(QLatin1String(".qml")))
|
2011-06-30 17:57:52 +02:00
|
|
|
result << file;
|
|
|
|
|
} else {
|
2015-02-01 18:44:47 +02:00
|
|
|
foreach (const FileName &file, files)
|
2013-04-23 12:36:44 +02:00
|
|
|
if (!file.toString().endsWith(QLatin1String(".qml")))
|
2011-06-30 17:57:52 +02:00
|
|
|
result << file;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
QSet<FileName> QmakePriFileNode::filterFilesRecursiveEnumerata(FileType fileType, const QSet<FileName> &files)
|
2010-08-10 16:27:35 +02:00
|
|
|
{
|
2015-02-01 18:44:47 +02:00
|
|
|
QSet<FileName> result;
|
|
|
|
|
if (fileType != QMLType && fileType != UnknownFileType)
|
2010-08-10 16:27:35 +02:00
|
|
|
return result;
|
2015-02-01 18:44:47 +02:00
|
|
|
if (fileType == QMLType) {
|
|
|
|
|
foreach (const FileName &file, files)
|
2013-04-23 12:36:44 +02:00
|
|
|
if (file.toString().endsWith(QLatin1String(".qml")))
|
2010-08-10 16:27:35 +02:00
|
|
|
result << file;
|
|
|
|
|
} else {
|
2015-02-01 18:44:47 +02:00
|
|
|
foreach (const FileName &file, files)
|
2013-04-23 12:36:44 +02:00
|
|
|
if (!file.toString().endsWith(QLatin1String(".qml")))
|
2010-08-10 16:27:35 +02:00
|
|
|
result << file;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-16 11:02:37 +02:00
|
|
|
} // namespace QmakeProjectManager
|
2011-11-22 13:10:10 +01:00
|
|
|
|
2013-10-29 16:08:37 +01:00
|
|
|
static QmakeProjectType proFileTemplateTypeToProjectType(ProFileEvaluator::TemplateType type)
|
2011-05-25 11:23:25 +02:00
|
|
|
{
|
|
|
|
|
switch (type) {
|
|
|
|
|
case ProFileEvaluator::TT_Unknown:
|
|
|
|
|
case ProFileEvaluator::TT_Application:
|
|
|
|
|
return ApplicationTemplate;
|
2015-03-17 11:39:48 +02:00
|
|
|
case ProFileEvaluator::TT_StaticLibrary:
|
|
|
|
|
return StaticLibraryTemplate;
|
|
|
|
|
case ProFileEvaluator::TT_SharedLibrary:
|
|
|
|
|
return SharedLibraryTemplate;
|
2011-05-25 11:23:25 +02:00
|
|
|
case ProFileEvaluator::TT_Script:
|
|
|
|
|
return ScriptTemplate;
|
|
|
|
|
case ProFileEvaluator::TT_Aux:
|
|
|
|
|
return AuxTemplate;
|
|
|
|
|
case ProFileEvaluator::TT_Subdirs:
|
|
|
|
|
return SubDirsTemplate;
|
|
|
|
|
default:
|
|
|
|
|
return InvalidProject;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace {
|
2016-01-15 16:12:54 +01:00
|
|
|
// feed all files accepted by any of the factories to the callback.
|
|
|
|
|
class FindGeneratorSourcesVisitor : public NodesVisitor {
|
2011-05-25 11:23:25 +02:00
|
|
|
public:
|
2016-01-15 16:12:54 +01:00
|
|
|
FindGeneratorSourcesVisitor(
|
|
|
|
|
const QList<ProjectExplorer::ExtraCompilerFactory *> &factories,
|
|
|
|
|
std::function<void(FileNode *, ProjectExplorer::ExtraCompilerFactory *)> callback) :
|
|
|
|
|
factories(factories), callback(callback) {}
|
|
|
|
|
|
2011-05-25 11:23:25 +02:00
|
|
|
void visitProjectNode(ProjectNode *projectNode)
|
|
|
|
|
{
|
|
|
|
|
visitFolderNode(projectNode);
|
|
|
|
|
}
|
|
|
|
|
void visitFolderNode(FolderNode *folderNode)
|
|
|
|
|
{
|
|
|
|
|
foreach (FileNode *fileNode, folderNode->fileNodes()) {
|
2016-01-15 16:12:54 +01:00
|
|
|
foreach (ProjectExplorer::ExtraCompilerFactory *factory, factories) {
|
|
|
|
|
if (factory->sourceType() == fileNode->fileType())
|
|
|
|
|
callback(fileNode, factory);
|
|
|
|
|
}
|
2011-05-25 11:23:25 +02:00
|
|
|
}
|
|
|
|
|
}
|
2016-01-15 16:12:54 +01:00
|
|
|
|
|
|
|
|
const QList<ProjectExplorer::ExtraCompilerFactory *> factories;
|
|
|
|
|
std::function<void(FileNode *, ProjectExplorer::ExtraCompilerFactory *)> callback;
|
2011-05-25 11:23:25 +02:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-18 16:01:58 +01:00
|
|
|
QmakeProFileNode *QmakeProFileNode::findProFileFor(const FileName &fileName) const
|
2009-04-28 14:30:17 +02:00
|
|
|
{
|
2015-10-29 17:53:47 +01:00
|
|
|
if (fileName == filePath())
|
2015-02-18 16:01:58 +01:00
|
|
|
return const_cast<QmakeProFileNode *>(this);
|
2009-04-28 14:30:17 +02:00
|
|
|
foreach (ProjectNode *pn, subProjectNodes())
|
2015-01-09 15:50:06 +01:00
|
|
|
if (QmakeProFileNode *qmakeProFileNode = dynamic_cast<QmakeProFileNode *>(pn))
|
2015-02-18 16:01:58 +01:00
|
|
|
if (QmakeProFileNode *result = qmakeProFileNode->findProFileFor(fileName))
|
2009-04-28 14:30:17 +02:00
|
|
|
return result;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2009-01-14 17:13:17 +01:00
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QString QmakeProFileNode::makefile() const
|
2010-10-05 17:38:45 +02:00
|
|
|
{
|
2012-09-05 13:08:40 +02:00
|
|
|
return singleVariableValue(Makefile);
|
2010-10-05 17:38:45 +02:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QString QmakeProFileNode::objectExtension() const
|
2012-04-28 22:24:33 +03:00
|
|
|
{
|
2012-08-23 15:53:58 +02:00
|
|
|
if (m_varValues[ObjectExt].isEmpty())
|
2015-02-01 18:44:47 +02:00
|
|
|
return HostOsInfo::isWindowsHost() ? QLatin1String(".obj") : QLatin1String(".o");
|
2012-04-28 22:24:33 +03:00
|
|
|
return m_varValues[ObjectExt].first();
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QString QmakeProFileNode::objectsDirectory() const
|
2012-04-28 22:24:33 +03:00
|
|
|
{
|
2012-09-05 13:08:40 +02:00
|
|
|
return singleVariableValue(ObjectsDir);
|
2012-04-28 22:24:33 +03:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QByteArray QmakeProFileNode::cxxDefines() const
|
2012-02-16 15:09:56 +01:00
|
|
|
{
|
|
|
|
|
QByteArray result;
|
|
|
|
|
foreach (const QString &def, variableValue(DefinesVar)) {
|
2014-11-03 12:29:43 +01:00
|
|
|
// 'def' is shell input, so interpret it.
|
|
|
|
|
QtcProcess::SplitError error = QtcProcess::SplitOk;
|
|
|
|
|
const QStringList args = QtcProcess::splitArgs(def, HostOsInfo::hostOs(), false, &error);
|
|
|
|
|
if (error != QtcProcess::SplitOk || args.size() == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
2012-02-16 15:09:56 +01:00
|
|
|
result += "#define ";
|
2014-11-03 12:29:43 +01:00
|
|
|
const QString defInterpreted = args.first();
|
|
|
|
|
const int index = defInterpreted.indexOf(QLatin1Char('='));
|
2012-02-16 15:09:56 +01:00
|
|
|
if (index == -1) {
|
2014-11-03 12:29:43 +01:00
|
|
|
result += defInterpreted.toLatin1();
|
2012-02-16 15:09:56 +01:00
|
|
|
result += " 1\n";
|
|
|
|
|
} else {
|
2014-11-03 12:29:43 +01:00
|
|
|
const QString name = defInterpreted.left(index);
|
|
|
|
|
const QString value = defInterpreted.mid(index + 1);
|
2012-02-16 15:09:56 +01:00
|
|
|
result += name.toLatin1();
|
|
|
|
|
result += ' ';
|
|
|
|
|
result += value.toLocal8Bit();
|
|
|
|
|
result += '\n';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakeProFileNode::isDeployable() const
|
2011-05-10 16:18:04 +02:00
|
|
|
{
|
|
|
|
|
return m_isDeployable;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
/*!
|
2013-10-29 16:08:37 +01:00
|
|
|
\class QmakeProFileNode
|
2008-12-02 12:01:29 +01:00
|
|
|
Implements abstract ProjectNode class
|
|
|
|
|
*/
|
2013-10-29 14:22:31 +01:00
|
|
|
QmakeProFileNode::QmakeProFileNode(QmakeProject *project,
|
2015-02-02 00:37:38 +02:00
|
|
|
const FileName &filePath)
|
2015-06-18 15:14:06 +02:00
|
|
|
: QmakePriFileNode(project, this, filePath)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2015-01-09 15:50:06 +01:00
|
|
|
// The slot is a lambda, so that QmakeProFileNode does not need to be
|
|
|
|
|
// a qobject. The lifetime of the m_parserFutureWatcher is shorter
|
|
|
|
|
// than of this, so this is all safe
|
|
|
|
|
QObject::connect(&m_parseFutureWatcher, &QFutureWatcherBase::finished,
|
|
|
|
|
[this](){
|
|
|
|
|
applyAsyncEvaluate();
|
|
|
|
|
});
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QmakeProFileNode::~QmakeProFileNode()
|
2008-12-02 18:14:06 +01:00
|
|
|
{
|
2016-01-15 16:12:54 +01:00
|
|
|
qDeleteAll(m_extraCompilers);
|
2010-03-10 16:55:37 +01:00
|
|
|
m_parseFutureWatcher.waitForFinished();
|
2014-09-10 12:53:13 +02:00
|
|
|
if (m_readerExact)
|
|
|
|
|
applyAsyncEvaluate();
|
2010-03-10 16:55:37 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakeProFileNode::isParent(QmakeProFileNode *node)
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
2015-01-09 15:50:06 +01:00
|
|
|
while ((node = dynamic_cast<QmakeProFileNode *>(node->parentFolderNode()))) {
|
2010-03-10 16:55:37 +01:00
|
|
|
if (node == this)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
2008-12-02 18:14:06 +01:00
|
|
|
}
|
|
|
|
|
|
2014-03-17 11:52:45 +01:00
|
|
|
bool QmakeProFileNode::showInSimpleTree() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2014-03-17 11:52:45 +01:00
|
|
|
return showInSimpleTree(projectType()) || m_project->rootProjectNode() == this;
|
2010-11-18 17:31:30 +01:00
|
|
|
}
|
|
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
FolderNode::AddNewInformation QmakeProFileNode::addNewInformation(const QStringList &files, Node *context) const
|
2014-02-18 16:31:36 +01:00
|
|
|
{
|
|
|
|
|
Q_UNUSED(files)
|
2015-10-29 17:53:47 +01:00
|
|
|
return AddNewInformation(filePath().fileName(), context && context->projectNode() == this ? 120 : 100);
|
2014-02-18 16:31:36 +01:00
|
|
|
}
|
|
|
|
|
|
2014-03-17 11:52:45 +01:00
|
|
|
bool QmakeProFileNode::showInSimpleTree(QmakeProjectType projectType) const
|
2010-11-18 17:31:30 +01:00
|
|
|
{
|
2015-03-17 11:39:48 +02:00
|
|
|
return (projectType == ApplicationTemplate || projectType == SharedLibraryTemplate || projectType == StaticLibraryTemplate);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakeProFileNode::isDebugAndRelease() const
|
2012-05-04 16:25:41 +03:00
|
|
|
{
|
|
|
|
|
const QStringList configValues = m_varValues.value(ConfigVar);
|
2012-05-14 22:58:34 +03:00
|
|
|
return configValues.contains(QLatin1String("debug_and_release"));
|
2012-05-04 16:25:41 +03:00
|
|
|
}
|
|
|
|
|
|
2014-06-12 16:24:52 +02:00
|
|
|
bool QmakeProFileNode::isQtcRunnable() const
|
|
|
|
|
{
|
|
|
|
|
const QStringList configValues = m_varValues.value(ConfigVar);
|
|
|
|
|
return configValues.contains(QLatin1String("qtc_runnable"));
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 16:08:37 +01:00
|
|
|
QmakeProjectType QmakeProFileNode::projectType() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
|
return m_projectType;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 16:08:37 +01:00
|
|
|
QStringList QmakeProFileNode::variableValue(const QmakeVariable var) const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
|
return m_varValues.value(var);
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 16:08:37 +01:00
|
|
|
QString QmakeProFileNode::singleVariableValue(const QmakeVariable var) const
|
2012-08-20 12:41:52 +02:00
|
|
|
{
|
|
|
|
|
const QStringList &values = variableValue(var);
|
|
|
|
|
return values.isEmpty() ? QString() : values.first();
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProFileNode::emitProFileUpdatedRecursive()
|
2010-11-02 16:39:45 +01:00
|
|
|
{
|
2015-01-09 15:50:06 +01:00
|
|
|
emit m_project->proFileUpdated(this, m_validParse, m_parseInProgress);
|
2010-11-02 16:39:45 +01:00
|
|
|
|
|
|
|
|
foreach (ProjectNode *subNode, subProjectNodes()) {
|
2015-01-09 15:50:06 +01:00
|
|
|
if (QmakeProFileNode *node = dynamic_cast<QmakeProFileNode *>(subNode))
|
2011-09-12 12:40:53 +02:00
|
|
|
node->emitProFileUpdatedRecursive();
|
2010-11-02 16:39:45 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProFileNode::setParseInProgressRecursive(bool b)
|
2010-10-27 16:27:22 +02:00
|
|
|
{
|
2011-09-12 12:40:53 +02:00
|
|
|
setParseInProgress(b);
|
2011-06-22 12:53:49 +02:00
|
|
|
foreach (ProjectNode *subNode, subProjectNodes()) {
|
2015-01-09 15:50:06 +01:00
|
|
|
if (QmakeProFileNode *node = dynamic_cast<QmakeProFileNode *>(subNode))
|
2011-09-12 12:40:53 +02:00
|
|
|
node->setParseInProgressRecursive(b);
|
2011-06-22 12:53:49 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProFileNode::setParseInProgress(bool b)
|
2011-09-12 12:40:53 +02:00
|
|
|
{
|
|
|
|
|
if (m_parseInProgress == b)
|
|
|
|
|
return;
|
|
|
|
|
m_parseInProgress = b;
|
2015-01-09 15:50:06 +01:00
|
|
|
emit m_project->proFileUpdated(this, m_validParse, m_parseInProgress);
|
2011-09-12 12:40:53 +02:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProFileNode::setValidParseRecursive(bool b)
|
2012-05-08 12:53:24 +02:00
|
|
|
{
|
|
|
|
|
setValidParse(b);
|
|
|
|
|
foreach (ProjectNode *subNode, subProjectNodes()) {
|
2015-01-09 15:50:06 +01:00
|
|
|
if (QmakeProFileNode *node = dynamic_cast<QmakeProFileNode *>(subNode))
|
2012-05-08 12:53:24 +02:00
|
|
|
node->setValidParseRecursive(b);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Do note the absence of signal emission, always set validParse
|
|
|
|
|
// before setParseInProgress, as that will emit the signals
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProFileNode::setValidParse(bool b)
|
2012-05-08 12:53:24 +02:00
|
|
|
{
|
|
|
|
|
if (m_validParse == b)
|
|
|
|
|
return;
|
|
|
|
|
m_validParse = b;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakeProFileNode::validParse() const
|
2011-09-12 12:40:53 +02:00
|
|
|
{
|
|
|
|
|
return m_validParse;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakeProFileNode::parseInProgress() const
|
2010-10-27 16:27:22 +02:00
|
|
|
{
|
2011-06-10 15:37:10 +02:00
|
|
|
return m_parseInProgress;
|
2010-10-27 16:27:22 +02:00
|
|
|
}
|
|
|
|
|
|
2014-10-24 12:43:14 +02:00
|
|
|
void QmakeProFileNode::scheduleUpdate(QmakeProFileNode::AsyncUpdateDelay delay)
|
2008-12-09 17:17:12 +01:00
|
|
|
{
|
2011-09-12 12:40:53 +02:00
|
|
|
setParseInProgressRecursive(true);
|
2014-10-24 12:43:14 +02:00
|
|
|
m_project->scheduleAsyncUpdate(this, delay);
|
2010-03-10 16:55:37 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProFileNode::asyncUpdate()
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
|
|
|
|
m_project->incrementPendingEvaluateFutures();
|
|
|
|
|
setupReader();
|
2015-04-22 18:35:13 +02:00
|
|
|
if (!includedInExactParse())
|
report errors from projects included by cumulative evaluation
so far, we would suppress any errors which occur during the (exact)
evaluation of projects which were included only by cumulative evaluation
of a parent project (see f53d37d48). this makes sense, as excluded
projects are likely to fail, producing unsettling noise on the way.
however, having no indication at all why a subproject failed to load is
not helpful, either. so print these errors, but tag them with a prefix.
note that we continue to suppress messages from the cumulative
evaluation of all projects, including from the exact evaluation of .prf
files done even in this mode. this is done because this output is
expected to be quite noisy and unhelpful. however, it can be argued that
this isn't a wise choice for projects which are known to likely fail for
reasons which would not impact our ability to show (an approximation of)
the project in the project explorer. for the time being, we assume that
the expected errors occur later on (typically during the .prf evaluation
phase due to unknown QT entries), so an unexpected error which would
also affect the cumulative evaluation is displayed nonetheless.
Change-Id: Idc2675744169b7cb52c0542a80075850e2b9317c
Reviewed-by: Tobias Hunger <tobias.hunger@theqtcompany.com>
2015-12-17 15:45:46 +01:00
|
|
|
m_readerExact->setExact(false);
|
2010-10-25 17:26:41 +02:00
|
|
|
m_parseFutureWatcher.waitForFinished();
|
2014-09-10 12:53:55 +02:00
|
|
|
EvalInput input = evalInput();
|
2016-02-08 16:26:19 +01:00
|
|
|
QFuture<EvalResult *> future = Utils::runAsync(ProjectExplorerPlugin::sharedThreadPool(),
|
|
|
|
|
QThread::LowestPriority,
|
|
|
|
|
&QmakeProFileNode::asyncEvaluate,
|
|
|
|
|
this, input);
|
2010-03-10 16:55:37 +01:00
|
|
|
m_parseFutureWatcher.setFuture(future);
|
2008-12-09 17:17:12 +01:00
|
|
|
}
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
EvalInput QmakeProFileNode::evalInput() const
|
|
|
|
|
{
|
|
|
|
|
EvalInput input;
|
|
|
|
|
input.projectDir = m_projectDir;
|
|
|
|
|
input.projectFilePath = m_projectFilePath;
|
|
|
|
|
input.buildDirectory = buildDir();
|
|
|
|
|
input.readerExact = m_readerExact;
|
|
|
|
|
input.readerCumulative = m_readerCumulative;
|
2015-02-01 18:44:47 +02:00
|
|
|
Target *t = m_project->activeTarget();
|
|
|
|
|
Kit *k = t ? t->kit() : KitManager::defaultKit();
|
2014-09-10 12:53:55 +02:00
|
|
|
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(k);
|
|
|
|
|
input.isQt5 = !qtVersion || qtVersion->qtVersion() >= QtSupport::QtVersionNumber(5,0,0);
|
|
|
|
|
input.qmakeGlobals = m_project->qmakeGlobals();
|
|
|
|
|
input.qmakeVfs = m_project->qmakeVfs();
|
|
|
|
|
return input;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProFileNode::setupReader()
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
|
|
|
|
Q_ASSERT(!m_readerExact);
|
|
|
|
|
Q_ASSERT(!m_readerCumulative);
|
|
|
|
|
|
|
|
|
|
m_readerExact = m_project->createProFileReader(this);
|
|
|
|
|
|
|
|
|
|
m_readerCumulative = m_project->createProFileReader(this);
|
2012-06-18 10:03:45 +02:00
|
|
|
m_readerCumulative->setCumulative(true);
|
2010-03-10 16:55:37 +01:00
|
|
|
}
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
EvalResult *QmakeProFileNode::evaluate(const EvalInput &input)
|
|
|
|
|
{
|
|
|
|
|
EvalResult *result = new EvalResult;
|
2015-02-02 00:37:38 +02:00
|
|
|
if (ProFile *pro = input.readerExact->parsedProFile(input.projectFilePath.toString())) {
|
2014-09-10 12:53:55 +02:00
|
|
|
bool exactOk = input.readerExact->accept(pro, QMakeEvaluator::LoadAll);
|
|
|
|
|
bool cumulOk = input.readerCumulative->accept(pro, QMakeEvaluator::LoadPreFiles);
|
2010-06-18 21:15:14 +02:00
|
|
|
pro->deref();
|
2014-09-10 12:53:55 +02:00
|
|
|
result->state = exactOk ? EvalResult::EvalOk : cumulOk ? EvalResult::EvalPartial : EvalResult::EvalFail;
|
|
|
|
|
} else {
|
|
|
|
|
result->state = EvalResult::EvalFail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (result->state == EvalResult::EvalFail)
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
result->projectType = proFileTemplateTypeToProjectType(
|
|
|
|
|
(result->state == EvalResult::EvalOk ? input.readerExact
|
|
|
|
|
: input.readerCumulative)->templateType());
|
|
|
|
|
if (result->state == EvalResult::EvalOk) {
|
|
|
|
|
if (result->projectType == SubDirsTemplate) {
|
|
|
|
|
QStringList errors;
|
|
|
|
|
result->errors.append(errors);
|
2015-08-12 12:59:38 +02:00
|
|
|
FileNameList subDirs = subDirsPaths(input.readerExact, input.projectDir, &result->subProjectsNotToDeploy, &errors);
|
|
|
|
|
|
|
|
|
|
foreach (const Utils::FileName &subDirName, subDirs) {
|
|
|
|
|
IncludedPriFile *subDir = new IncludedPriFile;
|
|
|
|
|
subDir->name = subDirName;
|
|
|
|
|
result->includedFiles.children.insert(subDirName, subDir);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result->exactSubdirs = subDirs.toSet();
|
2014-09-10 12:53:55 +02:00
|
|
|
}
|
2015-08-12 12:59:38 +02:00
|
|
|
|
|
|
|
|
QHash<ProFile *, QVector<ProFile *> > includeFiles = input.readerExact->includeFiles();
|
|
|
|
|
QVector<ProFile *> tmp = includeFiles.value(nullptr);
|
|
|
|
|
|
|
|
|
|
if (!tmp.isEmpty()) {
|
|
|
|
|
result->includedFiles.name = Utils::FileName::fromString(tmp.first()->fileName());
|
|
|
|
|
result->includedFiles.proFilesExact.append(tmp.first());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Convert ProFileReader::includeFiles to IncludedPriFile structure
|
|
|
|
|
QList<IncludedPriFile *> toBuild = { &result->includedFiles };
|
|
|
|
|
while (!toBuild.isEmpty()) {
|
|
|
|
|
IncludedPriFile *current = toBuild.takeFirst();
|
|
|
|
|
foreach (ProFile *proFile, current->proFilesExact) {
|
|
|
|
|
QVector<ProFile *> children = includeFiles.value(proFile);
|
|
|
|
|
foreach (ProFile *child, children) {
|
|
|
|
|
const Utils::FileName childName = Utils::FileName::fromString(child->fileName());
|
|
|
|
|
auto it = current->children.find(childName);
|
|
|
|
|
if (it == current->children.end()) {
|
|
|
|
|
IncludedPriFile *childTree = new IncludedPriFile;
|
|
|
|
|
childTree->name = childName;
|
|
|
|
|
it = current->children.insert(childName, childTree);
|
|
|
|
|
}
|
|
|
|
|
(*it)->proFilesExact.append(child);
|
|
|
|
|
}
|
2014-09-10 12:53:55 +02:00
|
|
|
}
|
2015-08-12 12:59:38 +02:00
|
|
|
toBuild.append(current->children.values());
|
2014-09-10 12:53:55 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-12 12:59:38 +02:00
|
|
|
if (result->projectType == SubDirsTemplate) {
|
|
|
|
|
FileNameList subDirs = subDirsPaths(input.readerCumulative, input.projectDir, 0, 0);
|
|
|
|
|
foreach (const Utils::FileName &subDirName, subDirs) {
|
|
|
|
|
auto it = result->includedFiles.children.find(subDirName);
|
|
|
|
|
if (it == result->includedFiles.children.end()) {
|
|
|
|
|
IncludedPriFile *subDir = new IncludedPriFile;
|
|
|
|
|
subDir->name = subDirName;
|
|
|
|
|
result->includedFiles.children.insert(subDirName, subDir);
|
|
|
|
|
}
|
2014-09-10 12:53:55 +02:00
|
|
|
}
|
|
|
|
|
}
|
2015-08-12 12:59:38 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
QHash<ProFile *, QVector<ProFile *> > includeFiles = input.readerCumulative->includeFiles();
|
|
|
|
|
QVector<ProFile *> tmp = includeFiles.value(nullptr);
|
|
|
|
|
|
|
|
|
|
if (!tmp.isEmpty()) {
|
|
|
|
|
result->includedFiles.name = Utils::FileName::fromString(tmp.first()->fileName());
|
|
|
|
|
result->includedFiles.proFilesCumulative.append(tmp.first());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QList<IncludedPriFile *> toBuild = { &result->includedFiles };
|
|
|
|
|
// Add ProFileReader::includeFiles information from cumulative paerse to IncludedPriFile structure
|
|
|
|
|
while (!toBuild.isEmpty()) {
|
|
|
|
|
IncludedPriFile *current = toBuild.takeFirst();
|
|
|
|
|
foreach (ProFile *proFile, current->proFilesCumulative) {
|
|
|
|
|
QVector<ProFile *> children = includeFiles.value(proFile);
|
|
|
|
|
foreach (ProFile *child, children) {
|
|
|
|
|
const Utils::FileName childName = Utils::FileName::fromString(child->fileName());
|
|
|
|
|
auto it = current->children.find(childName);
|
|
|
|
|
if (it == current->children.end()) {
|
|
|
|
|
IncludedPriFile *childTree = new IncludedPriFile;
|
|
|
|
|
childTree->name = childName;
|
|
|
|
|
it = current->children.insert(childName, childTree);
|
|
|
|
|
}
|
|
|
|
|
(*it)->proFilesCumulative.append(child);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
toBuild.append(current->children.values());
|
|
|
|
|
}
|
2014-09-10 12:53:55 +02:00
|
|
|
|
|
|
|
|
if (result->state == EvalResult::EvalOk) {
|
|
|
|
|
// create build_pass reader
|
|
|
|
|
QtSupport::ProFileReader *readerBuildPass = 0;
|
|
|
|
|
QStringList builds = input.readerExact->values(QLatin1String("BUILDS"));
|
|
|
|
|
if (builds.isEmpty()) {
|
|
|
|
|
readerBuildPass = input.readerExact;
|
|
|
|
|
} else {
|
|
|
|
|
QString build = builds.first();
|
|
|
|
|
QHash<QString, QStringList> basevars;
|
|
|
|
|
QStringList basecfgs = input.readerExact->values(build + QLatin1String(".CONFIG"));
|
|
|
|
|
basecfgs += build;
|
|
|
|
|
basecfgs += QLatin1String("build_pass");
|
|
|
|
|
basevars[QLatin1String("BUILD_PASS")] = QStringList(build);
|
|
|
|
|
QStringList buildname = input.readerExact->values(build + QLatin1String(".name"));
|
|
|
|
|
basevars[QLatin1String("BUILD_NAME")] = (buildname.isEmpty() ? QStringList(build) : buildname);
|
|
|
|
|
|
|
|
|
|
// We don't increase/decrease m_qmakeGlobalsRefCnt here, because the outer profilereaders keep m_qmakeGlobals alive anyway
|
|
|
|
|
readerBuildPass = new QtSupport::ProFileReader(input.qmakeGlobals, input.qmakeVfs); // needs to access m_qmakeGlobals, m_qmakeVfs
|
|
|
|
|
readerBuildPass->setOutputDir(input.buildDirectory);
|
|
|
|
|
readerBuildPass->setExtraVars(basevars);
|
|
|
|
|
readerBuildPass->setExtraConfigs(basecfgs);
|
|
|
|
|
|
|
|
|
|
EvalResult::EvalResultState evalResultBuildPass = EvalResult::EvalOk;
|
2015-02-02 00:37:38 +02:00
|
|
|
if (ProFile *pro = readerBuildPass->parsedProFile(input.projectFilePath.toString())) {
|
2015-01-07 16:50:44 +01:00
|
|
|
if (!readerBuildPass->accept(pro, QMakeEvaluator::LoadAll))
|
2014-09-10 12:53:55 +02:00
|
|
|
evalResultBuildPass = EvalResult::EvalPartial;
|
|
|
|
|
pro->deref();
|
|
|
|
|
} else {
|
|
|
|
|
evalResultBuildPass = EvalResult::EvalFail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (evalResultBuildPass != EvalResult::EvalOk) {
|
|
|
|
|
delete readerBuildPass;
|
|
|
|
|
readerBuildPass = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-02-02 00:37:38 +02:00
|
|
|
result->targetInformation = targetInformation(input.readerExact, readerBuildPass,
|
|
|
|
|
input.buildDirectory, input.projectFilePath.toString());
|
|
|
|
|
result->installsList = installsList(readerBuildPass, input.projectFilePath.toString(), input.projectDir);
|
2014-09-10 12:53:55 +02:00
|
|
|
|
|
|
|
|
// update other variables
|
|
|
|
|
result->newVarValues[DefinesVar] = input.readerExact->values(QLatin1String("DEFINES"));
|
|
|
|
|
result->newVarValues[IncludePathVar] = includePaths(input.readerExact, input.buildDirectory, input.projectDir);
|
|
|
|
|
result->newVarValues[CppFlagsVar] = input.readerExact->values(QLatin1String("QMAKE_CXXFLAGS"));
|
|
|
|
|
result->newVarValues[CppHeaderVar] = fileListForVar(input.readerExact, input.readerCumulative,
|
|
|
|
|
QLatin1String("HEADERS"), input.projectDir, input.buildDirectory);
|
|
|
|
|
result->newVarValues[CppSourceVar] = fileListForVar(input.readerExact, input.readerCumulative,
|
|
|
|
|
QLatin1String("SOURCES"), input.projectDir, input.buildDirectory);
|
|
|
|
|
result->newVarValues[ObjCSourceVar] = fileListForVar(input.readerExact, input.readerCumulative,
|
|
|
|
|
QLatin1String("OBJECTIVE_SOURCES"), input.projectDir, input.buildDirectory);
|
|
|
|
|
result->newVarValues[ObjCHeaderVar] = fileListForVar(input.readerExact, input.readerCumulative,
|
|
|
|
|
QLatin1String("OBJECTIVE_HEADERS"), input.projectDir, input.buildDirectory);
|
|
|
|
|
result->newVarValues[UiDirVar] = QStringList() << uiDirPath(input.readerExact, input.buildDirectory);
|
2016-02-08 17:53:07 +01:00
|
|
|
result->newVarValues[HeaderExtensionVar] = QStringList() << input.readerExact->value(QLatin1String("QMAKE_EXT_H"));
|
|
|
|
|
result->newVarValues[CppExtensionVar] = QStringList() << input.readerExact->value(QLatin1String("QMAKE_EXT_CPP"));
|
2014-09-10 12:53:55 +02:00
|
|
|
result->newVarValues[MocDirVar] = QStringList() << mocDirPath(input.readerExact, input.buildDirectory);
|
|
|
|
|
result->newVarValues[ResourceVar] = fileListForVar(input.readerExact, input.readerCumulative,
|
|
|
|
|
QLatin1String("RESOURCES"), input.projectDir, input.buildDirectory);
|
|
|
|
|
result->newVarValues[ExactResourceVar] = fileListForVar(input.readerExact, 0,
|
|
|
|
|
QLatin1String("RESOURCES"), input.projectDir, input.buildDirectory);
|
|
|
|
|
result->newVarValues[PkgConfigVar] = input.readerExact->values(QLatin1String("PKGCONFIG"));
|
|
|
|
|
result->newVarValues[PrecompiledHeaderVar] =
|
|
|
|
|
input.readerExact->absoluteFileValues(QLatin1String("PRECOMPILED_HEADER"),
|
|
|
|
|
input.projectDir,
|
|
|
|
|
QStringList() << input.projectDir,
|
|
|
|
|
0);
|
|
|
|
|
result->newVarValues[LibDirectoriesVar] = libDirectories(input.readerExact);
|
|
|
|
|
result->newVarValues[ConfigVar] = input.readerExact->values(QLatin1String("CONFIG"));
|
|
|
|
|
result->newVarValues[QmlImportPathVar] = input.readerExact->absolutePathValues(
|
|
|
|
|
QLatin1String("QML_IMPORT_PATH"), input.projectDir);
|
|
|
|
|
result->newVarValues[Makefile] = input.readerExact->values(QLatin1String("MAKEFILE"));
|
|
|
|
|
result->newVarValues[QtVar] = input.readerExact->values(QLatin1String("QT"));
|
|
|
|
|
result->newVarValues[ObjectExt] = input.readerExact->values(QLatin1String("QMAKE_EXT_OBJ"));
|
|
|
|
|
result->newVarValues[ObjectsDir] = input.readerExact->values(QLatin1String("OBJECTS_DIR"));
|
|
|
|
|
result->newVarValues[VersionVar] = input.readerExact->values(QLatin1String("VERSION"));
|
|
|
|
|
result->newVarValues[TargetExtVar] = input.readerExact->values(QLatin1String("TARGET_EXT"));
|
|
|
|
|
result->newVarValues[TargetVersionExtVar]
|
|
|
|
|
= input.readerExact->values(QLatin1String("TARGET_VERSION_EXT"));
|
|
|
|
|
result->newVarValues[StaticLibExtensionVar] = input.readerExact->values(QLatin1String("QMAKE_EXTENSION_STATICLIB"));
|
|
|
|
|
result->newVarValues[ShLibExtensionVar] = input.readerExact->values(QLatin1String("QMAKE_EXTENSION_SHLIB"));
|
|
|
|
|
result->newVarValues[AndroidArchVar] = input.readerExact->values(QLatin1String("ANDROID_TARGET_ARCH"));
|
|
|
|
|
result->newVarValues[AndroidDeploySettingsFile] = input.readerExact->values(QLatin1String("ANDROID_DEPLOYMENT_SETTINGS_FILE"));
|
|
|
|
|
result->newVarValues[AndroidPackageSourceDir] = input.readerExact->values(QLatin1String("ANDROID_PACKAGE_SOURCE_DIR"));
|
|
|
|
|
result->newVarValues[AndroidExtraLibs] = input.readerExact->values(QLatin1String("ANDROID_EXTRA_LIBS"));
|
2015-01-21 13:32:08 +01:00
|
|
|
result->newVarValues[IsoIconsVar] = input.readerExact->values(QLatin1String("ISO_ICONS"));
|
2015-08-12 11:16:36 +02:00
|
|
|
result->newVarValues[QmakeProjectName] = input.readerExact->values(QLatin1String("QMAKE_PROJECT_NAME"));
|
2016-09-23 15:53:31 +02:00
|
|
|
result->newVarValues[QmakeCc] = input.readerExact->values("QMAKE_CC");
|
|
|
|
|
result->newVarValues[QmakeCxx] = input.readerExact->values("QMAKE_CXX");
|
2014-09-10 12:53:55 +02:00
|
|
|
|
|
|
|
|
result->isDeployable = false;
|
|
|
|
|
if (result->projectType == ApplicationTemplate) {
|
|
|
|
|
result->isDeployable = true;
|
|
|
|
|
} else {
|
|
|
|
|
foreach (const QString &item, input.readerExact->values(QLatin1String("DEPLOYMENT"))) {
|
|
|
|
|
if (!input.readerExact->values(item + QLatin1String(".sources")).isEmpty()) {
|
|
|
|
|
result->isDeployable = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (readerBuildPass && readerBuildPass != input.readerExact)
|
|
|
|
|
delete readerBuildPass;
|
2015-01-22 13:39:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (result->state == EvalResult::EvalOk || result->state == EvalResult::EvalPartial) {
|
2014-09-10 12:53:55 +02:00
|
|
|
|
|
|
|
|
QList<QList<VariableAndVPathInformation>> variableAndVPathInformation;
|
|
|
|
|
{ // Collect information on VPATHS and qmake variables
|
|
|
|
|
QStringList baseVPathsExact = baseVPaths(input.readerExact, input.projectDir, input.buildDirectory);
|
|
|
|
|
QStringList baseVPathsCumulative = baseVPaths(input.readerCumulative, input.projectDir, input.buildDirectory);
|
|
|
|
|
|
|
|
|
|
const QVector<QmakeNodeStaticData::FileTypeData> &fileTypes = qmakeNodeStaticData()->fileTypeData;
|
|
|
|
|
|
|
|
|
|
variableAndVPathInformation.reserve(fileTypes.size());
|
|
|
|
|
for (int i = 0; i < fileTypes.size(); ++i) {
|
|
|
|
|
FileType type = fileTypes.at(i).type;
|
|
|
|
|
|
|
|
|
|
QList<VariableAndVPathInformation> list;
|
|
|
|
|
QStringList qmakeVariables = varNames(type, input.readerExact);
|
|
|
|
|
list.reserve(qmakeVariables.size());
|
|
|
|
|
foreach (const QString &qmakeVariable, qmakeVariables) {
|
|
|
|
|
VariableAndVPathInformation info;
|
|
|
|
|
info.variable = qmakeVariable;
|
|
|
|
|
info.vPathsExact = fullVPaths(baseVPathsExact, input.readerExact, qmakeVariable, input.projectDir);
|
|
|
|
|
info.vPathsCumulative = fullVPaths(baseVPathsCumulative, input.readerCumulative, qmakeVariable, input.projectDir);
|
|
|
|
|
list.append(info);
|
|
|
|
|
}
|
|
|
|
|
variableAndVPathInformation.append(list);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-12 12:59:38 +02:00
|
|
|
// extract values for each .pri file and add it to IncludedPriFiles structure
|
|
|
|
|
QList<IncludedPriFile *> toExtract = { &result->includedFiles };
|
|
|
|
|
while (!toExtract.isEmpty()) {
|
|
|
|
|
IncludedPriFile *current = toExtract.takeFirst();
|
|
|
|
|
current->result = extractValues(input, current->proFilesExact, current->proFilesCumulative, variableAndVPathInformation);
|
|
|
|
|
toExtract.append(current->children.values());
|
2014-09-10 12:53:55 +02:00
|
|
|
}
|
2010-06-18 21:15:14 +02:00
|
|
|
}
|
2014-09-10 12:53:55 +02:00
|
|
|
|
|
|
|
|
return result;
|
2010-03-10 16:55:37 +01:00
|
|
|
}
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
void QmakeProFileNode::asyncEvaluate(QFutureInterface<EvalResult *> &fi, EvalInput input)
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
2014-09-10 12:53:55 +02:00
|
|
|
EvalResult *evalResult = evaluate(input);
|
2011-02-09 20:03:04 +01:00
|
|
|
fi.reportResult(evalResult);
|
2010-03-10 16:55:37 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProFileNode::applyAsyncEvaluate()
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
2014-09-26 15:24:32 +02:00
|
|
|
applyEvaluate(m_parseFutureWatcher.result());
|
2010-03-10 16:55:37 +01:00
|
|
|
m_project->decrementPendingEvaluateFutures();
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-04 11:49:37 +02:00
|
|
|
bool sortByNodes(Node *a, Node *b)
|
|
|
|
|
{
|
2015-10-29 17:53:47 +01:00
|
|
|
return a->filePath() < b->filePath();
|
2012-05-04 11:49:37 +02:00
|
|
|
}
|
|
|
|
|
|
2014-09-26 15:24:32 +02:00
|
|
|
void QmakeProFileNode::applyEvaluate(EvalResult *evalResult)
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
2014-09-10 12:53:55 +02:00
|
|
|
QScopedPointer<EvalResult> result(evalResult);
|
2010-03-11 17:01:06 +01:00
|
|
|
if (!m_readerExact)
|
|
|
|
|
return;
|
2014-09-10 12:53:55 +02:00
|
|
|
|
2014-11-18 17:05:09 +01:00
|
|
|
if (m_project->asyncUpdateState() == QmakeProject::ShuttingDown) {
|
|
|
|
|
cleanupProFileReaders();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
foreach (const QString &error, evalResult->errors)
|
|
|
|
|
QmakeProject::proFileParseError(error);
|
|
|
|
|
|
|
|
|
|
// we are changing what is executed in that case
|
|
|
|
|
if (result->state == EvalResult::EvalFail || m_project->wasEvaluateCanceled()) {
|
2011-12-07 17:52:59 +01:00
|
|
|
m_validParse = false;
|
2016-04-04 11:25:36 +02:00
|
|
|
cleanupProFileReaders();
|
2012-05-08 12:53:24 +02:00
|
|
|
setValidParseRecursive(false);
|
|
|
|
|
setParseInProgressRecursive(false);
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
if (result->state == EvalResult::EvalFail) {
|
2015-02-02 00:37:38 +02:00
|
|
|
QmakeProject::proFileParseError(QCoreApplication::translate("QmakeProFileNode", "Error while parsing file %1. Giving up.")
|
|
|
|
|
.arg(m_projectFilePath.toUserOutput()));
|
2012-05-08 12:53:24 +02:00
|
|
|
if (m_projectType == InvalidProject)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// delete files && folders && projects
|
2014-02-18 19:49:55 +01:00
|
|
|
removeFileNodes(fileNodes());
|
2012-05-08 12:53:24 +02:00
|
|
|
removeProjectNodes(subProjectNodes());
|
2014-02-18 19:49:55 +01:00
|
|
|
removeFolderNodes(subFolderNodes());
|
2012-05-08 12:53:24 +02:00
|
|
|
|
|
|
|
|
m_projectType = InvalidProject;
|
2010-06-15 16:34:03 +02:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (debug)
|
2013-10-29 18:24:57 +01:00
|
|
|
qDebug() << "QmakeProFileNode - updating files for file " << m_projectFilePath;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
if (result->projectType != m_projectType) {
|
2012-05-08 12:53:24 +02:00
|
|
|
// probably all subfiles/projects have changed anyway
|
|
|
|
|
// delete files && folders && projects
|
|
|
|
|
foreach (ProjectNode *projectNode, subProjectNodes()) {
|
2015-01-09 15:50:06 +01:00
|
|
|
if (QmakeProFileNode *qmakeProFileNode = dynamic_cast<QmakeProFileNode *>(projectNode)) {
|
2013-10-29 17:37:39 +01:00
|
|
|
qmakeProFileNode->setValidParseRecursive(false);
|
|
|
|
|
qmakeProFileNode->setParseInProgressRecursive(false);
|
2012-05-08 12:53:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-18 19:49:55 +01:00
|
|
|
removeFileNodes(fileNodes());
|
2012-05-08 12:53:24 +02:00
|
|
|
removeProjectNodes(subProjectNodes());
|
2014-02-18 19:49:55 +01:00
|
|
|
removeFolderNodes(subFolderNodes());
|
2012-05-08 12:53:24 +02:00
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
bool changesShowInSimpleTree = showInSimpleTree() ^ showInSimpleTree(result->projectType);
|
2010-11-18 17:31:30 +01:00
|
|
|
|
2014-03-17 11:52:45 +01:00
|
|
|
if (changesShowInSimpleTree)
|
2015-02-01 18:44:47 +02:00
|
|
|
ProjectTree::instance()->emitAboutToChangeShowInSimpleTree(this);
|
2010-11-18 17:31:30 +01:00
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
m_projectType = result->projectType;
|
2010-11-18 17:31:30 +01:00
|
|
|
|
2014-03-17 11:52:45 +01:00
|
|
|
if (changesShowInSimpleTree)
|
2015-02-01 18:44:47 +02:00
|
|
|
ProjectTree::instance()->emitShowInSimpleTreeChanged(this);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Add/Remove pri files, sub projects
|
|
|
|
|
//
|
|
|
|
|
|
2014-09-05 16:13:21 +02:00
|
|
|
QString buildDirectory = buildDir();
|
2014-02-10 16:05:35 +01:00
|
|
|
SortByPath sortByPath;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-08-12 12:59:38 +02:00
|
|
|
QList<QPair<QmakePriFileNode *, IncludedPriFile *>> toCompare;
|
|
|
|
|
|
|
|
|
|
toCompare.append(qMakePair(this, &result->includedFiles));
|
|
|
|
|
|
|
|
|
|
while (!toCompare.isEmpty()) {
|
|
|
|
|
QmakePriFileNode *pn = toCompare.first().first;
|
|
|
|
|
IncludedPriFile *tree = toCompare.first().second;
|
|
|
|
|
toCompare.pop_front();
|
|
|
|
|
|
|
|
|
|
QList<ProjectNode*> existingProjectNodes = pn->subProjectNodes();
|
|
|
|
|
Utils::sort(existingProjectNodes, sortByPath);
|
|
|
|
|
// result is already sorted
|
|
|
|
|
|
|
|
|
|
QList<ProjectNode*> toAdd;
|
|
|
|
|
QList<ProjectNode*> toRemove;
|
|
|
|
|
|
|
|
|
|
QList<ProjectNode*>::const_iterator existingIt = existingProjectNodes.constBegin();
|
|
|
|
|
auto newIt = tree->children.constBegin();
|
|
|
|
|
|
|
|
|
|
forever {
|
|
|
|
|
bool existingAtEnd = (existingIt == existingProjectNodes.constEnd());
|
|
|
|
|
bool newAtEnd = (newIt == tree->children.constEnd());
|
|
|
|
|
|
|
|
|
|
if (existingAtEnd && newAtEnd)
|
|
|
|
|
break; // we are done, hurray!
|
|
|
|
|
|
|
|
|
|
if (! existingAtEnd
|
2015-10-29 17:53:47 +01:00
|
|
|
&& (newAtEnd || (*existingIt)->filePath() < (*newIt)->name)) {
|
2015-08-12 12:59:38 +02:00
|
|
|
// Remove case
|
|
|
|
|
toRemove << *existingIt;
|
|
|
|
|
++existingIt;
|
|
|
|
|
} else if (! newAtEnd
|
2015-10-29 17:53:47 +01:00
|
|
|
&& (existingAtEnd || (*newIt)->name < (*existingIt)->filePath())) {
|
2015-08-12 12:59:38 +02:00
|
|
|
// Adding a node
|
|
|
|
|
IncludedPriFile *nodeToAdd = *newIt;
|
|
|
|
|
++newIt;
|
|
|
|
|
|
|
|
|
|
QVector<ProFile *> filesExact = nodeToAdd->proFilesExact;
|
|
|
|
|
QVector<ProFile *> filesCumlative = nodeToAdd->proFilesCumulative;
|
|
|
|
|
|
|
|
|
|
// Loop preventation, make sure that exact same node is not in our parent chain
|
|
|
|
|
bool loop = false;
|
|
|
|
|
Node *n = pn;
|
|
|
|
|
while ((n = n->parentFolderNode())) {
|
2015-10-29 17:53:47 +01:00
|
|
|
if (dynamic_cast<QmakePriFileNode *>(n) && n->filePath() == nodeToAdd->name) {
|
2015-08-12 12:59:38 +02:00
|
|
|
loop = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2010-05-20 16:02:24 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-12 12:59:38 +02:00
|
|
|
if (loop) {
|
|
|
|
|
// Do nothing
|
|
|
|
|
} else {
|
|
|
|
|
if (!filesExact.isEmpty() || !filesCumlative.isEmpty()) {
|
|
|
|
|
QmakePriFileNode *qmakePriFileNode = new QmakePriFileNode(m_project, this, nodeToAdd->name);
|
|
|
|
|
qmakePriFileNode->setParentFolderNode(pn); // Needed for loop detection
|
|
|
|
|
qmakePriFileNode->setIncludedInExactParse(!filesExact.isEmpty() && pn->includedInExactParse());
|
|
|
|
|
toAdd << qmakePriFileNode;
|
|
|
|
|
qmakePriFileNode->update(nodeToAdd->result);
|
|
|
|
|
toCompare.append(qMakePair(qmakePriFileNode, nodeToAdd));
|
|
|
|
|
} else {
|
|
|
|
|
QmakeProFileNode *qmakeProFileNode = new QmakeProFileNode(m_project, nodeToAdd->name);
|
|
|
|
|
qmakeProFileNode->setParentFolderNode(pn); // Needed for loop detection
|
|
|
|
|
qmakeProFileNode->setIncludedInExactParse(
|
2015-10-29 17:53:47 +01:00
|
|
|
result->exactSubdirs.contains(qmakeProFileNode->filePath())
|
2015-08-12 12:59:38 +02:00
|
|
|
&& pn->includedInExactParse());
|
|
|
|
|
qmakeProFileNode->asyncUpdate();
|
|
|
|
|
toAdd << qmakeProFileNode;
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-03-10 16:55:37 +01:00
|
|
|
} else {
|
2015-08-12 12:59:38 +02:00
|
|
|
// Update existingNodeIte
|
|
|
|
|
QVector<ProFile *> filesExact = (*newIt)->proFilesExact;
|
|
|
|
|
QVector<ProFile *> filesCumlative = (*newIt)->proFilesCumulative;
|
|
|
|
|
if (!filesExact.isEmpty() || !filesCumlative.isEmpty()) {
|
|
|
|
|
QmakePriFileNode *priFileNode = static_cast<QmakePriFileNode *>(*existingIt);
|
|
|
|
|
priFileNode->update((*newIt)->result);
|
|
|
|
|
priFileNode->setIncludedInExactParse(!filesExact.isEmpty() && pn->includedInExactParse());
|
|
|
|
|
toCompare.append(qMakePair(priFileNode, *newIt));
|
2015-02-02 00:37:38 +02:00
|
|
|
} else {
|
2015-08-12 12:59:38 +02:00
|
|
|
// We always parse exactly, because we later when async parsing don't know whether
|
|
|
|
|
// the .pro file is included in this .pro file
|
|
|
|
|
// So to compare that later parse with the sync one
|
|
|
|
|
QmakeProFileNode *proFileNode = static_cast<QmakeProFileNode *>(*existingIt);
|
2015-10-29 17:53:47 +01:00
|
|
|
proFileNode->setIncludedInExactParse(result->exactSubdirs.contains(proFileNode->filePath())
|
2015-08-12 12:59:38 +02:00
|
|
|
&& pn->includedInExactParse());
|
|
|
|
|
proFileNode->asyncUpdate();
|
2015-02-02 00:37:38 +02:00
|
|
|
}
|
2015-08-12 12:59:38 +02:00
|
|
|
++newIt;
|
|
|
|
|
++existingIt;
|
|
|
|
|
// newCumalativeIt and newExactIt are already incremented
|
|
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
}
|
2015-08-12 12:59:38 +02:00
|
|
|
} // for
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-08-12 12:59:38 +02:00
|
|
|
foreach (ProjectNode *node, toRemove) {
|
|
|
|
|
if (QmakeProFileNode *qmakeProFileNode = dynamic_cast<QmakeProFileNode *>(node)) {
|
|
|
|
|
qmakeProFileNode->setValidParseRecursive(false);
|
|
|
|
|
qmakeProFileNode->setParseInProgressRecursive(false);
|
|
|
|
|
}
|
2012-05-08 12:53:24 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-12 12:59:38 +02:00
|
|
|
if (!toRemove.isEmpty())
|
|
|
|
|
pn->removeProjectNodes(toRemove);
|
|
|
|
|
if (!toAdd.isEmpty())
|
|
|
|
|
pn->addProjectNodes(toAdd);
|
|
|
|
|
}
|
2015-03-13 15:40:57 +01:00
|
|
|
|
2015-08-12 12:59:38 +02:00
|
|
|
QmakePriFileNode::update(result->includedFiles.result);
|
2010-03-10 16:55:37 +01:00
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
m_validParse = (result->state == EvalResult::EvalOk);
|
2011-06-10 15:37:10 +02:00
|
|
|
if (m_validParse) {
|
2011-02-09 20:03:04 +01:00
|
|
|
// update TargetInformation
|
2014-09-10 12:53:55 +02:00
|
|
|
m_qmakeTargetInformation = result->targetInformation;
|
2011-02-09 20:03:04 +01:00
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
m_subProjectsNotToDeploy = result->subProjectsNotToDeploy;
|
|
|
|
|
m_installsList = result->installsList;
|
|
|
|
|
m_isDeployable = result->isDeployable;
|
2011-02-09 20:03:04 +01:00
|
|
|
|
2015-01-09 15:50:06 +01:00
|
|
|
if (m_varValues != result->newVarValues)
|
2014-09-10 12:53:55 +02:00
|
|
|
m_varValues = result->newVarValues;
|
2015-08-12 11:16:36 +02:00
|
|
|
|
|
|
|
|
const QString projectName = singleVariableValue(QmakeProjectName);
|
|
|
|
|
if (projectName.isEmpty())
|
|
|
|
|
setDisplayName(m_projectFilePath.toFileInfo().completeBaseName());
|
|
|
|
|
else
|
|
|
|
|
setDisplayName(projectName);
|
2014-09-10 12:53:55 +02:00
|
|
|
} // result == EvalOk
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-09-12 12:40:53 +02:00
|
|
|
setParseInProgress(false);
|
2011-06-10 15:37:10 +02:00
|
|
|
|
2016-01-15 16:12:54 +01:00
|
|
|
updateGeneratedFiles(buildDirectory);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2014-11-18 17:05:09 +01:00
|
|
|
cleanupProFileReaders();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QmakeProFileNode::cleanupProFileReaders()
|
|
|
|
|
{
|
2010-03-10 16:55:37 +01:00
|
|
|
m_project->destroyProFileReader(m_readerExact);
|
2011-02-08 12:46:25 +01:00
|
|
|
m_project->destroyProFileReader(m_readerCumulative);
|
2010-03-10 16:55:37 +01:00
|
|
|
|
2016-04-04 11:25:36 +02:00
|
|
|
m_readerExact = nullptr;
|
|
|
|
|
m_readerCumulative = nullptr;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QStringList QmakeProFileNode::fileListForVar(QtSupport::ProFileReader *readerExact, QtSupport::ProFileReader *readerCumulative,
|
2014-09-10 12:53:55 +02:00
|
|
|
const QString &varName, const QString &projectDir, const QString &buildDir)
|
2012-04-19 13:43:51 +02:00
|
|
|
{
|
2012-11-28 13:46:49 +01:00
|
|
|
QStringList baseVPathsExact = baseVPaths(readerExact, projectDir, buildDir);
|
|
|
|
|
QStringList vPathsExact = fullVPaths(baseVPathsExact, readerExact, varName, projectDir);
|
2012-06-05 17:32:30 +02:00
|
|
|
|
2012-04-19 13:43:51 +02:00
|
|
|
QStringList result;
|
|
|
|
|
result = readerExact->absoluteFileValues(varName,
|
|
|
|
|
projectDir,
|
2012-06-05 17:32:30 +02:00
|
|
|
vPathsExact,
|
2012-04-19 13:43:51 +02:00
|
|
|
0);
|
2012-06-05 17:32:30 +02:00
|
|
|
if (readerCumulative) {
|
2012-11-28 13:46:49 +01:00
|
|
|
QStringList baseVPathsCumulative = baseVPaths(readerCumulative, projectDir, buildDir);
|
|
|
|
|
QStringList vPathsCumulative = fullVPaths(baseVPathsCumulative, readerCumulative, varName, projectDir);
|
2012-04-19 13:43:51 +02:00
|
|
|
result += readerCumulative->absoluteFileValues(varName,
|
|
|
|
|
projectDir,
|
2012-06-05 17:32:30 +02:00
|
|
|
vPathsCumulative,
|
2012-04-19 13:43:51 +02:00
|
|
|
0);
|
2012-06-05 17:32:30 +02:00
|
|
|
}
|
2012-04-19 13:43:51 +02:00
|
|
|
result.removeDuplicates();
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
QString QmakeProFileNode::uiDirPath(QtSupport::ProFileReader *reader, const QString &buildDir)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2012-01-13 14:20:45 +01:00
|
|
|
QString path = reader->value(QLatin1String("UI_DIR"));
|
2010-04-13 16:34:51 +02:00
|
|
|
if (QFileInfo(path).isRelative())
|
2014-09-05 16:13:21 +02:00
|
|
|
path = QDir::cleanPath(buildDir + QLatin1Char('/') + path);
|
2010-04-13 16:34:51 +02:00
|
|
|
return path;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
QString QmakeProFileNode::mocDirPath(QtSupport::ProFileReader *reader, const QString &buildDir)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2012-01-13 14:20:45 +01:00
|
|
|
QString path = reader->value(QLatin1String("MOC_DIR"));
|
2010-04-13 16:34:51 +02:00
|
|
|
if (QFileInfo(path).isRelative())
|
2014-09-05 16:13:21 +02:00
|
|
|
path = QDir::cleanPath(buildDir + QLatin1Char('/') + path);
|
2010-04-13 16:34:51 +02:00
|
|
|
return path;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
QStringList QmakeProFileNode::includePaths(QtSupport::ProFileReader *reader, const QString &buildDir, const QString &projectDir)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
|
QStringList paths;
|
2014-09-10 12:53:55 +02:00
|
|
|
foreach (const QString &cxxflags, reader->values(QLatin1String("QMAKE_CXXFLAGS"))) {
|
2012-01-13 14:20:45 +01:00
|
|
|
if (cxxflags.startsWith(QLatin1String("-I")))
|
2010-03-29 17:11:26 +02:00
|
|
|
paths.append(cxxflags.mid(2));
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
paths.append(reader->absolutePathValues(QLatin1String("INCLUDEPATH"), projectDir));
|
2010-04-13 16:34:51 +02:00
|
|
|
// paths already contains moc dir and ui dir, due to corrrectly parsing uic.prf and moc.prf
|
|
|
|
|
// except if those directories don't exist at the time of parsing
|
2010-10-30 21:54:23 +02:00
|
|
|
// thus we add those directories manually (without checking for existence)
|
2014-09-05 16:13:21 +02:00
|
|
|
paths << mocDirPath(reader, buildDir) << uiDirPath(reader, buildDir);
|
2008-12-02 12:01:29 +01:00
|
|
|
paths.removeDuplicates();
|
|
|
|
|
return paths;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
QStringList QmakeProFileNode::libDirectories(QtSupport::ProFileReader *reader)
|
2010-03-29 15:17:04 +02:00
|
|
|
{
|
|
|
|
|
QStringList result;
|
|
|
|
|
foreach (const QString &str, reader->values(QLatin1String("LIBS"))) {
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
if (str.startsWith(QLatin1String("-L")))
|
2010-03-29 15:17:04 +02:00
|
|
|
result.append(str.mid(2));
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-02 00:37:38 +02:00
|
|
|
FileNameList QmakeProFileNode::subDirsPaths(QtSupport::ProFileReader *reader,
|
|
|
|
|
const QString &projectDir,
|
|
|
|
|
QStringList *subProjectsNotToDeploy,
|
|
|
|
|
QStringList *errors)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2015-02-02 00:37:38 +02:00
|
|
|
FileNameList subProjectPaths;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
const QStringList subDirVars = reader->values(QLatin1String("SUBDIRS"));
|
|
|
|
|
|
|
|
|
|
foreach (const QString &subDirVar, subDirVars) {
|
|
|
|
|
// Special case were subdir is just an identifier:
|
|
|
|
|
// "SUBDIR = subid
|
|
|
|
|
// subid.subdir = realdir"
|
2009-03-12 14:57:37 +01:00
|
|
|
// or
|
|
|
|
|
// "SUBDIR = subid
|
|
|
|
|
// subid.file = realdir/realfile.pro"
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
QString realDir;
|
|
|
|
|
const QString subDirKey = subDirVar + QLatin1String(".subdir");
|
2009-03-12 14:57:37 +01:00
|
|
|
const QString subDirFileKey = subDirVar + QLatin1String(".file");
|
2008-12-02 12:01:29 +01:00
|
|
|
if (reader->contains(subDirKey))
|
2010-06-08 14:02:15 +02:00
|
|
|
realDir = reader->value(subDirKey);
|
2009-03-12 14:57:37 +01:00
|
|
|
else if (reader->contains(subDirFileKey))
|
2010-06-08 14:02:15 +02:00
|
|
|
realDir = reader->value(subDirFileKey);
|
2009-03-12 14:57:37 +01:00
|
|
|
else
|
2008-12-02 12:01:29 +01:00
|
|
|
realDir = subDirVar;
|
|
|
|
|
QFileInfo info(realDir);
|
2010-06-08 14:02:15 +02:00
|
|
|
if (!info.isAbsolute())
|
2014-09-10 12:53:55 +02:00
|
|
|
info.setFile(projectDir + QLatin1Char('/') + realDir);
|
2010-06-08 14:02:15 +02:00
|
|
|
realDir = info.filePath();
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2009-07-27 12:50:42 +02:00
|
|
|
QString realFile;
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
if (info.isDir())
|
2010-02-01 12:43:56 +01:00
|
|
|
realFile = QString::fromLatin1("%1/%2.pro").arg(realDir, info.fileName());
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
else
|
2008-12-02 12:01:29 +01:00
|
|
|
realFile = realDir;
|
|
|
|
|
|
2010-01-19 15:59:36 +01:00
|
|
|
if (QFile::exists(realFile)) {
|
2012-06-01 09:50:32 +02:00
|
|
|
realFile = QDir::cleanPath(realFile);
|
2015-02-02 00:37:38 +02:00
|
|
|
subProjectPaths << FileName::fromString(realFile);
|
2012-06-01 09:50:32 +02:00
|
|
|
if (subProjectsNotToDeploy && !subProjectsNotToDeploy->contains(realFile)
|
|
|
|
|
&& reader->values(subDirVar + QLatin1String(".CONFIG"))
|
|
|
|
|
.contains(QLatin1String("no_default_target"))) {
|
|
|
|
|
subProjectsNotToDeploy->append(realFile);
|
|
|
|
|
}
|
2010-01-19 15:59:36 +01:00
|
|
|
} else {
|
2014-09-10 12:53:55 +02:00
|
|
|
if (errors)
|
2015-03-16 16:03:50 +01:00
|
|
|
errors->append(QCoreApplication::translate("QmakeProFileNode", "Could not find .pro file for subdirectory \"%1\" in \"%2\".")
|
2014-09-10 12:53:55 +02:00
|
|
|
.arg(subDirVar).arg(realDir));
|
2010-01-19 15:59:36 +01:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2015-11-03 13:52:52 +01:00
|
|
|
return Utils::filteredUnique(subProjectPaths);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
TargetInformation QmakeProFileNode::targetInformation(QtSupport::ProFileReader *reader, QtSupport::ProFileReader *readerBuildPass, const QString &buildDir, const QString &projectFilePath)
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
|
|
|
|
TargetInformation result;
|
2014-04-29 13:24:51 +02:00
|
|
|
if (!reader || !readerBuildPass)
|
2010-03-10 16:55:37 +01:00
|
|
|
return result;
|
|
|
|
|
|
2012-11-26 15:09:56 +02:00
|
|
|
QStringList builds = reader->values(QLatin1String("BUILDS"));
|
2012-10-23 17:40:10 +02:00
|
|
|
if (!builds.isEmpty()) {
|
|
|
|
|
QString build = builds.first();
|
2013-03-12 14:09:18 +01:00
|
|
|
result.buildTarget = reader->value(build + QLatin1String(".target"));
|
2012-10-23 17:40:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BUILD DIR
|
2014-09-05 16:13:21 +02:00
|
|
|
result.buildDir = buildDir;
|
2010-03-10 16:55:37 +01:00
|
|
|
|
2014-04-29 13:24:51 +02:00
|
|
|
if (readerBuildPass->contains(QLatin1String("DESTDIR")))
|
|
|
|
|
result.destDir = readerBuildPass->value(QLatin1String("DESTDIR"));
|
2010-03-10 16:55:37 +01:00
|
|
|
|
2012-10-23 17:40:10 +02:00
|
|
|
// Target
|
2014-04-29 13:24:51 +02:00
|
|
|
result.target = readerBuildPass->value(QLatin1String("TARGET"));
|
2010-03-10 16:55:37 +01:00
|
|
|
if (result.target.isEmpty())
|
2014-09-10 12:53:55 +02:00
|
|
|
result.target = QFileInfo(projectFilePath).baseName();
|
2010-03-10 16:55:37 +01:00
|
|
|
|
|
|
|
|
result.valid = true;
|
2012-10-23 17:40:10 +02:00
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
TargetInformation QmakeProFileNode::targetInformation() const
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
2013-10-29 16:08:37 +01:00
|
|
|
return m_qmakeTargetInformation;
|
2010-03-10 16:55:37 +01:00
|
|
|
}
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
InstallsList QmakeProFileNode::installsList(const QtSupport::ProFileReader *reader, const QString &projectFilePath, const QString &projectDir)
|
2010-10-27 17:19:52 +02:00
|
|
|
{
|
2014-09-10 12:53:55 +02:00
|
|
|
InstallsList result;
|
2010-10-27 17:19:52 +02:00
|
|
|
if (!reader)
|
2014-09-10 12:53:55 +02:00
|
|
|
return result;
|
2010-10-27 17:19:52 +02:00
|
|
|
const QStringList &itemList = reader->values(QLatin1String("INSTALLS"));
|
|
|
|
|
foreach (const QString &item, itemList) {
|
2012-06-01 17:09:58 +02:00
|
|
|
if (reader->values(item + QLatin1String(".CONFIG")).contains(QLatin1String("no_default_install")))
|
|
|
|
|
continue;
|
2010-10-27 17:19:52 +02:00
|
|
|
QString itemPath;
|
2010-10-28 09:22:19 +02:00
|
|
|
const QString pathVar = item + QLatin1String(".path");
|
2010-10-27 17:19:52 +02:00
|
|
|
const QStringList &itemPaths = reader->values(pathVar);
|
|
|
|
|
if (itemPaths.count() != 1) {
|
|
|
|
|
qDebug("Invalid RHS: Variable '%s' has %d values.",
|
|
|
|
|
qPrintable(pathVar), itemPaths.count());
|
|
|
|
|
if (itemPaths.isEmpty()) {
|
2010-12-02 16:50:15 +01:00
|
|
|
qDebug("%s: Ignoring INSTALLS item '%s', because it has no path.",
|
2014-09-10 12:53:55 +02:00
|
|
|
qPrintable(projectFilePath), qPrintable(item));
|
2010-10-27 17:19:52 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-10-28 09:22:19 +02:00
|
|
|
itemPath = itemPaths.last();
|
2010-10-27 17:19:52 +02:00
|
|
|
|
|
|
|
|
const QStringList &itemFiles
|
|
|
|
|
= reader->absoluteFileValues(item + QLatin1String(".files"),
|
2014-09-10 12:53:55 +02:00
|
|
|
projectDir, QStringList() << projectDir, 0);
|
2010-10-27 17:19:52 +02:00
|
|
|
if (item == QLatin1String("target")) {
|
2014-09-10 12:53:55 +02:00
|
|
|
result.targetPath = itemPath;
|
2010-10-27 17:19:52 +02:00
|
|
|
} else {
|
|
|
|
|
if (itemFiles.isEmpty()) {
|
2010-12-16 14:46:24 +01:00
|
|
|
// TODO: Fix QMAKE_SUBSTITUTES handling in pro file reader, then uncomment again
|
|
|
|
|
// if (!reader->values(item + QLatin1String(".CONFIG"))
|
|
|
|
|
// .contains(QLatin1String("no_check_exist"))) {
|
|
|
|
|
// qDebug("%s: Ignoring INSTALLS item '%s', because it has no files.",
|
|
|
|
|
// qPrintable(m_projectFilePath), qPrintable(item));
|
|
|
|
|
// }
|
2010-10-27 17:19:52 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
2014-09-10 12:53:55 +02:00
|
|
|
result.items << InstallsItem(itemPath, itemFiles);
|
2010-10-27 17:19:52 +02:00
|
|
|
}
|
|
|
|
|
}
|
2014-09-10 12:53:55 +02:00
|
|
|
return result;
|
2010-10-27 17:19:52 +02:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
InstallsList QmakeProFileNode::installsList() const
|
2010-10-27 17:19:52 +02:00
|
|
|
{
|
|
|
|
|
return m_installsList;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QString QmakeProFileNode::sourceDir() const
|
2012-05-03 12:42:05 +02:00
|
|
|
{
|
|
|
|
|
return m_projectDir;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QString QmakeProFileNode::buildDir(QmakeBuildConfiguration *bc) const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2016-01-08 12:49:00 +01:00
|
|
|
const QDir srcDirRoot = m_project->rootProjectNode()->sourceDir();
|
2008-12-02 12:01:29 +01:00
|
|
|
const QString relativeDir = srcDirRoot.relativeFilePath(m_projectDir);
|
2011-01-21 15:37:05 +01:00
|
|
|
if (!bc && m_project->activeTarget())
|
2013-10-16 14:00:45 +02:00
|
|
|
bc = static_cast<QmakeBuildConfiguration *>(m_project->activeTarget()->activeBuildConfiguration());
|
2011-01-21 15:37:05 +01:00
|
|
|
if (!bc)
|
|
|
|
|
return QString();
|
2013-08-16 17:45:16 +02:00
|
|
|
return QDir::cleanPath(QDir(bc->buildDirectory().toString()).absoluteFilePath(relativeDir));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2016-01-15 16:12:54 +01:00
|
|
|
QStringList QmakeProFileNode::generatedFiles(const QString &buildDir,
|
|
|
|
|
const ProjectExplorer::FileNode *sourceFile) const
|
2009-12-03 16:23:15 +01:00
|
|
|
{
|
2016-01-15 16:12:54 +01:00
|
|
|
// The mechanism for finding the file names is rather crude, but as we
|
|
|
|
|
// cannot parse QMAKE_EXTRA_COMPILERS and qmake has facilities to put
|
|
|
|
|
// ui_*.h files into a special directory, or even change the .h suffix, we
|
|
|
|
|
// cannot help doing this here.
|
2016-01-15 16:58:22 +01:00
|
|
|
switch (sourceFile->fileType()) {
|
|
|
|
|
case FormType: {
|
2016-01-15 16:12:54 +01:00
|
|
|
FileName location;
|
|
|
|
|
auto it = m_varValues.constFind(UiDirVar);
|
|
|
|
|
if (it != m_varValues.constEnd() && !it.value().isEmpty())
|
|
|
|
|
location = FileName::fromString(it.value().front());
|
|
|
|
|
else
|
|
|
|
|
location = FileName::fromString(buildDir);
|
|
|
|
|
if (location.isEmpty())
|
|
|
|
|
return QStringList();
|
|
|
|
|
location.appendPath(QLatin1String("ui_")
|
|
|
|
|
+ sourceFile->filePath().toFileInfo().completeBaseName()
|
|
|
|
|
+ singleVariableValue(HeaderExtensionVar));
|
|
|
|
|
return QStringList(QDir::cleanPath(location.toString()));
|
2016-01-15 16:58:22 +01:00
|
|
|
}
|
|
|
|
|
case StateChartType: {
|
|
|
|
|
if (buildDir.isEmpty())
|
|
|
|
|
return QStringList();
|
|
|
|
|
QString location = QDir::cleanPath(FileName::fromString(buildDir).appendPath(
|
|
|
|
|
sourceFile->filePath().toFileInfo().completeBaseName()).toString());
|
|
|
|
|
return QStringList({location + singleVariableValue(HeaderExtensionVar),
|
|
|
|
|
location + singleVariableValue(CppExtensionVar)});
|
|
|
|
|
}
|
|
|
|
|
default:
|
2016-01-15 16:12:54 +01:00
|
|
|
// TODO: Other types will be added when adapters for their compilers become available.
|
|
|
|
|
return QStringList();
|
|
|
|
|
}
|
2009-12-03 16:23:15 +01:00
|
|
|
}
|
|
|
|
|
|
2016-01-15 16:12:54 +01:00
|
|
|
QList<ExtraCompiler *> QmakeProFileNode::extraCompilers() const
|
2009-12-03 16:23:15 +01:00
|
|
|
{
|
2016-01-15 16:12:54 +01:00
|
|
|
return m_extraCompilers;
|
2009-12-03 16:23:15 +01:00
|
|
|
}
|
|
|
|
|
|
2016-01-15 16:12:54 +01:00
|
|
|
void QmakeProFileNode::updateGeneratedFiles(const QString &buildDir)
|
2009-05-12 14:12:20 +02:00
|
|
|
{
|
2016-01-15 16:12:54 +01:00
|
|
|
// We can do this because other plugins are not supposed to keep the compilers around.
|
|
|
|
|
qDeleteAll(m_extraCompilers);
|
|
|
|
|
m_extraCompilers.clear();
|
|
|
|
|
|
|
|
|
|
// Only those project types can have generated files for us
|
|
|
|
|
if (m_projectType != ApplicationTemplate && m_projectType != SharedLibraryTemplate &&
|
|
|
|
|
m_projectType != StaticLibraryTemplate) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-10-08 14:33:33 +02:00
|
|
|
|
2016-01-15 16:12:54 +01:00
|
|
|
QList<ExtraCompilerFactory *> factories =
|
|
|
|
|
ProjectExplorer::ExtraCompilerFactory::extraCompilerFactories();
|
2009-05-12 14:12:20 +02:00
|
|
|
|
2016-01-15 16:12:54 +01:00
|
|
|
FindGeneratorSourcesVisitor filesVisitor(factories, [&](
|
|
|
|
|
FileNode *file, ExtraCompilerFactory *factory) {
|
|
|
|
|
QStringList generated = generatedFiles(buildDir, file);
|
|
|
|
|
if (!generated.isEmpty()) {
|
|
|
|
|
FileNameList fileNames = Utils::transform(generated, [](const QString &name) {
|
|
|
|
|
return FileName::fromString(name);
|
|
|
|
|
});
|
|
|
|
|
m_extraCompilers.append(factory->create(m_project, file->filePath(), fileNames));
|
2015-07-22 12:28:46 +02:00
|
|
|
}
|
2016-01-15 16:12:54 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Find all generated files
|
|
|
|
|
accept(&filesVisitor);
|
2009-05-12 14:12:20 +02:00
|
|
|
}
|