Merge remote-tracking branch 'origin/4.8'

Change-Id: Ia8fed69168d87afafdb5acf4de4d5d30f9b4ebf5
This commit is contained in:
Eike Ziller
2019-01-31 08:38:13 +01:00
20 changed files with 212 additions and 52 deletions

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2018 The Qt Company Ltd. ** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the Qt Creator documentation. ** This file is part of the Qt Creator documentation.
@@ -42,7 +42,11 @@
\list 1 \list 1
\li Select \uicontrol File > \uicontrol {New File or Project} > \li Select \uicontrol File > \uicontrol {New File or Project} >
\if defined(qtcreator)
\uicontrol Qt > \uicontrol {QML File (Qt Quick 2)} > \uicontrol Qt > \uicontrol {QML File (Qt Quick 2)} >
\else
\uicontrol {Qt Quick Files} > \uicontrol {Qt Quick File} >
\endif
\uicontrol Choose to create a QML file called Button.qml (for \uicontrol Choose to create a QML file called Button.qml (for
example). example).
@@ -147,7 +151,11 @@
\list 1 \list 1
\li Select \uicontrol File > \uicontrol {New File or Project} > \li Select \uicontrol File > \uicontrol {New File or Project} >
\if defined(qtcreator)
\uicontrol Qt > \uicontrol {QML File (Qt Quick 2)} > \uicontrol Qt > \uicontrol {QML File (Qt Quick 2)} >
\else
\uicontrol {Qt Quick Files} > \uicontrol {Qt Quick File} >
\endif
\uicontrol Choose to create a QML file called Button.qml (for \uicontrol Choose to create a QML file called Button.qml (for
example). example).

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2018 The Qt Company Ltd. ** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the Qt Creator documentation. ** This file is part of the Qt Creator documentation.
@@ -33,11 +33,7 @@
\contentspage index.html \contentspage index.html
\page quick-components.html \page quick-components.html
\previouspage creator-using-qt-quick-designer.html \previouspage creator-using-qt-quick-designer.html
\if defined(qtdesignstudio)
\nextpage qtquick-navigator.html
\else
\nextpage quick-buttons.html \nextpage quick-buttons.html
\endif
\title Creating Components \title Creating Components
@@ -466,15 +462,17 @@
Some ready-made controls, such as a gauge, dial, status indicator, and Some ready-made controls, such as a gauge, dial, status indicator, and
tumbler, are provided by the \l {Qt Quick Extras} module. tumbler, are provided by the \l {Qt Quick Extras} module.
\if defined(qtcreator)
\section1 Creating Components in Design Mode \section1 Creating Components in Design Mode
\list 1 \list 1
\li Select \uicontrol File > \uicontrol {New File or Project} > \li Select \uicontrol File > \uicontrol {New File or Project} >
\uicontrol {Files and Classes} > \uicontrol Qt > \if defined(qtcreator)
\uicontrol {QML File (Qt Quick 2)} > \uicontrol Choose to create a new .qml \uicontrol Qt > \uicontrol {QML File (Qt Quick 2)} >
file. \else
\uicontrol {Qt Quick Files} > \uicontrol {Qt Quick File} >
\endif
\uicontrol Choose to create a new .qml file.
\note Components are listed in the \uicontrol {QML Components} section of \note Components are listed in the \uicontrol {QML Components} section of
the \uicontrol Library only if the filename begins with a capital the \uicontrol Library only if the filename begins with a capital
@@ -501,7 +499,6 @@
\li \l{Creating Scalable Buttons and Borders} \li \l{Creating Scalable Buttons and Borders}
\endlist \endlist
\endif
\section1 Moving Within Components \section1 Moving Within Components

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2018 The Qt Company Ltd. ** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the Qt Creator documentation. ** This file is part of the Qt Creator documentation.
@@ -26,11 +26,7 @@
/*! /*!
\contentspage {Qt Creator Manual} \contentspage {Qt Creator Manual}
\page qtquick-navigator.html \page qtquick-navigator.html
\if defined(qtdesignstudio)
\previouspage quick-components.html
\else
\previouspage quick-scalable-image.html \previouspage quick-scalable-image.html
\endif
\nextpage qtquick-properties.html \nextpage qtquick-properties.html
\title Managing Item Hierarchy \title Managing Item Hierarchy

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2018 The Qt Company Ltd. ** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the Qt Creator documentation. ** This file is part of the Qt Creator documentation.
@@ -53,8 +53,6 @@
\list \list
\li JavaScript blocks \li JavaScript blocks
\li Function definitions
\li Function calls (except \c qsTr)
\li Other bindings than pure expressions \li Other bindings than pure expressions
\li Signal handlers \li Signal handlers
\li States in other items than the root item \li States in other items than the root item
@@ -74,6 +72,98 @@
\li Transition \li Transition
\endlist \endlist
\section1 Supported Methods
\QC supports most JavaScript functions that are supported by the QML
engine, as well as a subset of Qt QML methods.
This section lists the functions that you can use in \e .ui.qml files.
\section2 JavaScript Functions
As a rule of thumb, \e {pure functions} are supported. They only depend on
and modify states of parameters that are within their scope, and therefore
always return the same results when given the same parameters. This makes
it possible to convert and reformat property bindings without breaking the
\e .ui.qml files.
The following JavaScript functions are supported:
\list
\li \c charAt()
\li \c charCodeAt()
\li \c concat()
\li \c endsWith()
\li \c includes()
\li \c indexOf()
\li \c isFinite()
\li \c isNaN()
\li \c lastIndexOf()
\li \c substring()
\li \c toExponential()
\li \c toFixed()
\li \c toLocaleLowerCase()
\li \c toLocaleString
\li \c toLocaleUpperCase()
\li \c toLowerCase()
\li \c toPrecision()
\li \c toString()
\li \c toUpperCase()
\li \c valueOf()
\endlist
In addition, all functions of the \c Math and \c Date objects are supported.
For more information, see
\l{https://doc.qt.io/qt-5/qtqml-javascript-functionlist.html}
{List of JavaScript Objects and Functions}.
\section2 Qt QML Methods
\QC supports color methods, helper methods for creating objects of
specific data types, and translation methods.
The following color methods are supported:
\list
\li \l{Qt::darker()}{Qt.darker()}
\li \l{Qt::hsla()}{Qt.hsla()}
\li \l{Qt::hsva()}{Qt.hsva()}
\li \l{Qt::lighter()}{Qt.lighter()}
\li \l{Qt::rgba()}{Qt.rgba()}
\li \l{Qt::tint()}{Qt.tint()}
\endlist
The following helper methods are supported:
\list
\li \l{Qt::formatDate()}{Qt.formatDate()}
\li \l{Qt::formatDateTime()}{Qt.formatDateTime()}
\li \l{Qt::formatTime()}{Qt.formatTime()}
\li \l{Qt::matrix4x4()}{Qt.matrix4x4()}
\li \l{Qt::point()}{Qt.point()}
\li \l{Qt::quaternion()}{Qt.quaternion()}
\li \l{Qt::rect()}{Qt.rect()}
\li \l{Qt::size()}{Qt.size()}
\li \l{Qt::vector2d()}{Qt.vector2d()}
\li \l{Qt::vector3d()}{Qt.vector3d()}
\li \l{Qt::vector4d()}{Qt.vector4d()}
\endlist
The following translation methods are supported:
\list
\li \l{Qt::}{qsTr()}
\li \l{Qt::}{qsTranslate()}
\li \l{Qt::}{qsTranslateNoOp()}
\li \l{Qt::}{qsTrId()}
\li \l{Qt::}{qsTrIdNoOp()}
\li \l{Qt::}{qsTrNoOp()}
\endlist
For more information about using the methods, see
\l{https://doc.qt.io/qt-5/qml-qtqml-qt.html}{Qt QML Methods}.
\section1 Using Qt Quick UI Forms \section1 Using Qt Quick UI Forms
You can edit the forms in the \uicontrol {Form Editor} and You can edit the forms in the \uicontrol {Form Editor} and

View File

@@ -507,3 +507,7 @@ class Dumper(DumperBase):
def putCallItem(self, name, rettype, value, func, *args): def putCallItem(self, name, rettype, value, func, *args):
return return
def symbolAddress(self, symbolName):
res = self.nativeParseAndEvaluate(symbolName)
return None if res is None else res.address()

View File

@@ -858,16 +858,12 @@ class Dumper(DumperBase):
pass pass
self.ignoreStops = 0 self.ignoreStops = 0
self.silentStops = 0
if platform.system() == 'Linux': if platform.system() == 'Linux':
if self.startMode_ == AttachCore: if self.startMode_ == AttachCore:
pass pass
else: else:
if self.useTerminal_: if self.useTerminal_:
self.ignoreStops = 2 self.ignoreStops = 2
else:
self.silentStops = 1
else: else:
if self.useTerminal_: if self.useTerminal_:
self.ignoreStops = 1 self.ignoreStops = 1
@@ -878,10 +874,8 @@ class Dumper(DumperBase):
if self.sysRoot_: if self.sysRoot_:
self.debugger.SetCurrentPlatformSDKRoot(self.sysRoot_) self.debugger.SetCurrentPlatformSDKRoot(self.sysRoot_)
if os.path.isfile(self.executable_): exefile = None if self.attachPid_ > 0 else self.executable_
self.target = self.debugger.CreateTarget(self.executable_, None, None, True, error) self.target = self.debugger.CreateTarget(exefile, None, None, True, error)
else:
self.target = self.debugger.CreateTarget(None, None, None, True, error)
if self.nativeMixed: if self.nativeMixed:
self.interpreterEventBreakpoint = \ self.interpreterEventBreakpoint = \
@@ -1345,8 +1339,6 @@ class Dumper(DumperBase):
elif self.ignoreStops > 0: elif self.ignoreStops > 0:
self.ignoreStops -= 1 self.ignoreStops -= 1
self.process.Continue() self.process.Continue()
elif self.silentStops > 0:
self.silentStops -= 1
else: else:
self.reportState("stopped") self.reportState("stopped")
else: else:

View File

@@ -44,6 +44,7 @@
#include <QQmlParserStatus> #include <QQmlParserStatus>
#include <QTextDocument> #include <QTextDocument>
#include <QLibraryInfo> #include <QLibraryInfo>
#include <QJSValue>
static bool isSimpleExpression(const QString &expression) static bool isSimpleExpression(const QString &expression)
{ {
@@ -264,11 +265,17 @@ static bool isList(const QQmlProperty &property)
return property.propertyTypeCategory() == QQmlProperty::List; return property.propertyTypeCategory() == QQmlProperty::List;
} }
static bool isQJSValue(const QQmlProperty &property)
{
return !strcmp(property.propertyTypeName(), "QJSValue");
}
static bool isObject(const QQmlProperty &property) static bool isObject(const QQmlProperty &property)
{ {
return (property.propertyTypeCategory() == QQmlProperty::Object) || /* QVariant and QJSValue can also store QObjects. Lets trust our model. */
//QVariant can also store QObjects. Lets trust our model. return (property.propertyTypeCategory() == QQmlProperty::Object
(QLatin1String(property.propertyTypeName()) == QLatin1String("QVariant")); || !strcmp(property.propertyTypeName(), "QVariant")
|| isQJSValue(property));
} }
static QVariant objectToVariant(QObject *object) static QVariant objectToVariant(QObject *object)
@@ -337,6 +344,9 @@ void ObjectNodeInstance::addToNewProperty(QObject *object, QObject *newParent, c
list.append(object); list.append(object);
} else if (isObject(property)) { } else if (isObject(property)) {
if (isQJSValue(property)) /* In this case we have to explcitly generate and convert a QJSValue */
property.write(QVariant::fromValue(engine()->newQObject(object)));
else
property.write(objectToVariant(object)); property.write(objectToVariant(object));
if (QQuickItem *item = qobject_cast<QQuickItem *>(object)) if (QQuickItem *item = qobject_cast<QQuickItem *>(object))

View File

@@ -248,10 +248,10 @@ void ProjectExplorer::ProjectExplorerPlugin::testJsonWizardsComboBox()
QCOMPARE(qPrintable(disabledComboBox->currentText()), "fgh"); QCOMPARE(qPrintable(disabledComboBox->currentText()), "fgh");
} }
static const char *iconInsideResource(const QString &relativePathToIcon) static QString iconInsideResource(const QString &relativePathToIcon)
{ {
const QDir resourcePath(Core::ICore::resourcePath()); const QDir resourcePath(Core::ICore::resourcePath());
return resourcePath.filePath(relativePathToIcon).toLocal8Bit().data(); return resourcePath.filePath(relativePathToIcon);
} }
void ProjectExplorer::ProjectExplorerPlugin::testJsonWizardsIconList() void ProjectExplorer::ProjectExplorerPlugin::testJsonWizardsIconList()

