2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2015-01-14 18:07:15 +01:00
|
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
|
|
|
** Contact: http://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
|
2015-01-14 18:07:15 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms and
|
|
|
|
|
** conditions see http://www.qt.io/terms-conditions. For further information
|
2014-10-01 13:21:18 +02:00
|
|
|
** use the contact form at http://www.qt.io/contact-us.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2009-02-25 09:02:17 +01:00
|
|
|
** GNU Lesser General Public License Usage
|
2012-10-02 09:12:39 +02:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
2014-10-01 13:21:18 +02:00
|
|
|
** General Public License version 2.1 or version 3 as published by the Free
|
|
|
|
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
|
|
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
|
|
|
** following information to ensure the GNU Lesser General Public License
|
|
|
|
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
|
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
2012-10-02 09:12:39 +02:00
|
|
|
**
|
2015-01-14 18:07:15 +01:00
|
|
|
** In addition, as a special exception, The Qt Company gives you certain additional
|
|
|
|
|
** rights. These rights are described in The Qt Company LGPL Exception
|
2010-12-17 16:01:08 +01:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
|
**
|
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>
|
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
|
|
|
|
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>
|
2013-07-09 16:41:57 +02:00
|
|
|
#include <qtsupport/uicodemodelsupport.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>
|
2012-08-23 15:53:58 +02:00
|
|
|
#include <utils/hostosinfo.h>
|
2014-11-03 12:29:43 +01:00
|
|
|
#include <utils/qtcprocess.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
|
|
|
|
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;
|
2010-02-12 12:40:32 +01:00
|
|
|
const char *typeName;
|
|
|
|
|
const char *icon;
|
2014-10-15 23:07:33 +02:00
|
|
|
Theme::ImageFile themeImage;
|
2010-02-12 12:40:32 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const FileTypeDataStorage fileTypeDataStorage[] = {
|
2015-02-01 18:44:47 +02:00
|
|
|
{ HeaderType, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Headers"),
|
2014-10-15 23:07:33 +02:00
|
|
|
":/qmakeprojectmanager/images/headers.png", Theme::ProjectExplorerHeader },
|
2015-02-01 18:44:47 +02:00
|
|
|
{ SourceType, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Sources"),
|
2014-10-15 23:07:33 +02:00
|
|
|
":/qmakeprojectmanager/images/sources.png", Theme::ProjectExplorerSource },
|
2015-02-01 18:44:47 +02:00
|
|
|
{ FormType, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Forms"),
|
2014-10-15 23:07:33 +02:00
|
|
|
":/qtsupport/images/forms.png", Theme::ProjectExplorerForm },
|
2015-02-01 18:44:47 +02:00
|
|
|
{ ResourceType, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Resources"),
|
2014-10-15 23:07:33 +02:00
|
|
|
":/qtsupport/images/qt_qrc.png", Theme::ProjectExplorerResource },
|
2015-02-01 18:44:47 +02:00
|
|
|
{ QMLType, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "QML"),
|
2014-10-15 23:07:33 +02:00
|
|
|
":/qtsupport/images/qml.png", Theme::ProjectExplorerQML },
|
2015-02-01 18:44:47 +02:00
|
|
|
{ UnknownFileType, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Other files"),
|
2014-10-15 23:07:33 +02:00
|
|
|
":/qmakeprojectmanager/images/unknown.png", Theme::ProjectExplorerOtherFiles }
|
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)
|
2014-02-10 16:05:35 +01:00
|
|
|
{ return operator()(a->path(), b->path()); }
|
2015-02-01 18:44:47 +02:00
|
|
|
bool operator()(Node *a, const QString &b)
|
2014-02-10 16:05:35 +01:00
|
|
|
{ return operator()(a->path(), b); }
|
2015-02-01 18:44:47 +02:00
|
|
|
bool operator()(const QString &a, Node *b)
|
2014-02-10 16:05:35 +01:00
|
|
|
{ return operator()(a, b->path()); }
|
|
|
|
|
bool operator()(const QString &a, const QString &b)
|
|
|
|
|
{ return a < b; }
|
|
|
|
|
};
|
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(),
|
|
|
|
|
const QIcon &i = QIcon()) :
|
|
|
|
|
type(t), typeName(tN), 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;
|
|
|
|
|
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);
|
|
|
|
|
|
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
|
|
|
const QPixmap folderPixmap =
|
|
|
|
|
Core::FileIconProvider::overlayIcon(QStyle::SP_DirIcon,
|
|
|
|
|
overlayIcon, desiredSize);
|
|
|
|
|
QIcon folderIcon;
|
|
|
|
|
folderIcon.addPixmap(folderPixmap);
|
2015-01-09 15:50:06 +01:00
|
|
|
const QString desc = QCoreApplication::translate("QmakeProjectManager::QmakePriFileNode", fileTypeDataStorage[i].typeName);
|
2013-10-29 16:08:37 +01:00
|
|
|
fileTypeData.push_back(QmakeNodeStaticData::FileTypeData(fileTypeDataStorage[i].type,
|
2012-03-27 16:37:33 +02:00
|
|
|
desc, 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,
|
|
|
|
|
QLatin1String(":/qtsupport/images/qt_project.png"));
|
|
|
|
|
const QIcon projectBaseIcon(fileName);
|
2010-02-12 12:40:32 +01:00
|
|
|
const QPixmap projectPixmap = Core::FileIconProvider::overlayIcon(QStyle::SP_DirIcon,
|
|
|
|
|
projectBaseIcon,
|
|
|
|
|
desiredSize);
|
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;
|
|
|
|
|
QString projectFilePath;
|
|
|
|
|
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
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class EvalResult
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
enum EvalResultState { EvalAbort, EvalFail, EvalPartial, EvalOk };
|
|
|
|
|
EvalResultState state;
|
|
|
|
|
QmakeProjectType projectType;
|
|
|
|
|
|
|
|
|
|
QStringList subProjectsNotToDeploy;
|
|
|
|
|
QHash<QString, ProFile*> includeFilesExact;
|
|
|
|
|
QStringList newProjectFilesExact;
|
|
|
|
|
QSet<QString> exactSubdirs;
|
|
|
|
|
ProFile *fileForCurrentProjectExact; // probably only used in parser thread
|
|
|
|
|
QHash<QString, ProFile*> includeFilesCumlative;
|
|
|
|
|
QStringList newProjectFilesCumlative;
|
|
|
|
|
ProFile *fileForCurrentProjectCumlative; // probably only used in parser thread
|
|
|
|
|
TargetInformation targetInformation;
|
|
|
|
|
InstallsList installsList;
|
|
|
|
|
QHash<QmakeVariable, QStringList> newVarValues;
|
|
|
|
|
bool isDeployable;
|
|
|
|
|
QHash<QString, PriFileEvalResult> priFileResults;
|
|
|
|
|
QStringList errors;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-01-09 15:50:06 +01:00
|
|
|
|
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-02-01 18:44:47 +02:00
|
|
|
setFilePath(FileName::fromString(m_priFile->path()));
|
2010-01-20 14:47:08 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakePriFile::save(QString *errorString, const QString &fileName, bool autoSave)
|
2010-01-20 14:47:08 +01:00
|
|
|
{
|
2011-03-30 13:45:16 +02:00
|
|
|
Q_UNUSED(errorString);
|
2010-01-20 14:47:08 +01:00
|
|
|
Q_UNUSED(fileName);
|
2011-05-10 20:43:03 +02:00
|
|
|
Q_UNUSED(autoSave);
|
2010-01-20 14:47:08 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QString QmakePriFile::defaultPath() const
|
2010-01-20 14:47:08 +01:00
|
|
|
{
|
2010-02-02 17:09:41 +01:00
|
|
|
return QString();
|
2010-01-20 14:47:08 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QString QmakePriFile::suggestedFileName() const
|
2010-01-20 14:47:08 +01:00
|
|
|
{
|
2010-02-02 17:09:41 +01:00
|
|
|
return QString();
|
2010-01-20 14:47:08 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakePriFile::isModified() const
|
2010-01-20 14:47:08 +01:00
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakePriFile::isSaveAsAllowed() const
|
2010-01-20 14:47:08 +01:00
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
2013-10-29 17:37:39 +01:00
|
|
|
QmakePriFileNode::QmakePriFileNode(QmakeProject *project, QmakeProFileNode *qmakeProFileNode, const QString &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),
|
2008-12-04 11:10:56 +01:00
|
|
|
m_projectFilePath(QDir::fromNativeSeparators(filePath)),
|
2011-09-06 17:21:51 +02:00
|
|
|
m_projectDir(QFileInfo(filePath).absolutePath()),
|
|
|
|
|
m_includedInExactParse(true)
|
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
|
|
|
|
2010-02-24 15:03:54 +01:00
|
|
|
setDisplayName(QFileInfo(filePath).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
|
|
|
{
|
2011-05-20 21:40:53 +02:00
|
|
|
QtSupport::ProFileCacheManager::instance()->discardFile(m_projectFilePath);
|
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;
|
2010-02-26 12:55:17 +01:00
|
|
|
QStringList files;
|
2015-02-01 18:44:47 +02:00
|
|
|
FileType type;
|
2013-02-18 18:47:54 +01:00
|
|
|
int priority;
|
2010-08-10 16:27:35 +02:00
|
|
|
QString displayName;
|
2012-05-04 11:49:37 +02:00
|
|
|
QString typeName;
|
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()
|
|
|
|
|
{
|
2015-02-01 18:44:47 +02:00
|
|
|
type = UnknownFileType;
|
2012-05-04 11:49:37 +02:00
|
|
|
priority = 0;
|
2010-02-26 12:55:17 +01:00
|
|
|
}
|
2009-08-25 15:39:31 +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
|
2011-11-08 18:53:51 +01:00
|
|
|
currentNode->files.append(file.toString());
|
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);
|
2012-01-13 14:20:45 +01:00
|
|
|
keep->displayName = i.value()->displayName + QLatin1Char('/') + 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;
|
|
|
|
|
if (node->typeName.isEmpty())
|
|
|
|
|
newNode = new FolderNode(node->fullPath);
|
|
|
|
|
else
|
|
|
|
|
newNode = new ProVirtualFolderNode(node->fullPath, node->priority, node->typeName);
|
|
|
|
|
|
|
|
|
|
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))
|
2012-05-04 11:49:37 +02:00
|
|
|
existingFolderNodes.insert(node->path(), 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;
|
2014-02-10 16:05:35 +01:00
|
|
|
QStringList filesToAdd;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
foreach (const QString &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;
|
2014-02-18 21:38:03 +01:00
|
|
|
QStringList resourcesToAdd;
|
|
|
|
|
|
|
|
|
|
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());
|
|
|
|
|
|
|
|
|
|
foreach (const QString &file, resourcesToAdd)
|
|
|
|
|
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
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
PriFileEvalResult QmakePriFileNode::extractValues(const EvalInput &input, ProFile *includeFileExact, ProFile *includeFileCumlative,
|
|
|
|
|
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);
|
2011-02-09 14:59:07 +01:00
|
|
|
if (includeFileExact)
|
|
|
|
|
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) {
|
2011-02-09 14:59:07 +01:00
|
|
|
if (includeFileExact) {
|
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
|
|
|
}
|
|
|
|
|
if (includeFileCumlative) {
|
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;
|
|
|
|
|
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:
|
2011-05-05 17:42:35 +02:00
|
|
|
case LibraryTemplate:
|
|
|
|
|
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;
|
|
|
|
|
if (m_recursiveEnumerateFiles.contains(FileName::fromString(node->path())))
|
|
|
|
|
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-01-09 15:50:06 +01:00
|
|
|
FolderNode *folder = dynamic_cast<FolderNode *>(node);
|
2010-08-24 18:22:57 +02:00
|
|
|
if (folder) {
|
|
|
|
|
QStringList list;
|
|
|
|
|
foreach (FolderNode *f, folder->subFolderNodes())
|
2012-01-13 14:20:45 +01:00
|
|
|
list << f->path() + QLatin1Char('/');
|
2010-08-24 18:22:57 +02:00
|
|
|
if (deploysFolder(Utils::commonPath(list)))
|
|
|
|
|
addExistingFiles = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-27 13:32:32 +02:00
|
|
|
addExistingFiles = addExistingFiles && !deploysFolder(node->path());
|
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-01 18:44:47 +02:00
|
|
|
FileNode *fileNode = dynamic_cast<FileNode *>(node);
|
|
|
|
|
if ((fileNode && fileNode->fileType() != ProjectFileType)
|
2015-01-09 15:50:06 +01:00
|
|
|
|| dynamic_cast<ResourceEditor::ResourceTopLevelNode *>(node))
|
2015-02-01 18:44:47 +02:00
|
|
|
actions << Rename;
|
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);
|
|
|
|
|
const QStringList &allFiles = visitor.filePaths();
|
|
|
|
|
|
|
|
|
|
QStringList uniqueProFilePaths;
|
2010-08-27 15:44:15 +02:00
|
|
|
foreach (const QString &proFile, proFilePaths)
|
|
|
|
|
if (!allFiles.contains(proFile))
|
|
|
|
|
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);
|
|
|
|
|
const QStringList &allFiles = visitor.filePaths();
|
|
|
|
|
|
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;
|
2014-07-24 11:44:35 +02:00
|
|
|
foreach (const QString &file, filePaths) {
|
2013-08-30 16:38:57 +02:00
|
|
|
const Core::MimeType mt = Core::MimeDatabase::findByFile(file);
|
2013-07-01 16:13:48 +02:00
|
|
|
typeFileMap[mt.type()] << 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) {
|
|
|
|
|
if (!allFiles.contains(file))
|
|
|
|
|
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) {
|
|
|
|
|
if (!allFiles.contains(file))
|
|
|
|
|
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;
|
2014-07-24 11:44:35 +02:00
|
|
|
foreach (const QString &file, filePaths) {
|
2013-08-30 16:38:57 +02:00
|
|
|
const Core::MimeType mt = Core::MimeDatabase::findByFile(file);
|
2013-07-01 16:13:48 +02:00
|
|
|
typeFileMap[mt.type()] << file;
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakePriFileNode::renameFile(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());
|
2013-08-30 16:38:57 +02:00
|
|
|
const Core::MimeType mt = Core::MimeDatabase::findByFile(newFilePath);
|
2008-12-02 12:01:29 +01:00
|
|
|
QStringList dummy;
|
2013-07-01 16:13:48 +02:00
|
|
|
|
|
|
|
|
changeFiles(mt.type(), QStringList() << filePath, &dummy, RemoveFromProFile);
|
2012-04-18 11:50:32 +02:00
|
|
|
if (!dummy.isEmpty() && !changeProFileOptional)
|
2008-12-02 12:01:29 +01:00
|
|
|
return false;
|
2013-07-01 16:13:48 +02:00
|
|
|
changeFiles(mt.type(), QStringList() << newFilePath, &dummy, AddToProFile);
|
2012-04-18 11:50:32 +02:00
|
|
|
if (!dummy.isEmpty() && !changeProFileOptional)
|
2008-12-02 12:01:29 +01:00
|
|
|
return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
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-02-01 18:44:47 +02:00
|
|
|
return FolderNode::AddNewInformation(FileName::fromString(path()).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
|
2014-05-07 16:25:04 +02:00
|
|
|
= Core::DocumentModel::documentForFilePath(m_projectFilePath);
|
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
|
|
|
|
|
QtSupport::ProFileCacheManager::instance()->discardFile(m_projectFilePath);
|
2013-10-29 17:37:39 +01:00
|
|
|
m_project->qmakeProjectManager()->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);
|
2013-09-26 18:38:44 +02:00
|
|
|
includeFile = parser.parsedProBlock(contents, file, 1);
|
2008-12-05 14:29:18 +01:00
|
|
|
}
|
2013-09-26 18:38:44 +02:00
|
|
|
return qMakePair(includeFile, lines);
|
|
|
|
|
}
|
|
|
|
|
|
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,
|
|
|
|
|
ChangeType change)
|
|
|
|
|
{
|
|
|
|
|
if (filePaths.isEmpty())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
*notChanged = filePaths;
|
|
|
|
|
|
|
|
|
|
// Check for modified editors
|
|
|
|
|
if (!saveModifiedEditors())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!ensureWriteableProFile(m_projectFilePath))
|
|
|
|
|
return;
|
|
|
|
|
QPair<ProFile *, QStringList> pair = readProFile(m_projectFilePath);
|
|
|
|
|
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
|
2010-01-14 22:58:55 +01:00
|
|
|
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
|
|
|
{
|
|
|
|
|
if (!ensureWriteableProFile(m_projectFilePath))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
QPair<ProFile *, QStringList> pair = readProFile(m_projectFilePath);
|
|
|
|
|
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
|
|
|
{
|
|
|
|
|
Core::DocumentManager::expectFileChange(m_projectFilePath);
|
2015-02-01 18:44:47 +02:00
|
|
|
FileSaver saver(m_projectFilePath, QIODevice::Text);
|
2014-08-23 01:19:53 +02:00
|
|
|
saver.write(lines.join(QLatin1Char('\n')).toLocal8Bit());
|
2013-09-26 18:38:44 +02:00
|
|
|
saver.finalize(Core::ICore::mainWindow());
|
2010-01-14 21:51:34 +01:00
|
|
|
|
2013-10-29 17:37:39 +01:00
|
|
|
m_project->qmakeProjectManager()->notifyChanged(m_projectFilePath);
|
2013-09-26 18:38:44 +02:00
|
|
|
Core::DocumentManager::unexpectFileChange(m_projectFilePath);
|
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;
|
2014-05-07 16:25:04 +02:00
|
|
|
Core::IDocument *document = Core::DocumentModel::documentForFilePath(m_projectFilePath);
|
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)
|
|
|
|
|
// FORMS and RESOURCES are handled below
|
2014-02-13 12:01:28 +01:00
|
|
|
if (input != QLatin1String("FORMS")
|
|
|
|
|
&& 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;
|
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
|
|
|
|
|
|
|
|
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");
|
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;
|
|
|
|
|
case ProFileEvaluator::TT_Library:
|
|
|
|
|
return LibraryTemplate;
|
|
|
|
|
case ProFileEvaluator::TT_Script:
|
|
|
|
|
return ScriptTemplate;
|
|
|
|
|
case ProFileEvaluator::TT_Aux:
|
|
|
|
|
return AuxTemplate;
|
|
|
|
|
case ProFileEvaluator::TT_Subdirs:
|
|
|
|
|
return SubDirsTemplate;
|
|
|
|
|
default:
|
|
|
|
|
return InvalidProject;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
// find all ui files in project
|
2015-02-01 18:44:47 +02:00
|
|
|
class FindUiFileNodesVisitor : public NodesVisitor {
|
2011-05-25 11:23:25 +02:00
|
|
|
public:
|
|
|
|
|
void visitProjectNode(ProjectNode *projectNode)
|
|
|
|
|
{
|
|
|
|
|
visitFolderNode(projectNode);
|
|
|
|
|
}
|
|
|
|
|
void visitFolderNode(FolderNode *folderNode)
|
|
|
|
|
{
|
|
|
|
|
foreach (FileNode *fileNode, folderNode->fileNodes()) {
|
2015-02-01 18:44:47 +02:00
|
|
|
if (fileNode->fileType() == FormType)
|
2011-05-25 11:23:25 +02:00
|
|
|
uiFileNodes << fileNode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
QList<FileNode*> uiFileNodes;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
const QmakeProFileNode *QmakeProFileNode::findProFileFor(const QString &fileName) const
|
2009-04-28 14:30:17 +02:00
|
|
|
{
|
|
|
|
|
if (fileName == path())
|
|
|
|
|
return this;
|
|
|
|
|
foreach (ProjectNode *pn, subProjectNodes())
|
2015-01-09 15:50:06 +01:00
|
|
|
if (QmakeProFileNode *qmakeProFileNode = dynamic_cast<QmakeProFileNode *>(pn))
|
2013-10-29 17:37:39 +01:00
|
|
|
if (const 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-01-09 15:50:06 +01:00
|
|
|
const QString &filePath)
|
2013-10-29 14:22:31 +01:00
|
|
|
: QmakePriFileNode(project, this, filePath),
|
2010-10-27 16:27:22 +02:00
|
|
|
m_validParse(false),
|
2012-05-08 12:53:24 +02:00
|
|
|
m_parseInProgress(true),
|
2013-02-18 18:47:54 +01:00
|
|
|
m_projectType(InvalidProject),
|
2010-03-10 16:55:37 +01:00
|
|
|
m_readerExact(0),
|
|
|
|
|
m_readerCumulative(0)
|
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
|
|
|
{
|
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-01-10 23:40:32 +02:00
|
|
|
return AddNewInformation(FileName::fromString(path()).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
|
|
|
{
|
|
|
|
|
return (projectType == ApplicationTemplate || projectType == LibraryTemplate);
|
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
|
|
|
QHash<QString, QString> QmakeProFileNode::uiFiles() const
|
2012-10-08 14:33:33 +02:00
|
|
|
{
|
2013-07-11 16:24:51 +02:00
|
|
|
return m_uiFiles;
|
2012-10-08 14:33:33 +02:00
|
|
|
}
|
|
|
|
|
|
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();
|
2010-10-25 17:26:41 +02:00
|
|
|
m_parseFutureWatcher.waitForFinished();
|
2014-09-10 12:53:55 +02:00
|
|
|
EvalInput input = evalInput();
|
|
|
|
|
QFuture<EvalResult *> future = QtConcurrent::run(&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
|
|
|
static QStringList mergeList(const QStringList &listA, const QStringList &listB)
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
2014-09-10 12:53:55 +02:00
|
|
|
QStringList result;
|
|
|
|
|
result.reserve(qMax(listA.size(), listB.size()));
|
|
|
|
|
auto ait = listA.constBegin();
|
|
|
|
|
auto aend = listA.constEnd();
|
|
|
|
|
auto bit = listB.constBegin();
|
2014-10-17 14:48:16 +02:00
|
|
|
auto bend = listB.constEnd();
|
2014-09-10 12:53:55 +02:00
|
|
|
while (ait != aend && bit != bend) {
|
|
|
|
|
const QString &a = *ait;
|
|
|
|
|
const QString &b = *bit;
|
|
|
|
|
if (a < b) {
|
|
|
|
|
result.append(a);
|
|
|
|
|
++ait;
|
|
|
|
|
} else if (b < a) {
|
|
|
|
|
result.append(b);
|
|
|
|
|
++bit;
|
|
|
|
|
} else {
|
|
|
|
|
result.append(a);
|
|
|
|
|
++ait;
|
|
|
|
|
++bit;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
while (ait != aend) {
|
|
|
|
|
result.append(*ait);
|
|
|
|
|
++ait;
|
|
|
|
|
}
|
|
|
|
|
while (bit != bend) {
|
|
|
|
|
result.append(*bit);
|
|
|
|
|
++bit;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EvalResult *QmakeProFileNode::evaluate(const EvalInput &input)
|
|
|
|
|
{
|
|
|
|
|
EvalResult *result = new EvalResult;
|
|
|
|
|
if (ProFile *pro = input.readerExact->parsedProFile(input.projectFilePath)) {
|
|
|
|
|
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());
|
|
|
|
|
result->fileForCurrentProjectExact = 0;
|
|
|
|
|
result->fileForCurrentProjectCumlative = 0;
|
|
|
|
|
|
|
|
|
|
if (result->state == EvalResult::EvalOk) {
|
|
|
|
|
if (result->projectType == SubDirsTemplate) {
|
|
|
|
|
QStringList errors;
|
|
|
|
|
result->newProjectFilesExact = subDirsPaths(input.readerExact, input.projectDir, &result->subProjectsNotToDeploy, &errors);
|
|
|
|
|
result->errors.append(errors);
|
|
|
|
|
result->exactSubdirs = result->newProjectFilesExact.toSet();
|
|
|
|
|
}
|
|
|
|
|
foreach (ProFile *includeFile, input.readerExact->includeFiles()) {
|
|
|
|
|
if (includeFile->fileName() == input.projectFilePath) { // this file
|
|
|
|
|
result->fileForCurrentProjectExact = includeFile;
|
|
|
|
|
} else {
|
|
|
|
|
result->newProjectFilesExact << includeFile->fileName();
|
|
|
|
|
result->includeFilesExact.insert(includeFile->fileName(), includeFile);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (result->projectType == SubDirsTemplate)
|
|
|
|
|
result->newProjectFilesCumlative = subDirsPaths(input.readerCumulative, input.projectDir, 0, 0);
|
|
|
|
|
foreach (ProFile *includeFile, input.readerCumulative->includeFiles()) {
|
|
|
|
|
if (includeFile->fileName() == input.projectFilePath) {
|
|
|
|
|
result->fileForCurrentProjectCumlative = includeFile;
|
|
|
|
|
} else {
|
|
|
|
|
result->newProjectFilesCumlative << includeFile->fileName();
|
|
|
|
|
result->includeFilesCumlative.insert(includeFile->fileName(), includeFile);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
SortByPath sortByPath;
|
|
|
|
|
Utils::sort(result->newProjectFilesExact, sortByPath);
|
|
|
|
|
Utils::sort(result->newProjectFilesCumlative, sortByPath);
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
if (ProFile *pro = readerBuildPass->parsedProFile(input.projectFilePath)) {
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
result->targetInformation = targetInformation(input.readerExact, readerBuildPass, input.buildDirectory, input.projectFilePath);
|
|
|
|
|
result->installsList = installsList(readerBuildPass, input.projectFilePath, input.projectDir);
|
|
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
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"));
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// extract values
|
|
|
|
|
QStringList allFiles = mergeList(result->newProjectFilesExact, result->newProjectFilesCumlative);
|
|
|
|
|
foreach (const QString &file, allFiles) {
|
|
|
|
|
ProFile *fileExact = result->includeFilesExact.value(file);
|
|
|
|
|
ProFile *fileCumlative = result->includeFilesCumlative.value(file);
|
|
|
|
|
if (fileExact || fileCumlative) {
|
|
|
|
|
result->priFileResults[file] = extractValues(input, fileExact, fileCumlative, variableAndVPathInformation);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
result->priFileResults[input.projectFilePath] = extractValues(input, result->fileForCurrentProjectExact,
|
|
|
|
|
result->fileForCurrentProjectCumlative,
|
|
|
|
|
variableAndVPathInformation);
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
return a->path() < b->path();
|
|
|
|
|
}
|
|
|
|
|
|
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;
|
2010-03-11 17:01:06 +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
|
|
|
m_readerExact = m_readerCumulative = 0;
|
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-01-09 15:50:06 +01:00
|
|
|
QmakeProject::proFileParseError(QCoreApplication::translate("QmakeProFileNode", "Error while parsing file %1. Giving up.").arg(m_projectFilePath));
|
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
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
QList<ProjectNode*> existingProjectNodes = subProjectNodes();
|
|
|
|
|
|
2014-09-05 16:13:21 +02:00
|
|
|
QString buildDirectory = buildDir();
|
2014-02-10 16:05:35 +01:00
|
|
|
SortByPath sortByPath;
|
2014-06-16 18:25:52 +04:00
|
|
|
Utils::sort(existingProjectNodes, sortByPath);
|
2014-09-10 12:53:55 +02:00
|
|
|
// result is already sorted
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
QList<ProjectNode*> toAdd;
|
|
|
|
|
QList<ProjectNode*> toRemove;
|
|
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
QList<ProjectNode*>::const_iterator existingIt = existingProjectNodes.constBegin();
|
2014-09-10 12:53:55 +02:00
|
|
|
QStringList::const_iterator newExactIt = result->newProjectFilesExact.constBegin();
|
|
|
|
|
QStringList::const_iterator newCumlativeIt = result->newProjectFilesCumlative.constBegin();
|
2010-03-10 16:55:37 +01:00
|
|
|
|
|
|
|
|
forever {
|
|
|
|
|
bool existingAtEnd = (existingIt == existingProjectNodes.constEnd());
|
2014-09-10 12:53:55 +02:00
|
|
|
bool newExactAtEnd = (newExactIt == result->newProjectFilesExact.constEnd());
|
|
|
|
|
bool newCumlativeAtEnd = (newCumlativeIt == result->newProjectFilesCumlative.constEnd());
|
2010-03-10 16:55:37 +01:00
|
|
|
|
|
|
|
|
if (existingAtEnd && newExactAtEnd && newCumlativeAtEnd)
|
|
|
|
|
break; // we are done, hurray!
|
|
|
|
|
|
2010-10-30 21:54:23 +02:00
|
|
|
// So this is one giant loop comparing 3 lists at once and sorting the comparison
|
2010-03-10 16:55:37 +01:00
|
|
|
// into mainly 2 buckets: toAdd and toRemove
|
|
|
|
|
// We need to distinguish between nodes that came from exact and cumalative
|
|
|
|
|
// parsing, since the update call is diffrent for them
|
|
|
|
|
// I believe this code to be correct, be careful in changing it
|
|
|
|
|
|
|
|
|
|
QString nodeToAdd;
|
|
|
|
|
if (! existingAtEnd
|
|
|
|
|
&& (newExactAtEnd || (*existingIt)->path() < *newExactIt)
|
|
|
|
|
&& (newCumlativeAtEnd || (*existingIt)->path() < *newCumlativeIt)) {
|
|
|
|
|
// Remove case
|
|
|
|
|
toRemove << *existingIt;
|
|
|
|
|
++existingIt;
|
2012-11-28 20:44:03 +02:00
|
|
|
} else if (! newExactAtEnd
|
2010-03-10 16:55:37 +01:00
|
|
|
&& (existingAtEnd || *newExactIt < (*existingIt)->path())
|
|
|
|
|
&& (newCumlativeAtEnd || *newExactIt < *newCumlativeIt)) {
|
|
|
|
|
// Mark node from exact for adding
|
|
|
|
|
nodeToAdd = *newExactIt;
|
|
|
|
|
++newExactIt;
|
|
|
|
|
} else if (! newCumlativeAtEnd
|
|
|
|
|
&& (existingAtEnd || *newCumlativeIt < (*existingIt)->path())
|
|
|
|
|
&& (newExactAtEnd || *newCumlativeIt < *newExactIt)) {
|
|
|
|
|
// Mark node from cumalative for adding
|
|
|
|
|
nodeToAdd = *newCumlativeIt;
|
|
|
|
|
++newCumlativeIt;
|
|
|
|
|
} else if (!newExactAtEnd
|
|
|
|
|
&& !newCumlativeAtEnd
|
|
|
|
|
&& (existingAtEnd || *newExactIt < (*existingIt)->path())
|
|
|
|
|
&& (existingAtEnd || *newCumlativeIt < (*existingIt)->path())) {
|
|
|
|
|
// Mark node from both for adding
|
|
|
|
|
nodeToAdd = *newExactIt;
|
|
|
|
|
++newExactIt;
|
|
|
|
|
++newCumlativeIt;
|
|
|
|
|
} else {
|
|
|
|
|
Q_ASSERT(!newExactAtEnd || !newCumlativeAtEnd);
|
|
|
|
|
// update case, figure out which case exactly
|
|
|
|
|
if (newExactAtEnd) {
|
|
|
|
|
++newCumlativeIt;
|
|
|
|
|
} else if (newCumlativeAtEnd) {
|
|
|
|
|
++newExactIt;
|
2012-11-28 20:44:03 +02:00
|
|
|
} else if (*newExactIt < *newCumlativeIt) {
|
2010-03-10 16:55:37 +01:00
|
|
|
++newExactIt;
|
|
|
|
|
} else if (*newCumlativeIt < *newExactIt) {
|
|
|
|
|
++newCumlativeIt;
|
2008-12-02 12:01:29 +01:00
|
|
|
} else {
|
2010-03-10 16:55:37 +01:00
|
|
|
++newExactIt;
|
|
|
|
|
++newCumlativeIt;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2010-03-10 16:55:37 +01:00
|
|
|
// Update existingNodeIte
|
2014-09-10 12:53:55 +02:00
|
|
|
ProFile *fileExact = result->includeFilesExact.value((*existingIt)->path());
|
|
|
|
|
ProFile *fileCumlative = result->includeFilesCumlative.value((*existingIt)->path());
|
2010-03-10 16:55:37 +01:00
|
|
|
if (fileExact || fileCumlative) {
|
2013-10-29 14:22:31 +01:00
|
|
|
QmakePriFileNode *priFileNode = static_cast<QmakePriFileNode *>(*existingIt);
|
2014-09-10 12:53:55 +02:00
|
|
|
priFileNode->update(result->priFileResults[(*existingIt)->path()]);
|
2011-09-06 17:21:51 +02:00
|
|
|
priFileNode->setIncludedInExactParse(fileExact != 0 && includedInExactParse());
|
2010-03-10 16:55:37 +01:00
|
|
|
} else {
|
|
|
|
|
// 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
|
2013-10-29 14:22:31 +01:00
|
|
|
QmakeProFileNode *proFileNode = static_cast<QmakeProFileNode *>(*existingIt);
|
2014-09-10 12:53:55 +02:00
|
|
|
proFileNode->setIncludedInExactParse(result->exactSubdirs.contains(proFileNode->path()) && includedInExactParse());
|
2014-09-26 15:24:32 +02:00
|
|
|
proFileNode->asyncUpdate();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2010-03-10 16:55:37 +01:00
|
|
|
++existingIt;
|
|
|
|
|
// newCumalativeIt and newExactIt are already incremented
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
}
|
2010-05-20 16:02:24 +02:00
|
|
|
// If we found something to add, do it
|
2010-03-10 16:55:37 +01:00
|
|
|
if (!nodeToAdd.isEmpty()) {
|
2014-09-10 12:53:55 +02:00
|
|
|
ProFile *fileExact = result->includeFilesExact.value(nodeToAdd);
|
|
|
|
|
ProFile *fileCumlative = result->includeFilesCumlative.value(nodeToAdd);
|
2010-05-20 16:02:24 +02:00
|
|
|
|
|
|
|
|
// Loop preventation, make sure that exact same node is not in our parent chain
|
|
|
|
|
bool loop = false;
|
2015-02-01 18:44:47 +02:00
|
|
|
Node *n = this;
|
2010-05-20 16:02:24 +02:00
|
|
|
while ((n = n->parentFolderNode())) {
|
2015-01-09 15:50:06 +01:00
|
|
|
if (dynamic_cast<QmakePriFileNode *>(n) && n->path() == nodeToAdd) {
|
2010-05-20 16:02:24 +02:00
|
|
|
loop = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (loop) {
|
|
|
|
|
// Do nothing
|
|
|
|
|
} else if (fileExact || fileCumlative) {
|
2013-10-29 17:37:39 +01:00
|
|
|
QmakePriFileNode *qmakePriFileNode = new QmakePriFileNode(m_project, this, nodeToAdd);
|
|
|
|
|
qmakePriFileNode->setParentFolderNode(this); // Needed for loop detection
|
|
|
|
|
qmakePriFileNode->setIncludedInExactParse(fileExact != 0 && includedInExactParse());
|
2014-09-10 12:53:55 +02:00
|
|
|
qmakePriFileNode->update(result->priFileResults[nodeToAdd]);
|
2013-10-29 17:37:39 +01:00
|
|
|
toAdd << qmakePriFileNode;
|
2010-03-10 16:55:37 +01:00
|
|
|
} else {
|
2013-10-29 16:08:37 +01:00
|
|
|
QmakeProFileNode *qmakeProFileNode = new QmakeProFileNode(m_project, nodeToAdd);
|
|
|
|
|
qmakeProFileNode->setParentFolderNode(this); // Needed for loop detection
|
2014-09-10 12:53:55 +02:00
|
|
|
qmakeProFileNode->setIncludedInExactParse(result->exactSubdirs.contains(qmakeProFileNode->path()) && includedInExactParse());
|
2014-09-26 15:24:32 +02:00
|
|
|
qmakeProFileNode->asyncUpdate();
|
2013-10-29 16:08:37 +01:00
|
|
|
toAdd << qmakeProFileNode;
|
2010-03-10 16:55:37 +01:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2010-03-10 16:55:37 +01:00
|
|
|
} // for
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-05-08 12:53:24 +02:00
|
|
|
foreach (ProjectNode *node, toRemove) {
|
2015-01-09 15:50:06 +01:00
|
|
|
if (QmakeProFileNode *qmakeProFileNode = dynamic_cast<QmakeProFileNode *>(node)) {
|
2013-10-29 16:08:37 +01:00
|
|
|
qmakeProFileNode->setValidParseRecursive(false);
|
|
|
|
|
qmakeProFileNode->setParseInProgressRecursive(false);
|
2012-05-08 12:53:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
if (!toRemove.isEmpty())
|
|
|
|
|
removeProjectNodes(toRemove);
|
|
|
|
|
if (!toAdd.isEmpty())
|
|
|
|
|
addProjectNodes(toAdd);
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
QmakePriFileNode::update(result->priFileResults[m_projectFilePath]);
|
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;
|
|
|
|
|
} // 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
|
|
|
|
2014-09-05 16:13:21 +02:00
|
|
|
updateUiFiles(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
|
|
|
|
|
|
|
|
m_readerExact = 0;
|
|
|
|
|
m_readerCumulative = 0;
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
QStringList QmakeProFileNode::subDirsPaths(QtSupport::ProFileReader *reader,
|
|
|
|
|
const QString &projectDir,
|
|
|
|
|
QStringList *subProjectsNotToDeploy,
|
|
|
|
|
QStringList *errors)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
|
QStringList subProjectPaths;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
subProjectPaths << realFile;
|
|
|
|
|
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-01-09 15:50:06 +01:00
|
|
|
errors->append(QCoreApplication::translate("QmakeProFileNode", "Could not find .pro file for sub dir \"%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
|
|
|
}
|
|
|
|
|
|
2010-06-08 13:57:23 +02:00
|
|
|
subProjectPaths.removeDuplicates();
|
2008-12-02 12:01:29 +01:00
|
|
|
return subProjectPaths;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
{
|
2013-10-29 14:22:31 +01:00
|
|
|
const QDir srcDirRoot = m_project->rootQmakeProjectNode()->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
|
|
|
}
|
|
|
|
|
|
2014-09-05 16:13:21 +02:00
|
|
|
QString QmakeProFileNode::uiDirectory(const QString &buildDir) const
|
2009-12-03 16:23:15 +01:00
|
|
|
{
|
2013-10-29 16:08:37 +01:00
|
|
|
const QmakeVariablesHash::const_iterator it = m_varValues.constFind(UiDirVar);
|
2009-12-03 16:23:15 +01:00
|
|
|
if (it != m_varValues.constEnd() && !it.value().isEmpty())
|
|
|
|
|
return it.value().front();
|
2014-09-05 16:13:21 +02:00
|
|
|
return buildDir;
|
2009-12-03 16:23:15 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QString QmakeProFileNode::uiHeaderFile(const QString &uiDir, const QString &formFile)
|
2009-12-03 16:23:15 +01:00
|
|
|
{
|
|
|
|
|
QString uiHeaderFilePath = uiDir;
|
|
|
|
|
uiHeaderFilePath += QLatin1String("/ui_");
|
|
|
|
|
uiHeaderFilePath += QFileInfo(formFile).completeBaseName();
|
|
|
|
|
uiHeaderFilePath += QLatin1String(".h");
|
|
|
|
|
return QDir::cleanPath(uiHeaderFilePath);
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-05 16:13:21 +02:00
|
|
|
void QmakeProFileNode::updateUiFiles(const QString &buildDir)
|
2009-05-12 14:12:20 +02:00
|
|
|
{
|
2013-07-11 16:24:51 +02:00
|
|
|
m_uiFiles.clear();
|
2012-10-08 14:33:33 +02:00
|
|
|
|
2009-05-12 14:12:20 +02:00
|
|
|
// Only those two project types can have ui files for us
|
|
|
|
|
if (m_projectType == ApplicationTemplate || m_projectType == LibraryTemplate) {
|
|
|
|
|
// Find all ui files
|
2011-09-07 11:52:04 +02:00
|
|
|
FindUiFileNodesVisitor uiFilesVisitor;
|
2009-05-12 14:12:20 +02:00
|
|
|
this->accept(&uiFilesVisitor);
|
2015-02-01 18:44:47 +02:00
|
|
|
const QList<FileNode*> uiFiles = uiFilesVisitor.uiFileNodes;
|
2009-05-12 14:12:20 +02:00
|
|
|
|
|
|
|
|
// Find the UiDir, there can only ever be one
|
2014-09-05 16:13:21 +02:00
|
|
|
const QString uiDir = uiDirectory(buildDir);
|
2015-02-01 18:44:47 +02:00
|
|
|
foreach (const FileNode *uiFile, uiFiles)
|
2013-07-11 16:24:51 +02:00
|
|
|
m_uiFiles.insert(uiFile->path(), uiHeaderFile(uiDir, uiFile->path()));
|
2009-05-12 14:12:20 +02:00
|
|
|
}
|
|
|
|
|
}
|