forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/4.14'
Change-Id: Ib343adc6b761d15410d357137e4fc38040ce8d48
This commit is contained in:
@@ -46,7 +46,7 @@
|
|||||||
indistinguishable from the same application running on the desktop.
|
indistinguishable from the same application running on the desktop.
|
||||||
|
|
||||||
\if defined(qtdesignstudio)
|
\if defined(qtdesignstudio)
|
||||||
To create a resource file out of your project, select \uicontrol Tools >
|
To create a resource file out of your project, select \uicontrol Build >
|
||||||
\uicontrol {Generate Resource File} in \QC. Then upload the package into
|
\uicontrol {Generate Resource File} in \QC. Then upload the package into
|
||||||
\QDV.
|
\QDV.
|
||||||
\else
|
\else
|
||||||
|
@@ -358,7 +358,9 @@ namespace ADS
|
|||||||
saveStartupWorkspace();
|
saveStartupWorkspace();
|
||||||
|
|
||||||
for (auto floatingWidget : d->m_floatingWidgets) {
|
for (auto floatingWidget : d->m_floatingWidgets) {
|
||||||
if (floatingWidget)
|
/* There have been crashes with partially destructed widgets in
|
||||||
|
m_floatingWidgets. Those do not have a parent. */
|
||||||
|
if (floatingWidget && floatingWidget->parent() == this)
|
||||||
delete floatingWidget.data();
|
delete floatingWidget.data();
|
||||||
}
|
}
|
||||||
d->m_floatingWidgets.clear();
|
d->m_floatingWidgets.clear();
|
||||||
|
@@ -1779,8 +1779,11 @@ void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) c
|
|||||||
void DebuggerEngine::notifyDebuggerProcessFinished(int exitCode,
|
void DebuggerEngine::notifyDebuggerProcessFinished(int exitCode,
|
||||||
QProcess::ExitStatus exitStatus, const QString &backendName)
|
QProcess::ExitStatus exitStatus, const QString &backendName)
|
||||||
{
|
{
|
||||||
showMessage(QString("%1 PROCESS FINISHED, status %2, exit code %3")
|
showMessage(QString("%1 PROCESS FINISHED, status %2, exit code %3 (0x%4)")
|
||||||
.arg(backendName).arg(exitStatus).arg(exitCode));
|
.arg(backendName)
|
||||||
|
.arg(exitStatus)
|
||||||
|
.arg(exitCode)
|
||||||
|
.arg(QString::number(exitCode, 16)));
|
||||||
|
|
||||||
switch (state()) {
|
switch (state()) {
|
||||||
case DebuggerFinished:
|
case DebuggerFinished:
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#include "assetexporter.h"
|
#include "assetexporter.h"
|
||||||
|
#include "assetexportpluginconstants.h"
|
||||||
#include "componentexporter.h"
|
#include "componentexporter.h"
|
||||||
#include "exportnotification.h"
|
#include "exportnotification.h"
|
||||||
|
|
||||||
@@ -154,21 +155,47 @@ bool AssetExporter::isBusy() const
|
|||||||
m_currentState == AssetExporter::ParsingState::WritingJson;
|
m_currentState == AssetExporter::ParsingState::WritingJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::FilePath AssetExporter::exportAsset(const QmlObjectNode &node, const Component *component,
|
const QPixmap &AssetExporter::generateAsset(const ModelNode &node)
|
||||||
const QString &uuid)
|
|
||||||
{
|
{
|
||||||
|
static QPixmap nullPixmap;
|
||||||
if (m_cancelled)
|
if (m_cancelled)
|
||||||
|
return nullPixmap;
|
||||||
|
|
||||||
|
const QString uuid = node.auxiliaryData(Constants::UuidAuxTag).toString();
|
||||||
|
QTC_ASSERT(!uuid.isEmpty(), return nullPixmap);
|
||||||
|
|
||||||
|
if (!m_assets.contains(uuid)) {
|
||||||
|
// Generate asset.
|
||||||
|
QmlObjectNode objectNode(node);
|
||||||
|
QPixmap asset = objectNode.toQmlItemNode().instanceRenderPixmap();
|
||||||
|
m_assets[uuid] = asset;
|
||||||
|
}
|
||||||
|
return m_assets[uuid];
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::FilePath AssetExporter::assetPath(const ModelNode &node, const Component *component,
|
||||||
|
const QString &suffix) const
|
||||||
|
{
|
||||||
|
const QString uuid = node.auxiliaryData(Constants::UuidAuxTag).toString();
|
||||||
|
if (!component || uuid.isEmpty())
|
||||||
return {};
|
return {};
|
||||||
const Utils::FilePath assetExportDir = m_perComponentExport ? componentExportDir(component) :
|
|
||||||
m_exportPath;
|
const Utils::FilePath assetExportDir =
|
||||||
const QString fileName = uuid + ".png";
|
m_perComponentExport ? componentExportDir(component) : m_exportPath;
|
||||||
const Utils::FilePath assetPath = assetExportDir.pathAppended("assets").pathAppended(fileName);
|
const Utils::FilePath assetPath = assetExportDir.pathAppended("assets")
|
||||||
if (m_assetDumper)
|
.pathAppended(uuid + suffix + ".png");
|
||||||
m_assetDumper->dumpAsset(node.toQmlItemNode().instanceRenderPixmap(), assetPath);
|
|
||||||
|
|
||||||
return assetPath;
|
return assetPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AssetExporter::exportAsset(const QPixmap &asset, const Utils::FilePath &path)
|
||||||
|
{
|
||||||
|
if (m_cancelled || !m_assetDumper)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_assetDumper->dumpAsset(asset, path);
|
||||||
|
}
|
||||||
|
|
||||||
void AssetExporter::exportComponent(const ModelNode &rootNode)
|
void AssetExporter::exportComponent(const ModelNode &rootNode)
|
||||||
{
|
{
|
||||||
qCDebug(loggerInfo) << "Exporting component" << rootNode.id();
|
qCDebug(loggerInfo) << "Exporting component" << rootNode.id();
|
||||||
|
@@ -71,8 +71,10 @@ public:
|
|||||||
void cancel();
|
void cancel();
|
||||||
bool isBusy() const;
|
bool isBusy() const;
|
||||||
|
|
||||||
Utils::FilePath exportAsset(const QmlObjectNode& node, const Component *component,
|
const QPixmap &generateAsset(const ModelNode &node);
|
||||||
const QString &uuid);
|
Utils::FilePath assetPath(const ModelNode &node, const Component *component,
|
||||||
|
const QString &suffix = {}) const;
|
||||||
|
void exportAsset(const QPixmap &asset, const Utils::FilePath &path);
|
||||||
QByteArray generateUuid(const ModelNode &node);
|
QByteArray generateUuid(const ModelNode &node);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
@@ -108,6 +110,7 @@ private:
|
|||||||
bool m_perComponentExport = false;
|
bool m_perComponentExport = false;
|
||||||
std::vector<std::unique_ptr<Component>> m_components;
|
std::vector<std::unique_ptr<Component>> m_components;
|
||||||
QSet<QByteArray> m_usedHashes;
|
QSet<QByteArray> m_usedHashes;
|
||||||
|
QHash<QString, QPixmap> m_assets;
|
||||||
std::unique_ptr<AssetDumper> m_assetDumper;
|
std::unique_ptr<AssetDumper> m_assetDumper;
|
||||||
bool m_cancelled = false;
|
bool m_cancelled = false;
|
||||||
};
|
};
|
||||||
|
@@ -63,6 +63,7 @@ const char ImportsTag[] = "extraImports";
|
|||||||
const char UuidTag[] = "uuid";
|
const char UuidTag[] = "uuid";
|
||||||
const char ClipTag[] = "clip";
|
const char ClipTag[] = "clip";
|
||||||
const char AssetDataTag[] = "assetData";
|
const char AssetDataTag[] = "assetData";
|
||||||
|
const char ReferenceAssetTag[] = "referenceAsset";
|
||||||
const char AssetPathTag[] = "assetPath";
|
const char AssetPathTag[] = "assetPath";
|
||||||
const char AssetBoundsTag[] = "assetBounds";
|
const char AssetBoundsTag[] = "assetBounds";
|
||||||
const char OpacityTag[] = "opacity";
|
const char OpacityTag[] = "opacity";
|
||||||
|
@@ -31,6 +31,7 @@
|
|||||||
#include "model.h"
|
#include "model.h"
|
||||||
#include "nodeabstractproperty.h"
|
#include "nodeabstractproperty.h"
|
||||||
#include "nodemetainfo.h"
|
#include "nodemetainfo.h"
|
||||||
|
#include "qmlitemnode.h"
|
||||||
#include "rewriterview.h"
|
#include "rewriterview.h"
|
||||||
|
|
||||||
#include "utils/qtcassert.h"
|
#include "utils/qtcassert.h"
|
||||||
@@ -38,6 +39,7 @@
|
|||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
Q_LOGGING_CATEGORY(loggerInfo, "qtc.designer.assetExportPlugin.modelExporter", QtInfoMsg)
|
Q_LOGGING_CATEGORY(loggerInfo, "qtc.designer.assetExportPlugin.modelExporter", QtInfoMsg)
|
||||||
@@ -86,6 +88,7 @@ void Component::exportComponent()
|
|||||||
// Change the export type to component
|
// Change the export type to component
|
||||||
QJsonObject metadata = m_json.value(MetadataTag).toObject();
|
QJsonObject metadata = m_json.value(MetadataTag).toObject();
|
||||||
metadata.insert(ExportTypeTag, ExportTypeComponent);
|
metadata.insert(ExportTypeTag, ExportTypeComponent);
|
||||||
|
addReferenceAsset(metadata);
|
||||||
m_json.insert(MetadataTag, metadata);
|
m_json.insert(MetadataTag, metadata);
|
||||||
addImports();
|
addImports();
|
||||||
}
|
}
|
||||||
@@ -152,6 +155,37 @@ QJsonObject Component::nodeToJson(const ModelNode &node)
|
|||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Component::addReferenceAsset(QJsonObject &metadataObject) const
|
||||||
|
{
|
||||||
|
QPixmap refAsset = m_exporter.generateAsset(m_rootNode);
|
||||||
|
stichChildrendAssets(m_rootNode, refAsset);
|
||||||
|
Utils::FilePath refAssetPath = m_exporter.assetPath(m_rootNode, this, "_ref");
|
||||||
|
m_exporter.exportAsset(refAsset, refAssetPath);
|
||||||
|
QJsonObject assetData;
|
||||||
|
if (metadataObject.contains(AssetDataTag))
|
||||||
|
assetData = metadataObject[AssetDataTag].toObject();
|
||||||
|
assetData.insert(ReferenceAssetTag, refAssetPath.toString());
|
||||||
|
metadataObject.insert(AssetDataTag, assetData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Component::stichChildrendAssets(const ModelNode &node, QPixmap &parentPixmap) const
|
||||||
|
{
|
||||||
|
if (!node.hasAnySubModelNodes())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QPainter painter(&parentPixmap);
|
||||||
|
for (const ModelNode &child : node.directSubModelNodes()) {
|
||||||
|
QPixmap childPixmap = m_exporter.generateAsset(child);
|
||||||
|
if (childPixmap.isNull())
|
||||||
|
continue;
|
||||||
|
stichChildrendAssets(child, childPixmap);
|
||||||
|
QTransform cTransform = QmlObjectNode(child).toQmlItemNode().instanceTransform();
|
||||||
|
painter.setTransform(cTransform);
|
||||||
|
painter.drawPixmap(QPoint(0, 0), childPixmap);
|
||||||
|
}
|
||||||
|
painter.end();
|
||||||
|
}
|
||||||
|
|
||||||
void Component::addImports()
|
void Component::addImports()
|
||||||
{
|
{
|
||||||
QJsonArray importsArray;
|
QJsonArray importsArray;
|
||||||
|
@@ -88,6 +88,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
NodeDumper* createNodeDumper(const ModelNode &node) const;
|
NodeDumper* createNodeDumper(const ModelNode &node) const;
|
||||||
QJsonObject nodeToJson(const ModelNode &node);
|
QJsonObject nodeToJson(const ModelNode &node);
|
||||||
|
void addReferenceAsset(QJsonObject &metadataObject) const;
|
||||||
|
void stichChildrendAssets(const ModelNode &node, QPixmap &parentPixmap) const;
|
||||||
void addImports();
|
void addImports();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -54,10 +54,12 @@ QJsonObject AssetNodeDumper::json(Component &component) const
|
|||||||
{
|
{
|
||||||
QJsonObject jsonObject = ItemNodeDumper::json(component);
|
QJsonObject jsonObject = ItemNodeDumper::json(component);
|
||||||
|
|
||||||
Utils::FilePath assetPath = component.exporter().exportAsset(objectNode(), &component, uuid());
|
AssetExporter &exporter = component.exporter();
|
||||||
|
const Utils::FilePath assetPath = exporter.assetPath(m_node, &component);
|
||||||
|
exporter.exportAsset(exporter.generateAsset(m_node), assetPath);
|
||||||
|
|
||||||
QJsonObject assetData;
|
QJsonObject assetData;
|
||||||
assetData.insert(AssetPathTag, assetPath.toString());
|
assetData.insert(AssetPathTag, assetPath.toString());
|
||||||
|
|
||||||
QJsonObject metadata = jsonObject.value(MetadataTag).toObject();
|
QJsonObject metadata = jsonObject.value(MetadataTag).toObject();
|
||||||
metadata.insert(AssetDataTag, assetData);
|
metadata.insert(AssetDataTag, assetData);
|
||||||
jsonObject.insert(MetadataTag, metadata);
|
jsonObject.insert(MetadataTag, metadata);
|
||||||
|
@@ -56,7 +56,10 @@ const int flowBlockSize = 200;
|
|||||||
const int blockRadius = 18;
|
const int blockRadius = 18;
|
||||||
const int blockAdjust = 40;
|
const int blockAdjust = 40;
|
||||||
const int startItemOffset = 96;
|
const int startItemOffset = 96;
|
||||||
const int labelFontSize = 16;
|
|
||||||
|
const qreal fontSize = 10; // points
|
||||||
|
const qreal zoomLevelLabel = 0.5; // Everything lower than that will hide all labels
|
||||||
|
const qreal defaultDpi = 96.0;
|
||||||
|
|
||||||
void drawIcon(QPainter *painter,
|
void drawIcon(QPainter *painter,
|
||||||
int x,
|
int x,
|
||||||
@@ -882,7 +885,6 @@ public:
|
|||||||
, bezier(50)
|
, bezier(50)
|
||||||
, type(ConnectionType::Default)
|
, type(ConnectionType::Default)
|
||||||
, label()
|
, label()
|
||||||
, fontSize(labelFontSize / scaleFactor)
|
|
||||||
, labelOffset(14 / scaleFactor)
|
, labelOffset(14 / scaleFactor)
|
||||||
, labelPosition(50.0)
|
, labelPosition(50.0)
|
||||||
, labelFlags(Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextDontClip)
|
, labelFlags(Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextDontClip)
|
||||||
@@ -944,8 +946,6 @@ public:
|
|||||||
label = node.modelNode().bindingProperty("condition").expression();
|
label = node.modelNode().bindingProperty("condition").expression();
|
||||||
if (node.modelNode().hasVariantProperty("question"))
|
if (node.modelNode().hasVariantProperty("question"))
|
||||||
label = node.modelNode().variantProperty("question").value().toString();
|
label = node.modelNode().variantProperty("question").value().toString();
|
||||||
// font size
|
|
||||||
|
|
||||||
// label offset
|
// label offset
|
||||||
|
|
||||||
// label position
|
// label position
|
||||||
@@ -960,7 +960,6 @@ public:
|
|||||||
|
|
||||||
if (node.modelNode().hasVariantProperty(eventsName))
|
if (node.modelNode().hasVariantProperty(eventsName))
|
||||||
events = node.modelNode().variantProperty(eventsName).value().toString();
|
events = node.modelNode().variantProperty(eventsName).value().toString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal width;
|
qreal width;
|
||||||
@@ -980,7 +979,6 @@ public:
|
|||||||
int bezier;
|
int bezier;
|
||||||
ConnectionType type;
|
ConnectionType type;
|
||||||
QString label;
|
QString label;
|
||||||
int fontSize;
|
|
||||||
qreal labelOffset;
|
qreal labelOffset;
|
||||||
qreal labelPosition;
|
qreal labelPosition;
|
||||||
int labelFlags;
|
int labelFlags;
|
||||||
@@ -1284,7 +1282,7 @@ public:
|
|||||||
const bool boolExitRight = fromRect.right() < toRect.center().x();
|
const bool boolExitRight = fromRect.right() < toRect.center().x();
|
||||||
const bool boolExitBottom = fromRect.bottom() < toRect.center().y();
|
const bool boolExitBottom = fromRect.bottom() < toRect.center().y();
|
||||||
|
|
||||||
const int padding = 4 * config.adjustedWidth;
|
const qreal padding = 8;
|
||||||
|
|
||||||
if (horizontalFirst) {
|
if (horizontalFirst) {
|
||||||
const qreal startX = boolExitRight ? fromRect.right() + padding : fromRect.x() - padding;
|
const qreal startX = boolExitRight ? fromRect.right() + padding : fromRect.x() - padding;
|
||||||
@@ -1404,11 +1402,14 @@ void FormEditorTransitionItem::updateGeometry()
|
|||||||
QPixmap pixmap(640, 480);
|
QPixmap pixmap(640, 480);
|
||||||
QPainter localPainter(&pixmap);
|
QPainter localPainter(&pixmap);
|
||||||
QFont font = localPainter.font();
|
QFont font = localPainter.font();
|
||||||
font.setPixelSize(config.fontSize);
|
font.setPointSizeF(getFontSize(&localPainter) / getScaleFactor());
|
||||||
localPainter.setFont(font);
|
localPainter.setFont(font);
|
||||||
|
|
||||||
for (const auto &from : resolved.from) {
|
const auto fromNodes = resolved.from;
|
||||||
for (const auto &to : resolved.to) {
|
const auto toNodes = resolved.to;
|
||||||
|
|
||||||
|
for (const auto &from : fromNodes) {
|
||||||
|
for (const auto &to : toNodes) {
|
||||||
Connection connection(resolved, pos(), from, to, config);
|
Connection connection(resolved, pos(), from, to, config);
|
||||||
|
|
||||||
// Just add the configured transition width to the bounding box to make sure the BB is not cutting
|
// Just add the configured transition width to the bounding box to make sure the BB is not cutting
|
||||||
@@ -1434,31 +1435,13 @@ QPointF FormEditorTransitionItem::instancePosition() const
|
|||||||
|
|
||||||
void FormEditorTransitionItem::drawLabels(QPainter *painter, const Connection &connection)
|
void FormEditorTransitionItem::drawLabels(QPainter *painter, const Connection &connection)
|
||||||
{
|
{
|
||||||
// draw label with event ids
|
drawSingleEventIdLabel(painter, connection);
|
||||||
if (connection.config.isSelected && !connection.config.events.isEmpty())
|
drawEventIdsLabel(painter, connection);
|
||||||
{
|
drawGeneralLabel(painter, connection);
|
||||||
qreal offset = connection.config.labelOffset;
|
}
|
||||||
QStringList events = connection.config.events.split(',');
|
|
||||||
int fontSize = connection.config.fontSize;
|
void FormEditorTransitionItem::drawGeneralLabel(QPainter *painter, const Connection &connection)
|
||||||
QString outputText;
|
{
|
||||||
qreal minWidth = offset * 12.0;
|
|
||||||
qreal letterWidth = fontSize * 0.6; // assumption on max letter width
|
|
||||||
int eventCount = events.size();
|
|
||||||
std::for_each(events.begin(), events.end(), [&](auto id) {
|
|
||||||
outputText.append(id.trimmed());
|
|
||||||
outputText.append('\n');
|
|
||||||
if (minWidth < id.size() * letterWidth) minWidth = id.size() * letterWidth;
|
|
||||||
});
|
|
||||||
const QPointF pos = connection.path.pointAtPercent(0.0);
|
|
||||||
painter->save();
|
|
||||||
painter->setBrush(QColor(70, 70, 70, 200));
|
|
||||||
painter->setPen(Qt::lightGray);
|
|
||||||
painter->drawRoundedRect(pos.x(), pos.y() + offset, minWidth, 1.5 * fontSize * eventCount + offset * 4.0, offset / 2.0, offset / 2.0);
|
|
||||||
painter->drawText(pos.x(), pos.y() + 2.0 * offset, minWidth, offset * 2.0, Qt::AlignHCenter, QObject::tr("Connected Events"));
|
|
||||||
painter->drawLine(pos.x() + offset, pos.y() + 4.0 * offset, pos.x() + minWidth - offset, pos.y() + offset * 4.0);
|
|
||||||
painter->drawText(pos.x() + offset, pos.y() + 4.0 * offset, minWidth - offset, 1.5 * fontSize * eventCount, Qt::AlignLeft, outputText);
|
|
||||||
painter->restore();
|
|
||||||
}
|
|
||||||
if (connection.config.label.isEmpty())
|
if (connection.config.label.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1481,11 +1464,166 @@ void FormEditorTransitionItem::drawLabels(QPainter *painter, const Connection &c
|
|||||||
painter->restore();
|
painter->restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FormEditorTransitionItem::drawSingleEventIdLabel(QPainter *painter, const Connection &connection)
|
||||||
|
{
|
||||||
|
if (connection.config.events.isEmpty() || connection.config.events.split(",").size() != 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QPointF position;
|
||||||
|
qreal angle;
|
||||||
|
|
||||||
|
const qreal hMargin = 10.0 / getScaleFactor();
|
||||||
|
QFontMetrics metric(painter->font());
|
||||||
|
QRectF textRect = metric.boundingRect(connection.config.events);
|
||||||
|
textRect.adjust(-hMargin, 0.0, hMargin, 0.0);
|
||||||
|
const qreal halfHeight = textRect.height() / 2.0;
|
||||||
|
|
||||||
|
if (connection.config.type == ConnectionType::Bezier) {
|
||||||
|
position = connection.path.pointAtPercent(0.5);
|
||||||
|
angle = connection.path.angleAtPercent(0.5);
|
||||||
|
textRect.moveCenter(position);
|
||||||
|
} else {
|
||||||
|
const QLineF start(connection.start, connection.mid1);
|
||||||
|
const QLineF mid(connection.mid1, connection.mid2);
|
||||||
|
const QLineF end(connection.mid2, connection.end);
|
||||||
|
QVector<QLineF> pathLines = {start, mid, end};
|
||||||
|
|
||||||
|
std::sort(pathLines.begin(), pathLines.end(), [](const QLineF &a, const QLineF &b) {
|
||||||
|
return a.length() > b.length() && (a.angle() == 0 || a.angle() == 180);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Calculate font bounding box without taking into account the cale factor
|
||||||
|
QFont originalFont = painter->font();
|
||||||
|
originalFont.setPointSizeF(getFontSize(painter));
|
||||||
|
QFontMetrics originalMetric(originalFont);
|
||||||
|
QRectF originalTextRect = originalMetric.boundingRect(connection.config.events);
|
||||||
|
originalTextRect.adjust(-10.0, 0.0, 10.0, 0.0);
|
||||||
|
|
||||||
|
const qreal width = originalTextRect.width(); // original width
|
||||||
|
|
||||||
|
QVector<QLineF> candidates;
|
||||||
|
candidates.reserve(3);
|
||||||
|
std::copy_if(pathLines.begin(), pathLines.end(),
|
||||||
|
std::back_inserter(candidates),
|
||||||
|
[width](const QLineF &line) { return line.length() > width; });
|
||||||
|
|
||||||
|
const QLineF tmp = candidates.empty() ? start : candidates.first();
|
||||||
|
angle = tmp.angle();
|
||||||
|
|
||||||
|
if (tmp.p1() == start.p1()) {
|
||||||
|
if (angle == 0) {
|
||||||
|
position = tmp.p2() + QPointF(-connection.config.radius, halfHeight);
|
||||||
|
textRect.moveBottomRight(position);
|
||||||
|
} else if (angle == 90) {
|
||||||
|
position = tmp.p2() + QPointF(halfHeight, connection.config.radius);
|
||||||
|
textRect.moveBottomRight(position);
|
||||||
|
} else if (angle == 180) {
|
||||||
|
position = tmp.p2() + QPointF(connection.config.radius, halfHeight);
|
||||||
|
textRect.moveBottomLeft(position);
|
||||||
|
} else if (angle == 270) {
|
||||||
|
position = tmp.p2() + QPointF(halfHeight, -connection.config.radius);
|
||||||
|
textRect.moveBottomLeft(position);
|
||||||
|
}
|
||||||
|
} else if (tmp.p2() == end.p2()) {
|
||||||
|
if (angle == 0) {
|
||||||
|
position = tmp.p1() + QPointF(connection.config.radius, halfHeight);
|
||||||
|
textRect.moveBottomLeft(position);
|
||||||
|
} else if (angle == 90) {
|
||||||
|
position = tmp.p1() + QPointF(halfHeight, -connection.config.radius);
|
||||||
|
textRect.moveBottomLeft(position);
|
||||||
|
} else if (angle == 180) {
|
||||||
|
position = tmp.p1() + QPointF(-connection.config.radius, halfHeight);
|
||||||
|
textRect.moveBottomRight(position);
|
||||||
|
} else if (angle == 270) {
|
||||||
|
position = tmp.p1() + QPointF(halfHeight, connection.config.radius);
|
||||||
|
textRect.moveBottomRight(position);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
position = tmp.center();
|
||||||
|
textRect.moveCenter(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
painter->save();
|
||||||
|
|
||||||
|
painter->setBrush(Qt::red);
|
||||||
|
painter->translate(position);
|
||||||
|
painter->rotate(-normalizeAngle(angle));
|
||||||
|
painter->translate(-position);
|
||||||
|
painter->drawRoundedRect(textRect, halfHeight, halfHeight);
|
||||||
|
|
||||||
|
painter->setPen(Qt::white);
|
||||||
|
painter->drawText(textRect, Qt::AlignCenter, connection.config.events);
|
||||||
|
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FormEditorTransitionItem::drawEventIdsLabel(QPainter *painter, const Connection &connection)
|
||||||
|
{
|
||||||
|
if (!connection.config.isSelected || connection.config.events.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// draw label with event ids
|
||||||
|
const QStringList events = connection.config.events.split(',');
|
||||||
|
const int eventCount = events.size();
|
||||||
|
|
||||||
|
const qreal scaleFactor = getScaleFactor();
|
||||||
|
const qreal radius = 7.0 / scaleFactor;
|
||||||
|
const qreal hMargin = 10.0 / scaleFactor;
|
||||||
|
|
||||||
|
QFontMetrics metric(painter->font());
|
||||||
|
const QString title = QObject::tr("Connected Events");
|
||||||
|
const QRect titleRect = metric.boundingRect(title);
|
||||||
|
const qreal lineHeight = titleRect.height();
|
||||||
|
|
||||||
|
qreal minWidth = titleRect.width() + (2 * hMargin);
|
||||||
|
// Get the width for the widest event label
|
||||||
|
for (const QString &event : events)
|
||||||
|
minWidth = std::max(minWidth, metric.boundingRect(event.trimmed()).width() + (2 * hMargin));
|
||||||
|
|
||||||
|
const qreal offset = 10.0 / scaleFactor;
|
||||||
|
const QLineF line(connection.start, connection.mid1);
|
||||||
|
QPointF pos = line.p1();
|
||||||
|
|
||||||
|
if (line.angle() == 0)
|
||||||
|
pos += QPointF(0.0, offset);
|
||||||
|
else if (line.angle() == 90)
|
||||||
|
pos += QPointF(offset, -(eventCount + 1) * lineHeight);
|
||||||
|
else if (line.angle() == 180)
|
||||||
|
pos += QPointF(-minWidth, offset);
|
||||||
|
else if (line.angle() == 270)
|
||||||
|
pos += QPointF(offset, 0.0);
|
||||||
|
|
||||||
|
const QRectF tmpRect(pos, QSize(minWidth, lineHeight));
|
||||||
|
|
||||||
|
painter->save();
|
||||||
|
painter->setBrush(QColor(70, 70, 70, 200));
|
||||||
|
painter->setPen(Qt::NoPen);
|
||||||
|
|
||||||
|
// Draw background rect
|
||||||
|
painter->drawRoundedRect(tmpRect.adjusted(0, 0, 0, eventCount * lineHeight), radius, radius);
|
||||||
|
// Draw title background rect
|
||||||
|
painter->drawRoundedRect(tmpRect, radius, radius);
|
||||||
|
|
||||||
|
painter->setPen(Qt::lightGray);
|
||||||
|
// Draw title
|
||||||
|
painter->drawText(tmpRect, Qt::AlignHCenter | Qt::TextDontClip, title);
|
||||||
|
// Draw events
|
||||||
|
int i = 1;
|
||||||
|
for (const QString &event : events) {
|
||||||
|
painter->drawText(tmpRect.translated(hMargin, lineHeight * i++),
|
||||||
|
Qt::AlignLeft | Qt::TextDontClip,
|
||||||
|
event.trimmed());
|
||||||
|
}
|
||||||
|
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
static void drawArrow(QPainter *painter,
|
static void drawArrow(QPainter *painter,
|
||||||
const QPointF &point,
|
const QPointF &point,
|
||||||
const qreal &angle,
|
const qreal &angle,
|
||||||
int arrowLength,
|
const qreal &arrowLength,
|
||||||
int arrowWidth)
|
const qreal &arrowWidth)
|
||||||
{
|
{
|
||||||
const QPointF peakP(0, 0);
|
const QPointF peakP(0, 0);
|
||||||
const QPointF leftP(-arrowLength, -arrowWidth * 0.5);
|
const QPointF leftP(-arrowLength, -arrowWidth * 0.5);
|
||||||
@@ -1503,8 +1641,8 @@ static void drawArrow(QPainter *painter,
|
|||||||
|
|
||||||
void FormEditorTransitionItem::paintConnection(QPainter *painter, const Connection &connection)
|
void FormEditorTransitionItem::paintConnection(QPainter *painter, const Connection &connection)
|
||||||
{
|
{
|
||||||
const int arrowLength = 4 * connection.config.adjustedWidth;
|
const qreal arrowLength = 4 * connection.config.adjustedWidth;
|
||||||
const int arrowWidth = 8 * connection.config.adjustedWidth;
|
const qreal arrowWidth = 8 * connection.config.adjustedWidth;
|
||||||
|
|
||||||
painter->save();
|
painter->save();
|
||||||
painter->setRenderHint(QPainter::Antialiasing);
|
painter->setRenderHint(QPainter::Antialiasing);
|
||||||
@@ -1550,10 +1688,11 @@ void FormEditorTransitionItem::paintConnection(QPainter *painter, const Connecti
|
|||||||
// Draw start ellipse
|
// Draw start ellipse
|
||||||
if (connection.config.drawStart) {
|
if (connection.config.drawStart) {
|
||||||
painter->setBrush(Qt::white);
|
painter->setBrush(Qt::white);
|
||||||
painter->drawEllipse(connection.start, arrowLength / 3, arrowLength / 3);
|
painter->drawEllipse(connection.start, arrowLength / 2.0, arrowLength / 2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw labels
|
// Draw labels
|
||||||
|
if (viewportTransform().m11() >= zoomLevelLabel)
|
||||||
drawLabels(painter, connection);
|
drawLabels(painter, connection);
|
||||||
|
|
||||||
painter->restore();
|
painter->restore();
|
||||||
@@ -1580,12 +1719,15 @@ void FormEditorTransitionItem::paint(QPainter *painter, const QStyleOptionGraphi
|
|||||||
|
|
||||||
ConnectionConfiguration config(qmlItemNode(), resolved, viewportTransform().m11(), m_hitTest);
|
ConnectionConfiguration config(qmlItemNode(), resolved, viewportTransform().m11(), m_hitTest);
|
||||||
|
|
||||||
QFont font = painter->font();
|
QFont f = painter->font();
|
||||||
font.setPixelSize(config.fontSize);
|
f.setPointSizeF(getFontSize(painter) / getScaleFactor());
|
||||||
painter->setFont(font);
|
painter->setFont(f);
|
||||||
|
|
||||||
for (const auto &f : resolved.from) {
|
const auto fromNodes = resolved.from;
|
||||||
for (const auto &t : resolved.to) {
|
const auto toNodes = resolved.to;
|
||||||
|
|
||||||
|
for (const auto &f : fromNodes) {
|
||||||
|
for (const auto &t : toNodes) {
|
||||||
Connection connection(resolved, pos(), f, t, config);
|
Connection connection(resolved, pos(), f, t, config);
|
||||||
if (!config.hitTesting) {
|
if (!config.hitTesting) {
|
||||||
// The following if statement is a special treatment for n-to-n, 1-to-n and n-to-1
|
// The following if statement is a special treatment for n-to-n, 1-to-n and n-to-1
|
||||||
@@ -1650,11 +1792,11 @@ void FormEditorTransitionItem::paint(QPainter *painter, const QStyleOptionGraphi
|
|||||||
pen.setColor(config.color);
|
pen.setColor(config.color);
|
||||||
painter->setPen(pen);
|
painter->setPen(pen);
|
||||||
|
|
||||||
const int iconAdjust = 48;
|
const qreal iconAdjust = 48;
|
||||||
const int size = connection.fromRect.width();
|
const qreal size = connection.fromRect.width();
|
||||||
const int iconSize = size - iconAdjust;
|
const qreal iconSize = size - iconAdjust;
|
||||||
const int x = connection.fromRect.topRight().x() - startItemOffset;
|
const qreal x = connection.fromRect.topRight().x() - startItemOffset;
|
||||||
const int y = connection.fromRect.topRight().y();
|
const qreal y = connection.fromRect.topRight().y();
|
||||||
painter->drawRoundedRect(x, y , size - 10, size, size / 2, iconSize / 2);
|
painter->drawRoundedRect(x, y , size - 10, size, size / 2, iconSize / 2);
|
||||||
drawIcon(painter, x + iconAdjust / 2, y + iconAdjust / 2, icon, iconSize, iconSize, config.color);
|
drawIcon(painter, x + iconAdjust / 2, y + iconAdjust / 2, icon, iconSize, iconSize, config.color);
|
||||||
}
|
}
|
||||||
@@ -1675,7 +1817,7 @@ bool FormEditorTransitionItem::flowHitTest(const QPointF &point) const
|
|||||||
const_cast<FormEditorTransitionItem *>(this)->paint(&p, nullptr, nullptr);
|
const_cast<FormEditorTransitionItem *>(this)->paint(&p, nullptr, nullptr);
|
||||||
m_hitTest = false;
|
m_hitTest = false;
|
||||||
|
|
||||||
QPoint pos = mapFromScene(point).toPoint();
|
const QPoint pos = mapFromScene(point).toPoint();
|
||||||
return image.pixelColor(pos).value() > 0;
|
return image.pixelColor(pos).value() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1687,6 +1829,20 @@ QTransform FormEditorItem::viewportTransform() const
|
|||||||
return scene()->views().first()->viewportTransform();
|
return scene()->views().first()->viewportTransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qreal FormEditorItem::getFontSize(QPainter *painter) const
|
||||||
|
{
|
||||||
|
const int dpi = std::max(painter->device()->logicalDpiX(),
|
||||||
|
painter->device()->logicalDpiY());
|
||||||
|
|
||||||
|
return fontSize * (dpi / defaultDpi);
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal FormEditorItem::getScaleFactor() const
|
||||||
|
{
|
||||||
|
// Cap scaling at 100% zoom
|
||||||
|
return (viewportTransform().m11() >= 1.0) ? viewportTransform().m11() : 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
void FormEditorFlowDecisionItem::updateGeometry()
|
void FormEditorFlowDecisionItem::updateGeometry()
|
||||||
{
|
{
|
||||||
prepareGeometryChange();
|
prepareGeometryChange();
|
||||||
@@ -1704,7 +1860,7 @@ void FormEditorFlowDecisionItem::updateGeometry()
|
|||||||
|
|
||||||
// If drawing the dialog title is requested we need to add it to the bounding rect.
|
// If drawing the dialog title is requested we need to add it to the bounding rect.
|
||||||
QRectF labelBoundingRect;
|
QRectF labelBoundingRect;
|
||||||
int showDialogLabel = false;
|
bool showDialogLabel = false;
|
||||||
if (qmlItemNode().modelNode().hasAuxiliaryData("showDialogLabel"))
|
if (qmlItemNode().modelNode().hasAuxiliaryData("showDialogLabel"))
|
||||||
showDialogLabel = qmlItemNode().modelNode().auxiliaryData("showDialogLabel").toBool();
|
showDialogLabel = qmlItemNode().modelNode().auxiliaryData("showDialogLabel").toBool();
|
||||||
|
|
||||||
@@ -1718,10 +1874,10 @@ void FormEditorFlowDecisionItem::updateGeometry()
|
|||||||
QPixmap pixmap(640, 480);
|
QPixmap pixmap(640, 480);
|
||||||
QPainter localPainter(&pixmap);
|
QPainter localPainter(&pixmap);
|
||||||
QFont font = localPainter.font();
|
QFont font = localPainter.font();
|
||||||
font.setPixelSize(labelFontSize / viewportTransform().m11());
|
font.setPointSizeF(getFontSize(&localPainter) / getScaleFactor());
|
||||||
localPainter.setFont(font);
|
localPainter.setFont(font);
|
||||||
|
|
||||||
int margin = blockAdjust * 0.5;
|
const qreal margin = blockAdjust * 0.5;
|
||||||
const QRectF adjustedRect = boundingRect.adjusted(margin, margin, -margin, -margin);
|
const QRectF adjustedRect = boundingRect.adjusted(margin, margin, -margin, -margin);
|
||||||
|
|
||||||
QRectF textRect(0, 0, 100, 20);
|
QRectF textRect(0, 0, 100, 20);
|
||||||
@@ -1791,7 +1947,6 @@ void FormEditorFlowDecisionItem::paint(QPainter *painter, const QStyleOptionGrap
|
|||||||
if (qmlItemNode().modelNode().hasAuxiliaryData("color"))
|
if (qmlItemNode().modelNode().hasAuxiliaryData("color"))
|
||||||
flowColor = qmlItemNode().modelNode().auxiliaryData("color").value<QColor>();
|
flowColor = qmlItemNode().modelNode().auxiliaryData("color").value<QColor>();
|
||||||
|
|
||||||
const qreal scaleFactor = viewportTransform().m11();
|
|
||||||
qreal width = 2;
|
qreal width = 2;
|
||||||
|
|
||||||
if (qmlItemNode().modelNode().hasAuxiliaryData("width"))
|
if (qmlItemNode().modelNode().hasAuxiliaryData("width"))
|
||||||
@@ -1832,7 +1987,7 @@ void FormEditorFlowDecisionItem::paint(QPainter *painter, const QStyleOptionGrap
|
|||||||
|
|
||||||
QRectF boundingRect(0, 0, size, size);
|
QRectF boundingRect(0, 0, size, size);
|
||||||
QTransform transform;
|
QTransform transform;
|
||||||
int margin = blockAdjust;
|
qreal margin = blockAdjust;
|
||||||
if (m_iconType == DecisionIcon) {
|
if (m_iconType == DecisionIcon) {
|
||||||
transform.translate(boundingRect.center().x(), boundingRect.center().y());
|
transform.translate(boundingRect.center().x(), boundingRect.center().y());
|
||||||
transform.rotate(45);
|
transform.rotate(45);
|
||||||
@@ -1845,18 +2000,18 @@ void FormEditorFlowDecisionItem::paint(QPainter *painter, const QStyleOptionGrap
|
|||||||
painter->setTransform(transform, true);
|
painter->setTransform(transform, true);
|
||||||
painter->drawRoundedRect(adjustedRect, radius, radius);
|
painter->drawRoundedRect(adjustedRect, radius, radius);
|
||||||
|
|
||||||
const int iconDecrement = 32;
|
const qreal iconDecrement = 32.0;
|
||||||
const int iconSize = adjustedRect.width() - iconDecrement;
|
const qreal iconSize = adjustedRect.width() - iconDecrement;
|
||||||
const int offset = iconDecrement / 2 + margin;
|
const qreal offset = iconDecrement / 2.0 + margin;
|
||||||
|
|
||||||
painter->restore();
|
painter->restore();
|
||||||
|
|
||||||
// Draw the dialog title inside the form view if requested. Decision item only.
|
// Draw the dialog title inside the form view if requested. Decision item only.
|
||||||
int showDialogLabel = false;
|
bool showDialogLabel = false;
|
||||||
if (qmlItemNode().modelNode().hasAuxiliaryData("showDialogLabel"))
|
if (qmlItemNode().modelNode().hasAuxiliaryData("showDialogLabel"))
|
||||||
showDialogLabel = qmlItemNode().modelNode().auxiliaryData("showDialogLabel").toBool();
|
showDialogLabel = qmlItemNode().modelNode().auxiliaryData("showDialogLabel").toBool();
|
||||||
|
|
||||||
if (showDialogLabel) {
|
if (showDialogLabel && viewportTransform().m11() >= zoomLevelLabel) {
|
||||||
QString dialogTitle;
|
QString dialogTitle;
|
||||||
if (qmlItemNode().modelNode().hasVariantProperty("dialogTitle"))
|
if (qmlItemNode().modelNode().hasVariantProperty("dialogTitle"))
|
||||||
dialogTitle = qmlItemNode().modelNode().variantProperty("dialogTitle").value().toString();
|
dialogTitle = qmlItemNode().modelNode().variantProperty("dialogTitle").value().toString();
|
||||||
@@ -1864,7 +2019,7 @@ void FormEditorFlowDecisionItem::paint(QPainter *painter, const QStyleOptionGrap
|
|||||||
if (!dialogTitle.isEmpty()) {
|
if (!dialogTitle.isEmpty()) {
|
||||||
|
|
||||||
QFont font = painter->font();
|
QFont font = painter->font();
|
||||||
font.setPixelSize(labelFontSize / scaleFactor);
|
font.setPointSizeF(getFontSize(painter) / getScaleFactor());
|
||||||
painter->setFont(font);
|
painter->setFont(font);
|
||||||
|
|
||||||
QRectF textRect(0, 0, 100, 20);
|
QRectF textRect(0, 0, 100, 20);
|
||||||
|
@@ -128,6 +128,8 @@ protected:
|
|||||||
QList<FormEditorItem*> offspringFormEditorItemsRecursive(const FormEditorItem *formEditorItem) const;
|
QList<FormEditorItem*> offspringFormEditorItemsRecursive(const FormEditorItem *formEditorItem) const;
|
||||||
FormEditorItem(const QmlItemNode &qmlItemNode, FormEditorScene* scene);
|
FormEditorItem(const QmlItemNode &qmlItemNode, FormEditorScene* scene);
|
||||||
QTransform viewportTransform() const;
|
QTransform viewportTransform() const;
|
||||||
|
qreal getFontSize(QPainter *painter) const;
|
||||||
|
qreal getScaleFactor() const;
|
||||||
|
|
||||||
QRectF m_boundingRect;
|
QRectF m_boundingRect;
|
||||||
QRectF m_paintedBoundingRect;
|
QRectF m_paintedBoundingRect;
|
||||||
@@ -204,6 +206,11 @@ protected:
|
|||||||
{}
|
{}
|
||||||
void paintConnection(QPainter *painter, const Connection &connection);
|
void paintConnection(QPainter *painter, const Connection &connection);
|
||||||
void drawLabels(QPainter *painter, const Connection &connection);
|
void drawLabels(QPainter *painter, const Connection &connection);
|
||||||
|
|
||||||
|
void drawGeneralLabel(QPainter *painter, const Connection &connection);
|
||||||
|
void drawSingleEventIdLabel(QPainter *painter, const Connection &connection);
|
||||||
|
void drawEventIdsLabel(QPainter *painter, const Connection &connection);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable bool m_hitTest = false;
|
mutable bool m_hitTest = false;
|
||||||
};
|
};
|
||||||
|
@@ -33,10 +33,12 @@ from optparse import OptionParser
|
|||||||
from toolfunctions import checkDirectory
|
from toolfunctions import checkDirectory
|
||||||
from toolfunctions import getFileContent
|
from toolfunctions import getFileContent
|
||||||
|
|
||||||
|
|
||||||
objMap = None
|
objMap = None
|
||||||
lastToken = [None, None]
|
lastToken = [None, None]
|
||||||
stopTokens = ('OP', 'NAME', 'NUMBER', 'ENDMARKER')
|
stopTokens = ('OP', 'NAME', 'NUMBER', 'ENDMARKER')
|
||||||
|
|
||||||
|
|
||||||
def parseCommandLine():
|
def parseCommandLine():
|
||||||
global directory, onlyRemovable, sharedFolders, deleteObjects
|
global directory, onlyRemovable, sharedFolders, deleteObjects
|
||||||
parser = OptionParser("\n%prog [OPTIONS] [DIRECTORY]")
|
parser = OptionParser("\n%prog [OPTIONS] [DIRECTORY]")
|
||||||
@@ -54,7 +56,7 @@ def parseCommandLine():
|
|||||||
elif len(args) == 1:
|
elif len(args) == 1:
|
||||||
directory = os.path.abspath(args[0])
|
directory = os.path.abspath(args[0])
|
||||||
else:
|
else:
|
||||||
print "\nERROR: Too many arguments\n"
|
print("\nERROR: Too many arguments\n")
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
onlyRemovable = options.onlyRemovable
|
onlyRemovable = options.onlyRemovable
|
||||||
@@ -70,6 +72,7 @@ def collectObjects():
|
|||||||
data = getFileContent(objMap)
|
data = getFileContent(objMap)
|
||||||
return map(lambda x: x.strip().split("\t", 1)[0], data.strip().splitlines())
|
return map(lambda x: x.strip().split("\t", 1)[0], data.strip().splitlines())
|
||||||
|
|
||||||
|
|
||||||
def handleStringsWithTrailingBackSlash(origStr):
|
def handleStringsWithTrailingBackSlash(origStr):
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
@@ -78,8 +81,11 @@ def handleStringsWithTrailingBackSlash(origStr):
|
|||||||
except:
|
except:
|
||||||
return origStr
|
return origStr
|
||||||
|
|
||||||
def handle_token(tokenType, token, (startRow, startCol), (endRow, endCol), line):
|
|
||||||
|
def handle_token(tokenType, token, startPos, endPos, line):
|
||||||
global useCounts, lastToken, stopTokens
|
global useCounts, lastToken, stopTokens
|
||||||
|
(startRow, startCol) = startPos
|
||||||
|
(endRow, endCol) = endPos
|
||||||
|
|
||||||
if tokenize.tok_name[tokenType] == 'STRING':
|
if tokenize.tok_name[tokenType] == 'STRING':
|
||||||
# concatenate strings followed directly by other strings
|
# concatenate strings followed directly by other strings
|
||||||
@@ -87,7 +93,7 @@ def handle_token(tokenType, token, (startRow, startCol), (endRow, endCol), line)
|
|||||||
token = "'" + lastToken[1][1:-1] + str(token)[1:-1] + "'"
|
token = "'" + lastToken[1][1:-1] + str(token)[1:-1] + "'"
|
||||||
# store the new string as lastToken after removing potential trailing backslashes
|
# store the new string as lastToken after removing potential trailing backslashes
|
||||||
# (including their following indentation)
|
# (including their following indentation)
|
||||||
lastToken = ['STRING' , handleStringsWithTrailingBackSlash(str(token))]
|
lastToken = ['STRING', handleStringsWithTrailingBackSlash(str(token))]
|
||||||
# if a stop token occurs check the potential string before it
|
# if a stop token occurs check the potential string before it
|
||||||
elif tokenize.tok_name[tokenType] in stopTokens:
|
elif tokenize.tok_name[tokenType] in stopTokens:
|
||||||
if lastToken[0] == 'STRING':
|
if lastToken[0] == 'STRING':
|
||||||
@@ -97,17 +103,22 @@ def handle_token(tokenType, token, (startRow, startCol), (endRow, endCol), line)
|
|||||||
# store the stop token as lastToken
|
# store the stop token as lastToken
|
||||||
lastToken = [tokenize.tok_name[tokenType], str(token)]
|
lastToken = [tokenize.tok_name[tokenType], str(token)]
|
||||||
|
|
||||||
|
|
||||||
def handleDataFiles(openFile, separator):
|
def handleDataFiles(openFile, separator):
|
||||||
global useCounts
|
global useCounts
|
||||||
# ignore header line
|
# ignore header line
|
||||||
openFile.readline()
|
first = True
|
||||||
for line in openFile:
|
for line in openFile:
|
||||||
|
if first:
|
||||||
|
first = False
|
||||||
|
continue
|
||||||
currentTokens = line.split(separator)
|
currentTokens = line.split(separator)
|
||||||
for token in currentTokens:
|
for token in currentTokens:
|
||||||
stripped = token.strip().strip('"')
|
stripped = token.strip().strip('"')
|
||||||
if stripped in useCounts:
|
if stripped in useCounts:
|
||||||
useCounts[stripped] = useCounts[stripped] + 1
|
useCounts[stripped] = useCounts[stripped] + 1
|
||||||
|
|
||||||
|
|
||||||
def findUsages():
|
def findUsages():
|
||||||
global directory, objMap, sharedFolders
|
global directory, objMap, sharedFolders
|
||||||
suffixes = (".py", ".csv", ".tsv")
|
suffixes = (".py", ".csv", ".tsv")
|
||||||
@@ -130,36 +141,51 @@ def findUsages():
|
|||||||
for directory in directories:
|
for directory in directories:
|
||||||
for root, dirnames, filenames in os.walk(directory):
|
for root, dirnames, filenames in os.walk(directory):
|
||||||
for filename in filter(lambda x: x.endswith(suffixes), filenames):
|
for filename in filter(lambda x: x.endswith(suffixes), filenames):
|
||||||
currentFile = open(os.path.join(root, filename))
|
if sys.version_info.major == 2:
|
||||||
|
currentFile = open(os.path.join(root, filename), "r")
|
||||||
|
else:
|
||||||
|
currentFile = open(os.path.join(root, filename), "r", encoding="utf8")
|
||||||
if filename.endswith(".py"):
|
if filename.endswith(".py"):
|
||||||
|
if sys.version_info.major == 2:
|
||||||
tokenize.tokenize(currentFile.readline, handle_token)
|
tokenize.tokenize(currentFile.readline, handle_token)
|
||||||
|
else:
|
||||||
|
tokens = tokenize.generate_tokens(currentFile.readline)
|
||||||
|
for token in tokens:
|
||||||
|
handle_token(token.type, token.string, token.start, token.end, token.line)
|
||||||
elif filename.endswith(".csv"):
|
elif filename.endswith(".csv"):
|
||||||
handleDataFiles(currentFile, ",")
|
handleDataFiles(currentFile, ",")
|
||||||
elif filename.endswith(".tsv"):
|
elif filename.endswith(".tsv"):
|
||||||
handleDataFiles(currentFile, "\t")
|
handleDataFiles(currentFile, "\t")
|
||||||
currentFile.close()
|
currentFile.close()
|
||||||
currentFile = open(objMap)
|
currentFile = open(objMap)
|
||||||
|
if sys.version_info.major == 2:
|
||||||
tokenize.tokenize(currentFile.readline, handle_token)
|
tokenize.tokenize(currentFile.readline, handle_token)
|
||||||
|
else:
|
||||||
|
tokens = tokenize.generate_tokens(currentFile.readline)
|
||||||
|
for token in tokens:
|
||||||
|
handle_token(token.type, token.string, token.start, token.end, token.line)
|
||||||
currentFile.close()
|
currentFile.close()
|
||||||
|
|
||||||
|
|
||||||
def printResult():
|
def printResult():
|
||||||
global useCounts, onlyRemovable
|
global useCounts, onlyRemovable
|
||||||
print
|
print
|
||||||
if onlyRemovable:
|
if onlyRemovable:
|
||||||
if min(useCounts.values()) > 0:
|
if min(useCounts.values()) > 0:
|
||||||
print "All objects are used once at least.\n"
|
print("All objects are used once at least.\n")
|
||||||
return False
|
return False
|
||||||
print "Unused objects:\n"
|
print("Unused objects:\n")
|
||||||
for obj in filter(lambda x: useCounts[x] == 0, useCounts):
|
for obj in filter(lambda x: useCounts[x] == 0, useCounts):
|
||||||
print "%s" % obj
|
print("%s" % obj)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
outFormat = "%3d %s"
|
outFormat = "%3d %s"
|
||||||
for obj,useCount in useCounts.iteritems():
|
for obj, useCount in useCounts.items():
|
||||||
print outFormat % (useCount, obj)
|
print(outFormat % (useCount, obj))
|
||||||
print
|
print
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def deleteRemovable():
|
def deleteRemovable():
|
||||||
global useCounts, objMap
|
global useCounts, objMap
|
||||||
|
|
||||||
@@ -192,6 +218,7 @@ def deleteRemovable():
|
|||||||
print("Deleted %d items, old objects.map has been moved to objects.map~" % count)
|
print("Deleted %d items, old objects.map has been moved to objects.map~" % count)
|
||||||
return count > 0
|
return count > 0
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
global useCounts, objMap, deleteObjects
|
global useCounts, objMap, deleteObjects
|
||||||
objMap = checkDirectory(directory)
|
objMap = checkDirectory(directory)
|
||||||
@@ -209,6 +236,7 @@ def main():
|
|||||||
print(mssg + "to find objects that might have been referenced only by removed objects.\n")
|
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__':
|
||||||
parseCommandLine()
|
parseCommandLine()
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
|
@@ -30,6 +30,9 @@ import sys
|
|||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
from toolfunctions import checkDirectory
|
from toolfunctions import checkDirectory
|
||||||
from toolfunctions import getFileContent
|
from toolfunctions import getFileContent
|
||||||
|
if sys.version_info.major == 3:
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
|
||||||
def parseCommandLine():
|
def parseCommandLine():
|
||||||
global directory, tsv
|
global directory, tsv
|
||||||
@@ -43,11 +46,12 @@ def parseCommandLine():
|
|||||||
elif len(args) == 1:
|
elif len(args) == 1:
|
||||||
directory = os.path.abspath(args[0])
|
directory = os.path.abspath(args[0])
|
||||||
else:
|
else:
|
||||||
print "\nERROR: Too many arguments\n"
|
print("\nERROR: Too many arguments\n")
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
tsv = options.tsv
|
tsv = options.tsv
|
||||||
|
|
||||||
|
|
||||||
def readProperties(line):
|
def readProperties(line):
|
||||||
def readOneProperty(rawProperties):
|
def readOneProperty(rawProperties):
|
||||||
name, rawProperties = rawProperties.split("=", 1)
|
name, rawProperties = rawProperties.split("=", 1)
|
||||||
@@ -64,6 +68,7 @@ def readProperties(line):
|
|||||||
properties[name] = value
|
properties[name] = value
|
||||||
return objectName, properties
|
return objectName, properties
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
global directory, tsv
|
global directory, tsv
|
||||||
objMap = checkDirectory(directory)
|
objMap = checkDirectory(directory)
|
||||||
@@ -71,23 +76,24 @@ def main():
|
|||||||
|
|
||||||
# Which properties have been used at least once?
|
# Which properties have been used at least once?
|
||||||
eachObjectsProperties = [set(properties.keys()) for properties in objects.values()]
|
eachObjectsProperties = [set(properties.keys()) for properties in objects.values()]
|
||||||
usedProperties = list(reduce(lambda x,y: x | y, eachObjectsProperties))
|
usedProperties = list(reduce(lambda x, y: x | y, eachObjectsProperties))
|
||||||
|
|
||||||
if tsv:
|
if tsv:
|
||||||
print "\t".join(["Squish internal name"] + usedProperties)
|
print("\t".join(["Squish internal name"] + usedProperties))
|
||||||
for name, properties in objects.items():
|
for name, properties in objects.items():
|
||||||
values = [name] + map(lambda x: properties.setdefault(x, ""), usedProperties)
|
values = [name] + map(lambda x: properties.setdefault(x, ""), usedProperties)
|
||||||
print "\t".join(values)
|
print("\t".join(values))
|
||||||
else:
|
else:
|
||||||
maxPropertyLength = max(map(len, usedProperties))
|
maxPropertyLength = max(map(len, usedProperties))
|
||||||
for name, properties in objects.items():
|
for name, properties in objects.items():
|
||||||
print "Squish internal name: %s" % name
|
print("Squish internal name: %s" % name)
|
||||||
print "Properties:"
|
print("Properties:")
|
||||||
for key, val in properties.items():
|
for key, val in properties.items():
|
||||||
print "%s: %s" % (key.rjust(maxPropertyLength + 4), val)
|
print("%s: %s" % (key.rjust(maxPropertyLength + 4), val))
|
||||||
print
|
print()
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parseCommandLine()
|
parseCommandLine()
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
|
@@ -26,16 +26,18 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
def checkDirectory(directory):
|
def checkDirectory(directory):
|
||||||
if not os.path.exists(directory):
|
if not os.path.exists(directory):
|
||||||
print "Given path '%s' does not exist" % directory
|
print("Given path '%s' does not exist" % directory)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
objMap = os.path.join(directory, "objects.map")
|
objMap = os.path.join(directory, "objects.map")
|
||||||
if not os.path.exists(objMap):
|
if not os.path.exists(objMap):
|
||||||
print "Given path '%s' does not contain an objects.map file" % directory
|
print("Given path '%s' does not contain an objects.map file" % directory)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
return objMap
|
return objMap
|
||||||
|
|
||||||
|
|
||||||
def getFileContent(filePath):
|
def getFileContent(filePath):
|
||||||
if os.path.isfile(filePath):
|
if os.path.isfile(filePath):
|
||||||
f = open(filePath, "r")
|
f = open(filePath, "r")
|
||||||
|
Reference in New Issue
Block a user