View File

@@ -914,15 +914,25 @@ void Project::setPreferredKitPredicate(const Kit::Predicate &predicate)
} // namespace ProjectExplorer } // namespace ProjectExplorer
#include <utils/hostosinfo.h>
#include <QTest> #include <QTest>
#include <QSignalSpy> #include <QSignalSpy>
namespace ProjectExplorer { namespace ProjectExplorer {
const Utils::FileName TEST_PROJECT_PATH = Utils::FileName::fromString("/tmp/foobar/baz.project"); static Utils::FileName constructTestPath(const char *basePath)
const Utils::FileName TEST_PROJECT_NONEXISTING_FILE = Utils::FileName::fromString("/tmp/foobar/nothing.cpp"); {
const Utils::FileName TEST_PROJECT_CPP_FILE = Utils::FileName::fromString("/tmp/foobar/main.cpp"); Utils::FileName drive;
const Utils::FileName TEST_PROJECT_GENERATED_FILE = Utils::FileName::fromString("/tmp/foobar/generated.foo"); if (Utils::HostOsInfo::isWindowsHost())
drive = Utils::FileName::fromString("C:");
return drive + QLatin1String(basePath);
}
const Utils::FileName TEST_PROJECT_PATH = constructTestPath("/tmp/foobar/baz.project");
const Utils::FileName TEST_PROJECT_NONEXISTING_FILE = constructTestPath("/tmp/foobar/nothing.cpp");
const Utils::FileName TEST_PROJECT_CPP_FILE = constructTestPath("/tmp/foobar/main.cpp");
const Utils::FileName TEST_PROJECT_GENERATED_FILE = constructTestPath("/tmp/foobar/generated.foo");
const QString TEST_PROJECT_MIMETYPE = "application/vnd.test.qmakeprofile"; const QString TEST_PROJECT_MIMETYPE = "application/vnd.test.qmakeprofile";
const QString TEST_PROJECT_DISPLAYNAME = "testProjectFoo"; const QString TEST_PROJECT_DISPLAYNAME = "testProjectFoo";
const char TEST_PROJECT_ID[] = "Test.Project.Id"; const char TEST_PROJECT_ID[] = "Test.Project.Id";

View File

@@ -208,6 +208,7 @@ private: //variables
bool m_instantQmlTextUpdate = false; bool m_instantQmlTextUpdate = false;
std::function<void(bool)> m_setWidgetStatusCallback; std::function<void(bool)> m_setWidgetStatusCallback;
bool m_hasIncompleteTypeInformation = false; bool m_hasIncompleteTypeInformation = false;
bool m_restoringAuxData = false;
mutable QHash<int, ModelNode> m_canonicalIntModelNode; mutable QHash<int, ModelNode> m_canonicalIntModelNode;
mutable QHash<ModelNode, int> m_canonicalModelNodeInt; mutable QHash<ModelNode, int> m_canonicalModelNodeInt;

View File

@@ -1519,7 +1519,7 @@ bool NodeMetaInfo::availableInVersion(int majorVersion, int minorVersion) const
bool NodeMetaInfo::isSubclassOf(const TypeName &type, int majorVersion, int minorVersion) const bool NodeMetaInfo::isSubclassOf(const TypeName &type, int majorVersion, int minorVersion) const
{ {
if (!isValid()) { if (!isValid()) {
qWarning() << "NodeMetaInfo is invalid"; qWarning() << "NodeMetaInfo is invalid" << type;
return false; return false;
} }

View File

@@ -591,8 +591,6 @@ void AbstractView::activateTimeline(const ModelNode &timeline)
if (currentTimeline().isValid()) if (currentTimeline().isValid())
currentTimeline().toogleRecording(false); currentTimeline().toogleRecording(false);
Internal::WriteLocker locker(m_model.data());
if (model()) if (model())
model()->d->notifyCurrentTimelineChanged(timeline); model()->d->notifyCurrentTimelineChanged(timeline);
} }
@@ -615,8 +613,6 @@ void AbstractView::deactivateTimelineRecording()
currentTimeline().resetGroupRecording(); currentTimeline().resetGroupRecording();
} }
Internal::WriteLocker locker(m_model.data());
if (model()) if (model())
model()->d->notifyCurrentTimelineChanged(ModelNode()); model()->d->notifyCurrentTimelineChanged(ModelNode());
} }

View File

@@ -392,6 +392,9 @@ void RewriterView::deactivateTextMofifierChangeSignals()
void RewriterView::auxiliaryDataChanged(const ModelNode &, const PropertyName &name, const QVariant &) void RewriterView::auxiliaryDataChanged(const ModelNode &, const PropertyName &name, const QVariant &)
{ {
if (m_restoringAuxData)
return;
if (name.endsWith("@NodeInstance")) if (name.endsWith("@NodeInstance"))
return; return;
@@ -1059,6 +1062,8 @@ void RewriterView::restoreAuxiliaryData()
{ {
QTC_ASSERT(m_textModifier, return); QTC_ASSERT(m_textModifier, return);
m_restoringAuxData = true;
setupCanonicalHashes(); setupCanonicalHashes();
const QString text = m_textModifier->text(); const QString text = m_textModifier->text();
@@ -1072,6 +1077,8 @@ void RewriterView::restoreAuxiliaryData()
QmlJS::SimpleReader reader; QmlJS::SimpleReader reader;
checkChildNodes(reader.readFromSource(auxSource), this); checkChildNodes(reader.readFromSource(auxSource), this);
} }
m_restoringAuxData = false;
} }
} //QmlDesigner } //QmlDesigner

View File

@@ -1733,6 +1733,11 @@ void ModelValidator::typeDiffers(bool /*isRootNode*/,
qDebug() << typeName << modelNode.majorVersion() << majorVersion; qDebug() << typeName << modelNode.majorVersion() << majorVersion;
} }
if (modelNode.minorVersion() != minorVersion) {
qDebug() << Q_FUNC_INFO << modelNode;
qDebug() << typeName << modelNode.minorVersion() << minorVersion;
}
QTC_ASSERT(modelNode.majorVersion() == majorVersion, return); QTC_ASSERT(modelNode.majorVersion() == majorVersion, return);
QTC_ASSERT(modelNode.minorVersion() == minorVersion, return); QTC_ASSERT(modelNode.minorVersion() == minorVersion, return);
QTC_ASSERT(0, return); QTC_ASSERT(0, return);

View File

@@ -601,6 +601,7 @@ void QtSupportPlugin::testQtProjectImporter_oneProject()
KitManager::deregisterKit(k); KitManager::deregisterKit(k);
// Delete kit templates: // Delete kit templates:
QVERIFY(kitTemplates.removeOne(defaultKit));
qDeleteAll(kitTemplates); qDeleteAll(kitTemplates);
} }

View File

@@ -101,7 +101,7 @@
<item row="1" column="4"> <item row="1" column="4">
<widget class="QSpinBox" name="automaticProposalTimeoutSpinBox"> <widget class="QSpinBox" name="automaticProposalTimeoutSpinBox">
<property name="maximum"> <property name="maximum">
<number>500</number> <number>2000</number>
</property> </property>
<property name="singleStep"> <property name="singleStep">
<number>50</number> <number>50</number>

View File

@@ -116,8 +116,6 @@ bool WinRtPackageDeploymentStep::init()
void WinRtPackageDeploymentStep::run(QFutureInterface<bool> &fi) void WinRtPackageDeploymentStep::run(QFutureInterface<bool> &fi)
{ {
AbstractProcessStep::run(fi);
const QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target()->kit()); const QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target()->kit());
if (!qt) if (!qt)
return; return;
@@ -144,6 +142,8 @@ void WinRtPackageDeploymentStep::run(QFutureInterface<bool> &fi)
} }
} }
} }
AbstractProcessStep::run(fi);
} }
bool WinRtPackageDeploymentStep::processSucceeded(int exitCode, QProcess::ExitStatus status) bool WinRtPackageDeploymentStep::processSucceeded(int exitCode, QProcess::ExitStatus status)

View File

@@ -1185,7 +1185,7 @@ bool QMakeEvaluator::loadSpecInternal()
# ifdef Q_OS_UNIX # ifdef Q_OS_UNIX
if (m_qmakespec.endsWith(QLatin1String("/default-host")) if (m_qmakespec.endsWith(QLatin1String("/default-host"))
|| m_qmakespec.endsWith(QLatin1String("/default"))) { || m_qmakespec.endsWith(QLatin1String("/default"))) {
QString rspec = QFileInfo(m_qmakespec).readLink(); QString rspec = QFileInfo(m_qmakespec).symLinkTarget();
if (!rspec.isEmpty()) if (!rspec.isEmpty())
m_qmakespec = QDir::cleanPath(QDir(m_qmakespec).absoluteFilePath(rspec)); m_qmakespec = QDir::cleanPath(QDir(m_qmakespec).absoluteFilePath(rspec));
} }

View File

@@ -1699,6 +1699,8 @@ void tst_Dumpers::dumper()
return static_cast<WatchItem *>(item)->internalName() == iname; return static_cast<WatchItem *>(item)->internalName() == iname;
})); }));
if (!item) { if (!item) {
if (check.optionallyPresent)
return true;
qDebug() << "NOT SEEN: " << check.iname; qDebug() << "NOT SEEN: " << check.iname;
return false; return false;
} }

View File

@@ -38,11 +38,13 @@ lastToken = [None, None]
stopTokens = ('OP', 'NAME', 'NUMBER', 'ENDMARKER') stopTokens = ('OP', 'NAME', 'NUMBER', 'ENDMARKER')
def parseCommandLine(): def parseCommandLine():
global directory, onlyRemovable, sharedFolders global directory, onlyRemovable, sharedFolders, deleteObjects
parser = OptionParser("\n%prog [OPTIONS] [DIRECTORY]") parser = OptionParser("\n%prog [OPTIONS] [DIRECTORY]")
parser.add_option("-o", "--only-removable", dest="onlyRemovable", parser.add_option("-o", "--only-removable", dest="onlyRemovable",
action="store_true", default=False, action="store_true", default=False,
help="list removable objects only") help="list removable objects only")
parser.add_option("-d", "--delete", dest="delete",
action="store_true", default=False)
parser.add_option("-s", dest="sharedFolders", parser.add_option("-s", dest="sharedFolders",
action="store", type="string", default="", action="store", type="string", default="",
help="comma-separated list of shared folders") help="comma-separated list of shared folders")
@@ -56,6 +58,7 @@ def parseCommandLine():
parser.print_help() parser.print_help()
sys.exit(1) sys.exit(1)
onlyRemovable = options.onlyRemovable onlyRemovable = options.onlyRemovable
deleteObjects = options.delete
sharedFolders = map(os.path.abspath, options.sharedFolders.split(',')) sharedFolders = map(os.path.abspath, options.sharedFolders.split(','))
def collectObjects(): def collectObjects():
@@ -153,15 +156,53 @@ def printResult():
print print
return None return None
def main(): def deleteRemovable():
global useCounts, objMap global useCounts, objMap
deletable = filter(lambda x: useCounts[x] == 0, useCounts)
if len(deletable) == 0:
print("Nothing to delete - leaving objects.map untouched")
return
data = ''
with open(objMap, "r") as objMapFile:
data = objMapFile.read()
objMapBackup = objMap + '~'
if os.path.exists(objMapBackup):
os.unlink(objMapBackup)
os.rename(objMap, objMapBackup)
count = 0
with open(objMap, "w") as objMapFile:
for line in data.splitlines():
try:
obj = line.split('\t')[0]
if obj in deletable:
count += 1
continue
objMapFile.write(line + '\n')
except:
print("Something's wrong in line '%s'" % line)
print("Deleted %d items, old objects.map has been moved to objects.map~" % count)
return count > 0
def main():
global useCounts, objMap, deleteObjects
objMap = checkDirectory(directory) objMap = checkDirectory(directory)
useCounts = dict.fromkeys(collectObjects(), 0) useCounts = dict.fromkeys(collectObjects(), 0)
findUsages() findUsages()
atLeastOneRemovable = printResult() atLeastOneRemovable = printResult()
deletedAtLeastOne = deleteObjects and deleteRemovable()
mssg = None
if atLeastOneRemovable: if atLeastOneRemovable:
print "\nAfter removing the listed objects you should re-run this tool" mssg = "\nAfter removing the listed objects you should re-run this tool\n"
print "to find objects that might have been used only by these objects.\n" if deletedAtLeastOne:
mssg = "\nYou should re-run this tool\n"
if mssg:
print(mssg + "to find objects that might have been referenced only by removed objects.\n")
return 0 return 0
if __name__ == '__main__': if __name__ == '__main__':