diff options
Diffstat (limited to 'src')
354 files changed, 3723 insertions, 3940 deletions
diff --git a/src/libs/advanceddockingsystem/workspaceview.cpp b/src/libs/advanceddockingsystem/workspaceview.cpp index 383aa2d0a5..087fc056af 100644 --- a/src/libs/advanceddockingsystem/workspaceview.cpp +++ b/src/libs/advanceddockingsystem/workspaceview.cpp @@ -187,7 +187,7 @@ void WorkspaceView::showEvent(QShowEvent *event) void WorkspaceView::keyPressEvent(QKeyEvent *event) { - if (event->key() != Qt::Key_Delete) { + if (event->key() != Qt::Key_Delete && event->key() != Qt::Key_Backspace) { TreeView::keyPressEvent(event); return; } diff --git a/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp b/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp index fe070fc08a..121fd1ff69 100644 --- a/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp +++ b/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp @@ -55,6 +55,7 @@ static const int KEYWORD_DISPLAY = 11; static const int KEYWORD_TEXTALIGN = 12; static const int KEYWORD_BASECOLOR = 13; static const int KEYWORD_SHAPE = 14; +static const int KEYWORD_OUTLINE = 15; // Shape items static const int KEYWORD_CIRCLE = 30; @@ -245,6 +246,7 @@ void StereotypeDefinitionParser::parse(ITextSource *source) << qMakePair(QString("textalignment"), KEYWORD_TEXTALIGN) << qMakePair(QString("basecolor"), KEYWORD_BASECOLOR) << qMakePair(QString("shape"), KEYWORD_SHAPE) + << qMakePair(QString("outline"), KEYWORD_OUTLINE) << qMakePair(QString("circle"), KEYWORD_CIRCLE) << qMakePair(QString("ellipse"), KEYWORD_ELLIPSE) << qMakePair(QString("line"), KEYWORD_LINE) @@ -436,6 +438,9 @@ void StereotypeDefinitionParser::parseIcon() case KEYWORD_SHAPE: stereotypeIcon.setIconShape(parseIconShape()); break; + case KEYWORD_OUTLINE: + stereotypeIcon.setOutlineShape(parseIconShape()); + break; case KEYWORD_NAME: stereotypeIcon.setName(parseStringProperty()); stereotypeIcon.setHasName(true); diff --git a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp index 34efac9f3d..6349b7db30 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp @@ -88,7 +88,7 @@ public: Q_UNUSED(option) Q_UNUSED(widget) - QPen pen(QBrush(Qt::gray), 1.0, Qt::DotLine); + QPen pen(QBrush(Qt::lightGray), 1.0, Qt::DotLine); painter->setPen(pen); painter->drawLine(QLineF(0.0, 0.0, 20.0, 0.0)); painter->drawLine(QLineF(0.0, 0.0, 0.0, 20.0)); diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp index 3e65c36dae..658b6bdb38 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp @@ -287,8 +287,25 @@ void ClassItem::update() bool ClassItem::intersectShapeWithLine(const QLineF &line, QPointF *intersectionPoint, QLineF *intersectionLine) const { + if (m_customIcon) { + QList<QPolygonF> polygons = m_customIcon->outline(); + for (int i = 0; i < polygons.size(); ++i) + polygons[i].translate(object()->pos() + object()->rect().topLeft()); + if (shapeIcon().textAlignment() == qmt::StereotypeIcon::TextalignBelow) { + if (nameItem()) { + QPolygonF polygon(nameItem()->boundingRect()); + polygon.translate(object()->pos() + nameItem()->pos()); + polygons.append(polygon); + } + if (m_contextLabel) { + QPolygonF polygon(m_contextLabel->boundingRect()); + polygon.translate(object()->pos() + m_contextLabel->pos()); + polygons.append(polygon); + } + } + return GeometryUtilities::intersect(polygons, line, nullptr, intersectionPoint, intersectionLine); + } QPolygonF polygon; - // TODO if m_customIcon then use that shape + label's shape as intersection path QRectF rect = object()->rect(); rect.translate(object()->pos()); polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.cpp index 96f0b8231c..55e70d9b1f 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.cpp @@ -160,13 +160,26 @@ void ComponentItem::update() bool ComponentItem::intersectShapeWithLine(const QLineF &line, QPointF *intersectionPoint, QLineF *intersectionLine) const { - QPolygonF polygon; if (m_customIcon) { - // TODO use customIcon path as shape - QRectF rect = object()->rect(); - rect.translate(object()->pos()); - polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); - } else if (hasPlainShape()) { + QList<QPolygonF> polygons = m_customIcon->outline(); + for (int i = 0; i < polygons.size(); ++i) + polygons[i].translate(object()->pos() + object()->rect().topLeft()); + if (shapeIcon().textAlignment() == qmt::StereotypeIcon::TextalignBelow) { + if (nameItem()) { + QPolygonF polygon(nameItem()->boundingRect()); + polygon.translate(object()->pos() + nameItem()->pos()); + polygons.append(polygon); + } + if (m_contextLabel) { + QPolygonF polygon(m_contextLabel->boundingRect()); + polygon.translate(object()->pos() + m_contextLabel->pos()); + polygons.append(polygon); + } + } + return GeometryUtilities::intersect(polygons, line, nullptr, intersectionPoint, intersectionLine); + } + QPolygonF polygon; + if (hasPlainShape()) { QRectF rect = object()->rect(); rect.translate(object()->pos()); polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); @@ -177,10 +190,14 @@ bool ComponentItem::intersectShapeWithLine(const QLineF &line, QPointF *intersec << rect.topRight() << rect.bottomRight() << rect.bottomLeft() - << rect.bottomLeft() + QPointF(0, UPPER_RECT_Y + RECT_HEIGHT + RECT_Y_DISTANCE + RECT_HEIGHT) - << rect.bottomLeft() + QPointF(-RECT_WIDTH * 0.5, UPPER_RECT_Y + RECT_HEIGHT + RECT_Y_DISTANCE + RECT_HEIGHT) - << rect.bottomLeft() + QPointF(-RECT_WIDTH * 0.5, UPPER_RECT_Y) - << rect.bottomLeft() + QPointF(0, UPPER_RECT_Y) + << rect.topLeft() + QPointF(0, UPPER_RECT_Y + RECT_HEIGHT + RECT_Y_DISTANCE + RECT_HEIGHT) + << rect.topLeft() + QPointF(-RECT_WIDTH * 0.5, UPPER_RECT_Y + RECT_HEIGHT + RECT_Y_DISTANCE + RECT_HEIGHT) + << rect.topLeft() + QPointF(-RECT_WIDTH * 0.5, UPPER_RECT_Y + RECT_HEIGHT + RECT_Y_DISTANCE) + << rect.topLeft() + QPointF(0, UPPER_RECT_Y + RECT_HEIGHT + RECT_Y_DISTANCE) + << rect.topLeft() + QPointF(0, UPPER_RECT_Y + RECT_HEIGHT) + << rect.topLeft() + QPointF(-RECT_WIDTH * 0.5, UPPER_RECT_Y + RECT_HEIGHT) + << rect.topLeft() + QPointF(-RECT_WIDTH * 0.5, UPPER_RECT_Y) + << rect.topLeft() + QPointF(0, UPPER_RECT_Y) << rect.topLeft(); } return GeometryUtilities::intersect(polygon, line, intersectionPoint, intersectionLine); diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.cpp index c3cce6a297..bdb1ab543f 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.cpp @@ -122,17 +122,24 @@ void DiagramItem::update() bool DiagramItem::intersectShapeWithLine(const QLineF &line, QPointF *intersectionPoint, QLineF *intersectionLine) const { - QPolygonF polygon; if (m_customIcon) { - // TODO use customIcon path as shape - QRectF rect = object()->rect(); - rect.translate(object()->pos()); - polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); - } else { - QRectF rect = object()->rect(); - rect.translate(object()->pos()); - polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); + QList<QPolygonF> polygons = m_customIcon->outline(); + for (int i = 0; i < polygons.size(); ++i) + polygons[i].translate(object()->pos() + object()->rect().topLeft()); + if (shapeIcon().textAlignment() == qmt::StereotypeIcon::TextalignBelow) { + if (nameItem()) { + QPolygonF polygon(nameItem()->boundingRect()); + polygon.translate(object()->pos() + nameItem()->pos()); + polygons.append(polygon); + } + } + return GeometryUtilities::intersect(polygons, line, nullptr, intersectionPoint, intersectionLine); } + QPolygonF polygon; + QRectF rect = object()->rect(); + rect.translate(object()->pos()); + // TODO use real outline + polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); return GeometryUtilities::intersect(polygon, line, intersectionPoint, intersectionLine); } diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.cpp index e3b50bab1b..cac585efa4 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.cpp @@ -130,17 +130,28 @@ void ItemItem::update() bool ItemItem::intersectShapeWithLine(const QLineF &line, QPointF *intersectionPoint, QLineF *intersectionLine) const { - QPolygonF polygon; if (m_customIcon) { - // TODO use customIcon path as shape - QRectF rect = object()->rect(); - rect.translate(object()->pos()); - polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); - } else { - QRectF rect = object()->rect(); - rect.translate(object()->pos()); - polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); + QList<QPolygonF> polygons = m_customIcon->outline(); + for (int i = 0; i < polygons.size(); ++i) + polygons[i].translate(object()->pos() + object()->rect().topLeft()); + if (shapeIcon().textAlignment() == qmt::StereotypeIcon::TextalignBelow) { + if (nameItem()) { + QPolygonF polygon(nameItem()->boundingRect()); + polygon.translate(object()->pos() + nameItem()->pos()); + polygons.append(polygon); + } + if (m_contextLabel) { + QPolygonF polygon(m_contextLabel->boundingRect()); + polygon.translate(object()->pos() + m_contextLabel->pos()); + polygons.append(polygon); + } + } + return GeometryUtilities::intersect(polygons, line, nullptr, intersectionPoint, intersectionLine); } + QRectF rect = object()->rect(); + rect.translate(object()->pos()); + QPolygonF polygon; + polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); return GeometryUtilities::intersect(polygon, line, intersectionPoint, intersectionLine); } diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.cpp index 8cc4f7ed92..7514d58203 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.cpp @@ -141,21 +141,32 @@ void PackageItem::update() bool PackageItem::intersectShapeWithLine(const QLineF &line, QPointF *intersectionPoint, QLineF *intersectionLine) const { - QPolygonF polygon; if (m_customIcon) { - // TODO use customIcon path as shape - QRectF rect = object()->rect(); - rect.translate(object()->pos()); - polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); - } else { - QRectF rect = object()->rect(); - rect.translate(object()->pos()); - ShapeGeometry shape = calcMinimumGeometry(); - polygon << rect.topLeft() << (rect.topLeft() + QPointF(shape.m_minimumTabSize.width(), 0.0)) - << (rect.topLeft() + QPointF(shape.m_minimumTabSize.width(), shape.m_minimumTabSize.height())) - << rect.topRight() + QPointF(0.0, shape.m_minimumTabSize.height()) - << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); + QList<QPolygonF> polygons = m_customIcon->outline(); + for (int i = 0; i < polygons.size(); ++i) + polygons[i].translate(object()->pos() + object()->rect().topLeft()); + if (shapeIcon().textAlignment() == qmt::StereotypeIcon::TextalignBelow) { + if (nameItem()) { + QPolygonF polygon(nameItem()->boundingRect()); + polygon.translate(object()->pos() + nameItem()->pos()); + polygons.append(polygon); + } + if (m_contextLabel) { + QPolygonF polygon(m_contextLabel->boundingRect()); + polygon.translate(object()->pos() + m_contextLabel->pos()); + polygons.append(polygon); + } + } + return GeometryUtilities::intersect(polygons, line, nullptr, intersectionPoint, intersectionLine); } + QPolygonF polygon; + QRectF rect = object()->rect(); + rect.translate(object()->pos()); + ShapeGeometry shape = calcMinimumGeometry(); + polygon << rect.topLeft() << (rect.topLeft() + QPointF(shape.m_minimumTabSize.width(), 0.0)) + << (rect.topLeft() + QPointF(shape.m_minimumTabSize.width(), shape.m_minimumTabSize.height())) + << rect.topRight() + QPointF(0.0, shape.m_minimumTabSize.height()) + << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); return GeometryUtilities::intersect(polygon, line, intersectionPoint, intersectionLine); } diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.cpp index 374f1e786a..13a8e4cbce 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.cpp @@ -33,6 +33,8 @@ #include <QPainter> +//#define DEBUG_OUTLINE + namespace qmt { CustomIconItem::CustomIconItem(DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent) @@ -102,9 +104,30 @@ void CustomIconItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *op painter->save(); painter->setBrush(m_brush); painter->setPen(m_pen); +#ifdef DEBUG_OUTLINE + ShapePolygonVisitor visitor(QPointF(0.0, 0.0), QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), m_baseSize, m_actualSize); + IconShape shape = m_stereotypeIcon.outlineShape(); + if (shape.isEmpty()) + shape = m_stereotypeIcon.iconShape(); + shape.visitShapes(&visitor); + painter->drawPath(visitor.path()); + ShapePaintVisitor visitor1(painter, QPointF(0.0, 0.0), QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), m_baseSize, m_actualSize); + m_stereotypeIcon.iconShape().visitShapes(&visitor1); +#else ShapePaintVisitor visitor(painter, QPointF(0.0, 0.0), QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), m_baseSize, m_actualSize); m_stereotypeIcon.iconShape().visitShapes(&visitor); +#endif painter->restore(); } +QList<QPolygonF> CustomIconItem::outline() const +{ + ShapePolygonVisitor visitor(QPointF(0.0, 0.0), QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), m_baseSize, m_actualSize); + IconShape shape = m_stereotypeIcon.outlineShape(); + if (shape.isEmpty()) + shape = m_stereotypeIcon.iconShape(); + shape.visitShapes(&visitor); + return visitor.toPolygons(); +} + } // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.h b/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.h index 93e083b962..ce4ea97260 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.h +++ b/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.h @@ -55,6 +55,8 @@ public: QRectF boundingRect() const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; + QList<QPolygonF> outline() const; + private: DiagramSceneModel *m_diagramSceneModel = nullptr; QString m_stereotypeIconId; diff --git a/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.cpp b/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.cpp index ecc7fb327c..2d23871f0b 100644 --- a/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.cpp +++ b/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.cpp @@ -151,8 +151,10 @@ void DiagramView::dropEvent(QDropEvent *event) void DiagramView::onSceneRectChanged(const QRectF &sceneRect) { - // TODO add some adjustment to all 4 sides? - setSceneRect(sceneRect); + // add some adjustment to all 4 sides + static const qreal ADJUSTMENT = 80; + QRectF rect = sceneRect.adjusted(-ADJUSTMENT, -ADJUSTMENT, ADJUSTMENT, ADJUSTMENT); + setSceneRect(rect); } } // namespace qmt diff --git a/src/libs/modelinglib/qmt/infrastructure/geometryutilities.cpp b/src/libs/modelinglib/qmt/infrastructure/geometryutilities.cpp index 5a42bf1f33..91886cf49e 100644 --- a/src/libs/modelinglib/qmt/infrastructure/geometryutilities.cpp +++ b/src/libs/modelinglib/qmt/infrastructure/geometryutilities.cpp @@ -54,24 +54,83 @@ QLineF GeometryUtilities::stretch(const QLineF &line, double p1Extension, double } bool GeometryUtilities::intersect(const QPolygonF &polygon, const QLineF &line, - QPointF *intersectionPoint, QLineF *intersectionLine) + QPointF *intersectionPoint, QLineF *intersectionLine, + int nearestPoint) { + bool found = false; + qreal mindist = 0; + QPointF ipoint; + QLineF iline; for (int i = 0; i <= polygon.size() - 2; ++i) { QLineF polygonLine(polygon.at(i), polygon.at(i+1)); + QPointF point; #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) - QLineF::IntersectType intersectionType = polygonLine.intersect(line, intersectionPoint); + QLineF::IntersectType intersectionType = polygonLine.intersect(line, &point); #else - QLineF::IntersectType intersectionType = polygonLine.intersects(line, intersectionPoint); + QLineF::IntersectType intersectionType = polygonLine.intersects(line, &point); #endif if (intersectionType == QLineF::BoundedIntersection) { - if (intersectionLine) - *intersectionLine = polygonLine; - return true; + qreal dist = QLineF(point, nearestPoint <= 0 ? line.p1() : line.p2()).length(); + if (!found || dist < mindist) { + mindist = dist; + ipoint = point; + iline = polygonLine; + found = true; + } + } + } + if (found) { + if (intersectionPoint) + *intersectionPoint = ipoint; + if (intersectionLine) + *intersectionLine = iline; + } + return found; +} + +bool GeometryUtilities::intersect(const QList<QPolygonF> &polygons, const QLineF &line, + int *intersectionPolygon, QPointF *intersectionPoint, + QLineF *intersectionLine, int nearestPoint) +{ + bool found = false; + qreal mindist = 0; + int ipolygon = -1; + QPointF ipoint; + QLineF iline; + for (int p = 0; p < polygons.size(); ++p) { + const QPolygonF polygon = polygons.at(p); + for (int i = 0; i <= polygon.size() - 2; ++i) { + const QLineF polygonLine(polygon.at(i), polygon.at(i + 1)); + QPointF point; +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) + QLineF::IntersectType intersectionType = polygonLine.intersect(line, &point); +#else + QLineF::IntersectType intersectionType = polygonLine.intersects(line, &point); +#endif + if (intersectionType == QLineF::BoundedIntersection) { + qreal dist = QLineF(point, nearestPoint <= 0 ? line.p1() : line.p2()).length(); + if (!found || dist < mindist) { + mindist = dist; + ipolygon = p; + ipoint = point; + iline = polygonLine; + found = true; + } + } } } - return false; + if (found) { + if (intersectionPolygon) + *intersectionPolygon = ipolygon; + if (intersectionPoint) + *intersectionPoint = ipoint; + if (intersectionLine) + *intersectionLine = iline; + } + return found; } + namespace { class Candidate diff --git a/src/libs/modelinglib/qmt/infrastructure/geometryutilities.h b/src/libs/modelinglib/qmt/infrastructure/geometryutilities.h index f0b4f697b0..6f39352f3f 100644 --- a/src/libs/modelinglib/qmt/infrastructure/geometryutilities.h +++ b/src/libs/modelinglib/qmt/infrastructure/geometryutilities.h @@ -52,7 +52,11 @@ public: static QLineF stretch(const QLineF &line, double p1Extension, double p2Extension); static bool intersect(const QPolygonF &polygon, const QLineF &line, - QPointF *intersectionPoint, QLineF *intersectionLine = nullptr); + QPointF *intersectionPoint = nullptr, QLineF *intersectionLine = nullptr, + int nearestPoint = 1); + static bool intersect(const QList<QPolygonF> &polygons, const QLineF &line, + int *intersectionPolygon, QPointF *intersectionPoint = nullptr, QLineF *intersectionLine = nullptr, + int nearestPoint = 1); static bool placeRectAtLine(const QRectF &rect, const QLineF &line, double lineOffset, double distance, const QLineF &intersectionLine, QPointF *placement, Side *horizontalAlignedSide); diff --git a/src/libs/modelinglib/qmt/stereotype/iconshape.cpp b/src/libs/modelinglib/qmt/stereotype/iconshape.cpp index 172bb36984..fc8e076ac8 100644 --- a/src/libs/modelinglib/qmt/stereotype/iconshape.cpp +++ b/src/libs/modelinglib/qmt/stereotype/iconshape.cpp @@ -107,6 +107,11 @@ IconShape &IconShape::operator=(const IconShape &rhs) return *this; } +bool IconShape::isEmpty() const +{ + return d->m_shapes.isEmpty(); +} + void IconShape::addLine(const ShapePointF &pos1, const ShapePointF &pos2) { d->m_shapes.append(new LineShape(pos1, pos2)); diff --git a/src/libs/modelinglib/qmt/stereotype/iconshape.h b/src/libs/modelinglib/qmt/stereotype/iconshape.h index 215dc8adec..87880f2c5c 100644 --- a/src/libs/modelinglib/qmt/stereotype/iconshape.h +++ b/src/libs/modelinglib/qmt/stereotype/iconshape.h @@ -46,6 +46,7 @@ public: IconShape &operator=(const IconShape &rhs); + bool isEmpty() const; QSizeF size() const; void setSize(const QSizeF &size); diff --git a/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.cpp b/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.cpp index 930f8450ad..13ce2b1317 100644 --- a/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.cpp +++ b/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.cpp @@ -263,4 +263,152 @@ void ShapeSizeVisitor::visitPath(const PathShape *shapePath) m_boundingRect |= path.boundingRect(); } +ShapePolygonVisitor::ShapePolygonVisitor(const QPointF &scaledOrigin, const QSizeF &originalSize, + const QSizeF &baseSize, const QSizeF &size) + : m_scaledOrigin(scaledOrigin), + m_originalSize(originalSize), + m_baseSize(baseSize), + m_size(size) +{ + m_path.setFillRule(Qt::WindingFill); +} + +QList<QPolygonF> ShapePolygonVisitor::toPolygons() const +{ + return m_path.toSubpathPolygons(); +} + +void ShapePolygonVisitor::visitLine(const LineShape *shapeLine) +{ + QPointF p1 = shapeLine->pos1().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size); + QPointF p2 = shapeLine->pos2().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size); + m_path.moveTo(p1); + m_path.lineTo(p2); +} + +void ShapePolygonVisitor::visitRect(const RectShape *shapeRect) +{ + m_path.addRect(QRectF(shapeRect->pos().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size), + shapeRect->size().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size))); +} + +void ShapePolygonVisitor::visitRoundedRect(const RoundedRectShape *shapeRoundedRect) +{ + qreal radiusX = shapeRoundedRect->radius().mapScaledTo(0, m_originalSize.width(), + m_baseSize.width(), m_size.width()); + qreal radiusY = shapeRoundedRect->radius().mapScaledTo(0, m_originalSize.height(), + m_baseSize.height(), m_size.height()); + m_path.addRoundedRect(QRectF(shapeRoundedRect->pos().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size), + shapeRoundedRect->size().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size)), + radiusX, radiusY); +} + +void ShapePolygonVisitor::visitCircle(const CircleShape *shapeCircle) +{ + m_path.addEllipse(shapeCircle->center().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size), + shapeCircle->radius().mapScaledTo(m_scaledOrigin.x(), m_originalSize.width(), + m_baseSize.width(), m_size.width()), + shapeCircle->radius().mapScaledTo(m_scaledOrigin.y(), m_originalSize.height(), + m_baseSize.height(), m_size.height())); +} + +void ShapePolygonVisitor::visitEllipse(const EllipseShape *shapeEllipse) +{ + QSizeF radius = shapeEllipse->radius().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size); + m_path.addEllipse(shapeEllipse->center().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size), + radius.width(), radius.height()); +} + +void ShapePolygonVisitor::visitDiamond(const DiamondShape *shapeDiamond) +{ + QPainterPath path; + QPointF center = shapeDiamond->center().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size); + QSizeF size = shapeDiamond->size().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size); + path.moveTo(center + QPointF(0.0, size.height() / 2.0)); + path.lineTo(center + QPointF(-size.width() / 2.0, 0.0)); + path.lineTo(center + QPointF(0.0, -size.height() / 2.0)); + path.lineTo(center + QPointF(size.width() / 2.0, 0.0)); + path.closeSubpath(); + m_path.addPath(path); +} + +void ShapePolygonVisitor::visitTriangle(const TriangleShape *shapeTriangle) +{ + QPainterPath path; + QPointF center = shapeTriangle->center().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size); + QSizeF size = shapeTriangle->size().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size); + path.moveTo(center + QPointF(size.width() / 2.0, size.height() / 2.0)); + path.lineTo(center + QPointF(-size.width() / 2.0, size.height() / 2.0)); + path.lineTo(center + QPointF(0.0, -size.height() / 2.0)); + path.closeSubpath(); + m_path.addPath(path); +} + +void ShapePolygonVisitor::visitArc(const ArcShape *shapeArc) +{ + QSizeF radius = shapeArc->radius().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size); + QRectF rect(shapeArc->center().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size) + - QPointF(radius.width(), radius.height()), radius * 2.0); + m_path.arcMoveTo(rect, shapeArc->startAngle()); + m_path.arcTo(rect, shapeArc->startAngle(), shapeArc->spanAngle()); +} + +void ShapePolygonVisitor::visitPath(const PathShape *shapePath) +{ + QPainterPath path; + for (const PathShape::Element &element: shapePath->elements()) { + switch (element.m_elementType) { + case PathShape::TypeNone: + // nothing to do + break; + case PathShape::TypeMoveto: + path.moveTo(element.m_position.mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size)); + break; + case PathShape::TypeLineto: + path.lineTo(element.m_position.mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size)); + break; + case PathShape::TypeArcmoveto: + { + QSizeF radius = element.m_size.mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size); + path.arcMoveTo(QRectF(element.m_position.mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size) + - QPointF(radius.width(), radius.height()), + radius * 2.0), + element.m_angle1); + break; + } + case PathShape::TypeArcto: + { + QSizeF radius = element.m_size.mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size); + path.arcTo(QRectF(element.m_position.mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size) + - QPointF(radius.width(), radius.height()), + radius * 2.0), + element.m_angle1, element.m_angle2); + break; + } + case PathShape::TypeClose: + path.closeSubpath(); + break; + } + } + m_path.addPath(path); +} + } // namespace qmt diff --git a/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.h b/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.h index 92e340e3e9..8ad4074764 100644 --- a/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.h +++ b/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.h @@ -31,6 +31,8 @@ #include <QPainter> #include <QPointF> #include <QSizeF> +#include <QPolygonF> +#include <QPainterPath> namespace qmt { @@ -84,4 +86,31 @@ private: QRectF m_boundingRect; }; +class QMT_EXPORT ShapePolygonVisitor : public ShapeConstVisitor +{ +public: + ShapePolygonVisitor(const QPointF &scaledOrigin, const QSizeF &originalSize, + const QSizeF &baseSize, const QSizeF &size); + + QPainterPath path() const { return m_path; } + QList<QPolygonF> toPolygons() const; + + void visitLine(const LineShape *shapeLine) override; + void visitRect(const RectShape *shapeRect) override; + void visitRoundedRect(const RoundedRectShape *shapeRoundedRect) override; + void visitCircle(const CircleShape *shapeCircle) override; + void visitEllipse(const EllipseShape *shapeEllipse) override; + void visitDiamond(const DiamondShape *shapeDiamond) override; + void visitTriangle(const TriangleShape *shapeTriangle) override; + void visitArc(const ArcShape *shapeArc) override; + void visitPath(const PathShape *shapePath) override; + +private: + QPointF m_scaledOrigin; + QSizeF m_originalSize; + QSizeF m_baseSize; + QSizeF m_size; + QPainterPath m_path; +}; + } // namespace qmt diff --git a/src/libs/modelinglib/qmt/stereotype/stereotypeicon.cpp b/src/libs/modelinglib/qmt/stereotype/stereotypeicon.cpp index d11cace46b..f9610851f3 100644 --- a/src/libs/modelinglib/qmt/stereotype/stereotypeicon.cpp +++ b/src/libs/modelinglib/qmt/stereotype/stereotypeicon.cpp @@ -109,4 +109,9 @@ void StereotypeIcon::setIconShape(const IconShape &iconShape) m_iconShape = iconShape; } +void StereotypeIcon::setOutlineShape(const IconShape &outlineShape) +{ + m_outlineShape = outlineShape; +} + } // namespace qmt diff --git a/src/libs/modelinglib/qmt/stereotype/stereotypeicon.h b/src/libs/modelinglib/qmt/stereotype/stereotypeicon.h index 4465734cfd..ab837bd333 100644 --- a/src/libs/modelinglib/qmt/stereotype/stereotypeicon.h +++ b/src/libs/modelinglib/qmt/stereotype/stereotypeicon.h @@ -100,6 +100,8 @@ public: void setBaseColor(const QColor &baseColor); IconShape iconShape() const { return m_iconShape; } void setIconShape(const IconShape &iconShape); + IconShape outlineShape() const { return m_outlineShape; } + void setOutlineShape(const IconShape &outlineShape); private: QString m_id; @@ -117,6 +119,7 @@ private: TextAlignment m_textAlignment = TextalignBelow; QColor m_baseColor; IconShape m_iconShape; + IconShape m_outlineShape; }; } // namespace qmt diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt index ff7bbe6286..8792967118 100644 --- a/src/libs/utils/CMakeLists.txt +++ b/src/libs/utils/CMakeLists.txt @@ -96,6 +96,7 @@ add_qtc_library(Utils osspecificaspects.h outputformat.h outputformatter.cpp outputformatter.h + overlaywidget.cpp overlaywidget.h overridecursor.cpp overridecursor.h parameteraction.cpp parameteraction.h pathchooser.cpp pathchooser.h diff --git a/src/libs/utils/filewizardpage.cpp b/src/libs/utils/filewizardpage.cpp index cd9f3b345b..f486229253 100644 --- a/src/libs/utils/filewizardpage.cpp +++ b/src/libs/utils/filewizardpage.cpp @@ -110,6 +110,19 @@ void FileWizardPage::setPathLabel(const QString &label) d->m_ui.pathLabel->setText(label); } +void FileWizardPage::setDefaultSuffix(const QString &suffix) +{ + if (suffix.isEmpty()) { + const auto layout = qobject_cast<QFormLayout *>(this->layout()); + if (layout->rowCount() == 3) + layout->removeRow(0); + } else { + d->m_ui.defaultSuffixLabel->setText( + tr("The default suffix if you do not explicitly specify a file extension is \".%1\".") + .arg(suffix)); + } +} + bool FileWizardPage::forceFirstCapitalLetterForFileName() const { return d->m_ui.nameLineEdit->forceFirstCapitalLetter(); diff --git a/src/libs/utils/filewizardpage.h b/src/libs/utils/filewizardpage.h index ede6c4d3ab..0ce3287bef 100644 --- a/src/libs/utils/filewizardpage.h +++ b/src/libs/utils/filewizardpage.h @@ -50,6 +50,7 @@ public: void setFileNameLabel(const QString &label); void setPathLabel(const QString &label); + void setDefaultSuffix(const QString &suffix); bool forceFirstCapitalLetterForFileName() const; void setForceFirstCapitalLetterForFileName(bool b); diff --git a/src/libs/utils/filewizardpage.ui b/src/libs/utils/filewizardpage.ui index e8b3ca1b4b..9d3f09abe4 100644 --- a/src/libs/utils/filewizardpage.ui +++ b/src/libs/utils/filewizardpage.ui @@ -6,34 +6,41 @@ <rect> <x>0</x> <y>0</y> - <width>196</width> - <height>68</height> + <width>368</width> + <height>102</height> </rect> </property> <property name="title"> <string>Choose the Location</string> </property> <layout class="QFormLayout" name="formLayout"> - <item row="0" column="0"> + <item row="1" column="0"> <widget class="QLabel" name="nameLabel"> <property name="text"> - <string>Name:</string> + <string>File name:</string> </property> </widget> </item> - <item row="0" column="1"> + <item row="1" column="1"> <widget class="Utils::FileNameValidatingLineEdit" name="nameLineEdit"/> </item> - <item row="1" column="0"> + <item row="3" column="0"> <widget class="QLabel" name="pathLabel"> <property name="text"> <string>Path:</string> </property> </widget> </item> - <item row="1" column="1"> + <item row="3" column="1"> <widget class="Utils::PathChooser" name="pathChooser" native="true"/> </item> + <item row="0" column="1"> + <widget class="QLabel" name="defaultSuffixLabel"> + <property name="text"> + <string/> + </property> + </widget> + </item> </layout> </widget> <customwidgets> diff --git a/src/libs/utils/outputformat.h b/src/libs/utils/outputformat.h index 12b14d5b80..1e959d05d4 100644 --- a/src/libs/utils/outputformat.h +++ b/src/libs/utils/outputformat.h @@ -35,8 +35,6 @@ enum OutputFormat DebugFormat, StdOutFormat, StdErrFormat, - StdOutFormatSameLine, - StdErrFormatSameLine, NumberOfFormats // Keep this entry last. }; diff --git a/src/libs/utils/outputformatter.cpp b/src/libs/utils/outputformatter.cpp index ad077755ca..9c3cee4879 100644 --- a/src/libs/utils/outputformatter.cpp +++ b/src/libs/utils/outputformatter.cpp @@ -25,6 +25,7 @@ #include "ansiescapecodehandler.h" #include "outputformatter.h" +#include "synchronousprocess.h" #include "theme/theme.h" #include <QPlainTextEdit> @@ -42,6 +43,7 @@ public: QTextCursor cursor; AnsiEscapeCodeHandler escapeCodeHandler; bool boldFontEnabled = true; + bool prependCarriageReturn = false; }; } // namespace Internal @@ -69,14 +71,14 @@ void OutputFormatter::setPlainTextEdit(QPlainTextEdit *plainText) initFormats(); } -void OutputFormatter::appendMessage(const QString &text, OutputFormat format) +void OutputFormatter::doAppendMessage(const QString &text, OutputFormat format) { if (!d->cursor.atEnd() && text.startsWith('\n')) d->cursor.movePosition(QTextCursor::End); - appendMessage(text, d->formats[format]); + doAppendMessage(text, d->formats[format]); } -void OutputFormatter::appendMessage(const QString &text, const QTextCharFormat &format) +void OutputFormatter::doAppendMessage(const QString &text, const QTextCharFormat &format) { const QList<FormattedText> formattedTextList = parseAnsi(text, format); for (const FormattedText &output : formattedTextList) @@ -95,21 +97,13 @@ QList<FormattedText> OutputFormatter::parseAnsi(const QString &text, const QText void OutputFormatter::append(const QString &text, const QTextCharFormat &format) { - int startPos = 0; - int crPos = -1; - while ((crPos = text.indexOf('\r', startPos)) >= 0) { - if (text.size() > crPos + 1 && text.at(crPos + 1) == '\n') { - d->cursor.insertText(text.mid(startPos, crPos - startPos) + '\n', format); - startPos = crPos + 2; - continue; - } - d->cursor.insertText(text.mid(startPos, crPos - startPos), format); - d->cursor.clearSelection(); - d->cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor); - startPos = crPos + 1; - } - if (startPos < text.count()) - d->cursor.insertText(text.mid(startPos), format); + if (!text.isEmpty()) + d->cursor.insertText(text, format); +} + +QTextCursor &OutputFormatter::cursor() const +{ + return d->cursor; } QTextCharFormat OutputFormatter::linkFormat(const QTextCharFormat &inputFormat, const QString &href) @@ -136,26 +130,12 @@ void OutputFormatter::initFormats() return; Theme *theme = creatorTheme(); - - // NormalMessageFormat d->formats[NormalMessageFormat].setForeground(theme->color(Theme::OutputPanes_NormalMessageTextColor)); - - // ErrorMessageFormat d->formats[ErrorMessageFormat].setForeground(theme->color(Theme::OutputPanes_ErrorMessageTextColor)); - - // LogMessageFormat d->formats[LogMessageFormat].setForeground(theme->color(Theme::OutputPanes_WarningMessageTextColor)); - - // StdOutFormat d->formats[StdOutFormat].setForeground(theme->color(Theme::OutputPanes_StdOutTextColor)); - d->formats[StdOutFormatSameLine] = d->formats[StdOutFormat]; - - // StdErrFormat d->formats[StdErrFormat].setForeground(theme->color(Theme::OutputPanes_StdErrTextColor)); - d->formats[StdErrFormatSameLine] = d->formats[StdErrFormat]; - d->formats[DebugFormat].setForeground(theme->color(Theme::OutputPanes_DebugTextColor)); - setBoldFontEnabled(d->boldFontEnabled); } @@ -164,6 +144,12 @@ void OutputFormatter::handleLink(const QString &href) Q_UNUSED(href) } +void OutputFormatter::clear() +{ + d->prependCarriageReturn = false; + plainTextEdit()->clear(); +} + void OutputFormatter::setBoldFontEnabled(bool enabled) { d->boldFontEnabled = enabled; @@ -177,4 +163,19 @@ void OutputFormatter::flush() d->escapeCodeHandler.endFormatScope(); } +void OutputFormatter::appendMessage(const QString &text, OutputFormat format) +{ + QString out = text; + if (d->prependCarriageReturn) { + d->prependCarriageReturn = false; + out.prepend('\r'); + } + out = SynchronousProcess::normalizeNewlines(out); + if (out.endsWith('\r')) { + d->prependCarriageReturn = true; + out.chop(1); + } + doAppendMessage(out, format); +} + } // namespace Utils diff --git a/src/libs/utils/outputformatter.h b/src/libs/utils/outputformatter.h index 5b7acb0337..626e073e50 100644 --- a/src/libs/utils/outputformatter.h +++ b/src/libs/utils/outputformatter.h @@ -29,7 +29,6 @@ #include "outputformat.h" #include <QObject> -#include <QFont> QT_BEGIN_NAMESPACE class QPlainTextEdit; @@ -45,36 +44,34 @@ namespace Internal { class OutputFormatterPrivate; } class QTCREATOR_UTILS_EXPORT OutputFormatter : public QObject { - Q_OBJECT - public: OutputFormatter(); ~OutputFormatter() override; QPlainTextEdit *plainTextEdit() const; - virtual void setPlainTextEdit(QPlainTextEdit *plainText); + void setPlainTextEdit(QPlainTextEdit *plainText); void flush(); - virtual void appendMessage(const QString &text, OutputFormat format); + void appendMessage(const QString &text, OutputFormat format); + virtual void handleLink(const QString &href); - virtual QList<QWidget *> toolbarWidgets() const { return {}; } - virtual void clear() {} + void clear(); void setBoldFontEnabled(bool enabled); static QTextCharFormat linkFormat(const QTextCharFormat &inputFormat, const QString &href); -signals: - void contentChanged(); - protected: - void initFormats(); virtual void clearLastLine(); QTextCharFormat charFormat(OutputFormat format) const; QList<FormattedText> parseAnsi(const QString &text, const QTextCharFormat &format); - void append(const QString &text, const QTextCharFormat &format); + virtual void doAppendMessage(const QString &text, OutputFormat format); + QTextCursor &cursor() const; private: - virtual void appendMessage(const QString &text, const QTextCharFormat &format); + virtual void doAppendMessage(const QString &text, const QTextCharFormat &format); + void append(const QString &text, const QTextCharFormat &format); + void initFormats(); + Internal::OutputFormatterPrivate *d; }; diff --git a/src/plugins/boot2qt/qdbdeploystepfactory.cpp b/src/libs/utils/overlaywidget.cpp index a39b3e5b86..d1a5f6e3d3 100644 --- a/src/plugins/boot2qt/qdbdeploystepfactory.cpp +++ b/src/libs/utils/overlaywidget.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -23,34 +23,54 @@ ** ****************************************************************************/ -#include "qdbdeploystepfactory.h" +#include "overlaywidget.h" -#include "qdbconstants.h" -#include "qdbmakedefaultappstep.h" -#include "qdbstopapplicationstep.h" +#include "qtcassert.h" -#include <projectexplorer/buildsteplist.h> -#include <projectexplorer/projectexplorerconstants.h> -#include <projectexplorer/target.h> +#include <QEvent> +#include <QPainter> -namespace Qdb { -namespace Internal { +Utils::OverlayWidget::OverlayWidget(QWidget *parent) +{ + setAttribute(Qt::WA_TransparentForMouseEvents); + if (parent) + attachToWidget(parent); +} + +void Utils::OverlayWidget::setPaintFunction(const Utils::OverlayWidget::PaintFunction &paint) +{ + m_paint = paint; +} -QdbMakeDefaultAppStepFactory::QdbMakeDefaultAppStepFactory() +bool Utils::OverlayWidget::eventFilter(QObject *obj, QEvent *ev) { - registerStep<QdbMakeDefaultAppStep>(QdbMakeDefaultAppStep::stepId()); - setDisplayName(QdbMakeDefaultAppStep::stepDisplayName()); - setSupportedDeviceType(Constants::QdbLinuxOsType); - setSupportedStepList(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY); + if (obj == parent() && ev->type() == QEvent::Resize) + resizeToParent(); + return QWidget::eventFilter(obj, ev); } -QdbStopApplicationStepFactory::QdbStopApplicationStepFactory() +void Utils::OverlayWidget::paintEvent(QPaintEvent *ev) { - registerStep<QdbStopApplicationStep>(QdbStopApplicationStep::stepId()); - setDisplayName(QdbStopApplicationStep::stepDisplayName()); - setSupportedDeviceType(Constants::QdbLinuxOsType); - setSupportedStepList(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY); + if (m_paint) { + QPainter p(this); + m_paint(this, p, ev); + } } -} // namespace Internal -} // namespace Qdb +void Utils::OverlayWidget::attachToWidget(QWidget *parent) +{ + if (parentWidget()) + parentWidget()->removeEventFilter(this); + setParent(parent); + if (parent) { + parent->installEventFilter(this); + resizeToParent(); + raise(); + } +} + +void Utils::OverlayWidget::resizeToParent() +{ + QTC_ASSERT(parentWidget(), return ); + setGeometry(QRect(QPoint(0, 0), parentWidget()->size())); +} diff --git a/src/plugins/projectexplorer/buildenvironmentwidget.h b/src/libs/utils/overlaywidget.h index 7c45bd8f89..3470166c73 100644 --- a/src/plugins/projectexplorer/buildenvironmentwidget.h +++ b/src/libs/utils/overlaywidget.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -25,32 +25,33 @@ #pragma once -#include <projectexplorer/namedwidget.h> +#include "utils_global.h" -QT_BEGIN_NAMESPACE -class QCheckBox; -QT_END_NAMESPACE +#include <QWidget> -namespace ProjectExplorer { +#include <functional> -class EnvironmentWidget; -class BuildConfiguration; +namespace Utils { -class PROJECTEXPLORER_EXPORT BuildEnvironmentWidget : public NamedWidget +class QTCREATOR_UTILS_EXPORT OverlayWidget : public QWidget { Q_OBJECT - public: - explicit BuildEnvironmentWidget(BuildConfiguration *bc); + using PaintFunction = std::function<void(QWidget *, QPainter &, QPaintEvent *)>; + + explicit OverlayWidget(QWidget *parent = nullptr); + + void attachToWidget(QWidget *parent); + void setPaintFunction(const PaintFunction &paint); + +protected: + bool eventFilter(QObject *obj, QEvent *ev) override; + void paintEvent(QPaintEvent *ev) override; private: - void environmentModelUserChangesChanged(); - void clearSystemEnvironmentCheckBoxClicked(bool checked); - void environmentChanged(); + void resizeToParent(); - EnvironmentWidget *m_buildEnvironmentWidget; - QCheckBox *m_clearSystemEnvironmentCheckBox; - BuildConfiguration *m_buildConfiguration; + PaintFunction m_paint; }; -} // namespace ProjectExplorer +} // namespace Utils diff --git a/src/libs/utils/progressindicator.cpp b/src/libs/utils/progressindicator.cpp index dc2d8bb626..7bc016f8ee 100644 --- a/src/libs/utils/progressindicator.cpp +++ b/src/libs/utils/progressindicator.cpp @@ -220,9 +220,11 @@ void ProgressIndicatorPainter::nextAnimationStep() \sa setIndicatorSize */ ProgressIndicator::ProgressIndicator(ProgressIndicatorSize size, QWidget *parent) - : QWidget(parent), m_paint(size) + : OverlayWidget(parent) + , m_paint(size) { - setAttribute(Qt::WA_TransparentForMouseEvents); + setPaintFunction( + [this](QWidget *w, QPainter &p, QPaintEvent *) { m_paint.paint(p, w->rect()); }); m_paint.setUpdateCallback([this]() { update(); }); updateGeometry(); } @@ -249,29 +251,6 @@ QSize ProgressIndicator::sizeHint() const } /*! - Makes the indicator a child of \a parent, automatically centering on it, - and adapting to size changes. -*/ -void ProgressIndicator::attachToWidget(QWidget *parent) -{ - if (parentWidget()) - parentWidget()->removeEventFilter(this); - setParent(parent); - parent->installEventFilter(this); - resizeToParent(); - raise(); -} - -/*! - \internal -*/ -void ProgressIndicator::paintEvent(QPaintEvent *) -{ - QPainter p(this); - m_paint.paint(p, rect()); -} - -/*! \internal */ void ProgressIndicator::showEvent(QShowEvent *) @@ -287,24 +266,4 @@ void ProgressIndicator::hideEvent(QHideEvent *) m_paint.stopAnimation(); } -/*! - \internal -*/ -bool ProgressIndicator::eventFilter(QObject *obj, QEvent *ev) -{ - if (obj == parent() && ev->type() == QEvent::Resize) { - resizeToParent(); - } - return QWidget::eventFilter(obj, ev); -} - -/*! - \internal -*/ -void ProgressIndicator::resizeToParent() -{ - QTC_ASSERT(parentWidget(), return); - setGeometry(QRect(QPoint(0, 0), parentWidget()->size())); -} - } // namespace Utils diff --git a/src/libs/utils/progressindicator.h b/src/libs/utils/progressindicator.h index 6713709c1b..0d13cf8952 100644 --- a/src/libs/utils/progressindicator.h +++ b/src/libs/utils/progressindicator.h @@ -25,6 +25,7 @@ #pragma once +#include "overlaywidget.h" #include "utils_global.h" #include <QTimer> @@ -76,7 +77,7 @@ private: UpdateCallback m_callback; }; -class QTCREATOR_UTILS_EXPORT ProgressIndicator : public QWidget +class QTCREATOR_UTILS_EXPORT ProgressIndicator : public OverlayWidget { Q_OBJECT public: @@ -86,17 +87,11 @@ public: QSize sizeHint() const final; - void attachToWidget(QWidget *parent); - protected: - void paintEvent(QPaintEvent *) final; void showEvent(QShowEvent *) final; void hideEvent(QHideEvent *) final; - bool eventFilter(QObject *obj, QEvent *ev) final; private: - void resizeToParent(); - ProgressIndicatorPainter m_paint; }; diff --git a/src/libs/utils/touchbar/touchbar_appdelegate_mac.mm b/src/libs/utils/touchbar/touchbar_appdelegate_mac.mm index e921695fdc..128679dfb7 100644 --- a/src/libs/utils/touchbar/touchbar_appdelegate_mac.mm +++ b/src/libs/utils/touchbar/touchbar_appdelegate_mac.mm @@ -29,6 +29,7 @@ #include <stack> #import <AppKit/NSTouchBar.h> +#import <AppKit/NSWindow.h> Q_GLOBAL_STATIC(Utils::Internal::ApplicationDelegate, staticApplicationDelegate); @@ -148,4 +149,11 @@ using namespace Utils::Internal; [anInvocation invokeWithTarget:self.qtDelegate]; } +// Work around QTBUG-61707 +- (void)applicationWillFinishLaunching:(NSNotification*)notify +{ + Q_UNUSED(notify) + [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSFullScreenMenuItemEverywhere"]; + NSWindow.allowsAutomaticWindowTabbing = NO; +} @end diff --git a/src/libs/utils/touchbar/touchbar_appdelegate_mac_p.h b/src/libs/utils/touchbar/touchbar_appdelegate_mac_p.h index da2f8e4e07..e97e49691d 100644 --- a/src/libs/utils/touchbar/touchbar_appdelegate_mac_p.h +++ b/src/libs/utils/touchbar/touchbar_appdelegate_mac_p.h @@ -37,6 +37,7 @@ - (void)setApplicationTouchBar:(Utils::Internal::TouchBarPrivate *)bar; - (void)pushTouchBar:(Utils::Internal::TouchBarPrivate *)bar; - (void)popTouchBar; +- (void)applicationWillFinishLaunching:(NSNotification*)notify; @end diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri index 55dd718a72..69db3b63a0 100644 --- a/src/libs/utils/utils-lib.pri +++ b/src/libs/utils/utils-lib.pri @@ -132,7 +132,8 @@ SOURCES += \ $$PWD/jsontreeitem.cpp \ $$PWD/namevaluevalidator.cpp \ $$PWD/camelcasecursor.cpp \ - $$PWD/infolabel.cpp + $$PWD/infolabel.cpp \ + $$PWD/overlaywidget.cpp HEADERS += \ $$PWD/environmentfwd.h \ @@ -279,7 +280,8 @@ HEADERS += \ $$PWD/listmodel.h \ $$PWD/namevaluevalidator.h \ $$PWD/camelcasecursor.h \ - $$PWD/infolabel.h + $$PWD/infolabel.h \ + $$PWD/overlaywidget.h FORMS += $$PWD/filewizardpage.ui \ $$PWD/projectintropage.ui \ diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index ed15c78d8e..2c1b098c9e 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -176,6 +176,8 @@ Project { "outputformat.h", "outputformatter.cpp", "outputformatter.h", + "overlaywidget.cpp", + "overlaywidget.h", "overridecursor.cpp", "overridecursor.h", "parameteraction.cpp", diff --git a/src/plugins/android/CMakeLists.txt b/src/plugins/android/CMakeLists.txt index 0f2eb17d7b..e672527ea6 100644 --- a/src/plugins/android/CMakeLists.txt +++ b/src/plugins/android/CMakeLists.txt @@ -24,6 +24,8 @@ add_qtc_plugin(Android androidmanifesteditor.cpp androidmanifesteditor.h androidmanifesteditorfactory.cpp androidmanifesteditorfactory.h androidmanifesteditorwidget.cpp androidmanifesteditorwidget.h + androidmanifesteditoriconwidget.cpp androidmanifesteditoriconwidget.h + androidmanifesteditoriconcontainerwidget.cpp androidmanifesteditoriconcontainerwidget.h androidpackageinstallationstep.cpp androidpackageinstallationstep.h androidplugin.cpp androidplugin.h androidpotentialkit.cpp androidpotentialkit.h diff --git a/src/plugins/android/android.pro b/src/plugins/android/android.pro index f3745d18c0..dd62a79bcd 100644 --- a/src/plugins/android/android.pro +++ b/src/plugins/android/android.pro @@ -9,6 +9,8 @@ HEADERS += \ androidconstants.h \ androidconfigurations.h \ androidmanager.h \ + androidmanifesteditoriconcontainerwidget.h \ + androidmanifesteditoriconwidget.h \ androidrunconfiguration.h \ androidruncontrol.h \ androidsettingswidget.h \ @@ -54,6 +56,8 @@ HEADERS += \ SOURCES += \ androidconfigurations.cpp \ androidmanager.cpp \ + androidmanifesteditoriconcontainerwidget.cpp \ + androidmanifesteditoriconwidget.cpp \ androidrunconfiguration.cpp \ androidruncontrol.cpp \ androidsettingswidget.cpp \ diff --git a/src/plugins/android/android.qbs b/src/plugins/android/android.qbs index 0162ed096d..0710d851fe 100644 --- a/src/plugins/android/android.qbs +++ b/src/plugins/android/android.qbs @@ -56,6 +56,10 @@ Project { "androidmanifestdocument.h", "androidmanifesteditor.cpp", "androidmanifesteditor.h", + "androidmanifesteditoriconwidget.cpp", + "androidmanifesteditoriconwidget.h", + "androidmanifesteditoriconcontainerwidget.cpp", + "androidmanifesteditoriconcontainerwidget.h", "androidmanifesteditorfactory.cpp", "androidmanifesteditorfactory.h", "androidmanifesteditorwidget.cpp", diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp index 5f31ca8620..e13eafd4cb 100644 --- a/src/plugins/android/androidbuildapkstep.cpp +++ b/src/plugins/android/androidbuildapkstep.cpp @@ -65,6 +65,7 @@ #include <QMessageBox> #include <QProcess> #include <QPushButton> +#include <QTimer> #include <QVBoxLayout> #include <memory> @@ -86,13 +87,13 @@ const char VerboseOutputKey[] = "VerboseOutput"; const char UseMinistroKey[] = "UseMinistro"; static void setupProcessParameters(ProcessParameters *pp, - BuildConfiguration *bc, + BuildStep *step, const QStringList &arguments, const QString &command) { - pp->setMacroExpander(bc->macroExpander()); - pp->setWorkingDirectory(bc->buildDirectory()); - Utils::Environment env = bc->environment(); + pp->setMacroExpander(step->macroExpander()); + pp->setWorkingDirectory(step->buildDirectory()); + Utils::Environment env = step->buildEnvironment(); pp->setEnvironment(env); pp->setCommandLine({command, arguments}); } @@ -124,22 +125,6 @@ private: this); }; -static FilePath aabPath(const BuildConfiguration *bc) -{ - if (!bc) - return {}; - - QString buildType; - if (bc->buildType() == BuildConfiguration::Release) - buildType = "release"; - else - buildType = "debug"; - - return bc->buildDirectory() - .pathAppended(Constants::ANDROID_BUILDDIRECTORY) - .pathAppended(QString("build/outputs/bundle/%1/android-build-%1.aab").arg(buildType)); -} - AndroidBuildApkStep::AndroidBuildApkStep(BuildStepList *parent, Core::Id id) : AbstractProcessStep(parent, id), m_buildTargetSdk(AndroidConfig::apiLevelNameFor(AndroidConfigurations:: @@ -152,8 +137,6 @@ AndroidBuildApkStep::AndroidBuildApkStep(BuildStepList *parent, Core::Id id) bool AndroidBuildApkStep::init() { - ProjectExplorer::BuildConfiguration *bc = buildConfiguration(); - if (m_signPackage) { qCDebug(buildapkstepLog) << "Signing enabled"; // check keystore and certificate passwords @@ -162,7 +145,7 @@ bool AndroidBuildApkStep::init() return false; } - if (bc->buildType() != ProjectExplorer::BuildConfiguration::Release) + if (buildType() != BuildConfiguration::Release) emit addOutput(tr("Warning: Signing a debug or profile package."), OutputFormat::ErrorMessage); } @@ -208,12 +191,21 @@ bool AndroidBuildApkStep::init() QFileInfo sourceDirInfo(sourceDirName); parser->setSourceDirectory(Utils::FilePath::fromString(sourceDirInfo.canonicalFilePath())); - parser->setBuildDirectory(bc->buildDirectory().pathAppended(Constants::ANDROID_BUILDDIRECTORY)); + parser->setBuildDirectory(buildDirectory().pathAppended(Constants::ANDROID_BUILDDIRECTORY)); setOutputParser(parser); m_openPackageLocationForRun = m_openPackageLocation; - m_packagePath = m_buildAAB ? aabPath(buildConfiguration()).toString() - : AndroidManager::apkPath(target()).toString(); + + if (m_buildAAB) { + const QString bt = buildType() == BuildConfiguration::Release ? QLatin1String("release") + : QLatin1String("debug"); + m_packagePath = buildDirectory() + .pathAppended(Constants::ANDROID_BUILDDIRECTORY) + .pathAppended(QString("build/outputs/bundle/%1/android-build-%1.aab").arg(bt)).toString(); + } else { + m_packagePath = AndroidManager::apkPath(target()).toString(); + } + qCDebug(buildapkstepLog) << "Package path:" << m_packagePath; if (!AbstractProcessStep::init()) @@ -224,7 +216,7 @@ bool AndroidBuildApkStep::init() command += '/'; command += Utils::HostOsInfo::withExecutableSuffix("androiddeployqt"); - QString outputDir = bc->buildDirectory().pathAppended(Constants::ANDROID_BUILDDIRECTORY).toString(); + QString outputDir = buildDirectory().pathAppended(Constants::ANDROID_BUILDDIRECTORY).toString(); if (node) m_inputFile = node->data(Constants::AndroidDeploySettingsFile).toString(); @@ -275,18 +267,18 @@ bool AndroidBuildApkStep::init() // Must be the last option, otherwise androiddeployqt might use the other // params (e.g. --sign) to choose not to add gdbserver if (version->qtVersion() >= QtSupport::QtVersionNumber(5, 6, 0)) { - if (m_addDebugger || bc->buildType() == ProjectExplorer::BuildConfiguration::Debug) + if (m_addDebugger || buildType() == ProjectExplorer::BuildConfiguration::Debug) arguments << "--gdbserver"; else arguments << "--no-gdbserver"; } ProjectExplorer::ProcessParameters *pp = processParameters(); - setupProcessParameters(pp, bc, arguments, command); + setupProcessParameters(pp, this, arguments, command); // Generate arguments with keystore password concealed ProjectExplorer::ProcessParameters pp2; - setupProcessParameters(&pp2, bc, argumentsPasswordConcealed, command); + setupProcessParameters(&pp2, this, argumentsPasswordConcealed, command); m_command = pp2.effectiveCommand().toString(); m_argumentsPasswordConcealed = pp2.prettyArguments(); @@ -307,7 +299,7 @@ void AndroidBuildApkStep::processFinished(int exitCode, QProcess::ExitStatus sta { AbstractProcessStep::processFinished(exitCode, status); if (m_openPackageLocationForRun && status == QProcess::NormalExit && exitCode == 0) - QMetaObject::invokeMethod(this, "showInGraphicalShell", Qt::QueuedConnection); + QTimer::singleShot(0, this, &AndroidBuildApkStep::showInGraphicalShell); } bool AndroidBuildApkStep::verifyKeystorePassword() @@ -383,13 +375,12 @@ void AndroidBuildApkStep::doRun() } auto setup = [this] { - auto bc = buildConfiguration(); const auto androidAbis = AndroidManager::applicationAbis(target()); for (const auto &abi : androidAbis) { - Utils::FilePath androidLibsDir = bc->buildDirectory() + Utils::FilePath androidLibsDir = buildDirectory() .pathAppended("android-build/libs") .pathAppended(abi); - if (!androidLibsDir.exists() && !QDir{bc->buildDirectory().toString()}.mkpath(androidLibsDir.toString())) + if (!androidLibsDir.exists() && !QDir{buildDirectory().toString()}.mkpath(androidLibsDir.toString())) return false; } @@ -418,7 +409,7 @@ void AndroidBuildApkStep::doRun() if (version->qtVersion() < QtSupport::QtVersionNumber(5, 14, 0)) { QTC_ASSERT(androidAbis.size() == 1, return false); applicationBinary = target()->activeRunConfiguration()->buildTargetInfo().targetFilePath.toString(); - Utils::FilePath androidLibsDir = bc->buildDirectory().pathAppended("android-build/libs").pathAppended(androidAbis.first()); + Utils::FilePath androidLibsDir = buildDirectory().pathAppended("android-build/libs").pathAppended(androidAbis.first()); for (const auto &target : targets) { if (!copyFileIfNewer(target, androidLibsDir.pathAppended(QFileInfo{target}.fileName()).toString())) return false; @@ -436,7 +427,7 @@ void AndroidBuildApkStep::doRun() applicationBinary.remove(0, 3).chop(targetSuffix.size()); } - Utils::FilePath androidLibsDir = bc->buildDirectory() + Utils::FilePath androidLibsDir = buildDirectory() .pathAppended("android-build/libs") .pathAppended(abi); for (const auto &target : targets) { diff --git a/src/plugins/android/androidbuildapkstep.h b/src/plugins/android/androidbuildapkstep.h index 49ef9dc94e..e60d2b7f38 100644 --- a/src/plugins/android/androidbuildapkstep.h +++ b/src/plugins/android/androidbuildapkstep.h @@ -79,7 +79,7 @@ public: QVariant data(Core::Id id) const override; private: - Q_INVOKABLE void showInGraphicalShell(); + void showInGraphicalShell(); bool init() override; ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override; diff --git a/src/plugins/android/androidbuildapkwidget.cpp b/src/plugins/android/androidbuildapkwidget.cpp index 66be50dca7..984c3049db 100644 --- a/src/plugins/android/androidbuildapkwidget.cpp +++ b/src/plugins/android/androidbuildapkwidget.cpp @@ -257,7 +257,7 @@ QWidget *AndroidBuildApkWidget::createCreateTemplatesGroup() auto createAndroidTemplatesButton = new QPushButton(tr("Create Templates")); connect(createAndroidTemplatesButton, &QAbstractButton::clicked, this, [this] { - CreateAndroidManifestWizard wizard(m_step->buildConfiguration()->buildSystem()); + CreateAndroidManifestWizard wizard(m_step->buildSystem()); wizard.exec(); }); @@ -406,7 +406,7 @@ void AndroidBuildApkWidget::setCertificates() void AndroidBuildApkWidget::updateSigningWarning() { - bool nonRelease = m_step->buildConfiguration()->buildType() != BuildConfiguration::Release; + bool nonRelease = m_step->buildType() != BuildConfiguration::Release; bool visible = m_step->signPackage() && nonRelease; m_signingDebugWarningLabel->setVisible(visible); } diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index 14cf58f2f5..84c9a3a6f0 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -1371,9 +1371,9 @@ void AndroidConfigurations::updateAutomaticKitList() if (qt != QtSupport::QtKitAspect::qtVersion(b)) return false; return matchToolChain(toolChainForLanguage[ProjectExplorer::Constants::CXX_LANGUAGE_ID], - ToolChainKitAspect::toolChain(b, ProjectExplorer::Constants::CXX_LANGUAGE_ID)) + ToolChainKitAspect::cxxToolChain(b)) && matchToolChain(toolChainForLanguage[ProjectExplorer::Constants::C_LANGUAGE_ID], - ToolChainKitAspect::toolChain(b, ProjectExplorer::Constants::C_LANGUAGE_ID)); + ToolChainKitAspect::cToolChain(b)); }); const auto initializeKit = [allLanguages, device, tc, qt](Kit *k) { diff --git a/src/plugins/android/androiddebugsupport.cpp b/src/plugins/android/androiddebugsupport.cpp index 3ffed5e7ec..fa6b4dd3ac 100644 --- a/src/plugins/android/androiddebugsupport.cpp +++ b/src/plugins/android/androiddebugsupport.cpp @@ -123,8 +123,10 @@ void AndroidDebugSupport::start() qCDebug(androidDebugSupportLog) << "Start. Package name: " << packageName << "PID: " << m_runner->pid().pid(); QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitAspect::qtVersion(kit); - if (!Utils::HostOsInfo::isWindowsHost() && - AndroidConfigurations::currentConfig().ndkVersion(qtVersion) >= QVersionNumber(11, 0, 0)) { + if (!Utils::HostOsInfo::isWindowsHost() + && (qtVersion + && AndroidConfigurations::currentConfig().ndkVersion(qtVersion) + >= QVersionNumber(11, 0, 0))) { qCDebug(androidDebugSupportLog) << "UseTargetAsync: " << true; setUseTargetAsync(true); } @@ -152,19 +154,21 @@ void AndroidDebugSupport::start() setRemoteChannel(gdbServer); auto qt = static_cast<AndroidQtVersion *>(qtVersion); - QTC_CHECK(qt); const int minimumNdk = qt ? qt->minimumNDK() : 0; int sdkVersion = qMax(AndroidManager::minimumSDK(kit), minimumNdk); // TODO find a way to use the new sysroot layout // instead ~/android/ndk-bundle/platforms/android-29/arch-arm64 // use ~/android/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot - Utils::FilePath sysRoot = AndroidConfigurations::currentConfig().ndkLocation(qtVersion) - .pathAppended("platforms") - .pathAppended(QString("android-%1").arg(sdkVersion)) - .pathAppended(devicePreferredAbi); - setSysRoot(sysRoot); - qCDebug(androidDebugSupportLog) << "Sysroot: " << sysRoot; + if (qtVersion) { + Utils::FilePath sysRoot = AndroidConfigurations::currentConfig() + .ndkLocation(qtVersion) + .pathAppended("platforms") + .pathAppended(QString("android-%1").arg(sdkVersion)) + .pathAppended(devicePreferredAbi); + setSysRoot(sysRoot); + qCDebug(androidDebugSupportLog) << "Sysroot: " << sysRoot; + } } if (isQmlDebugging()) { qCDebug(androidDebugSupportLog) << "QML debugging enabled. QML server: " diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp index 4fd6c7504b..d4bc98d6bb 100644 --- a/src/plugins/android/androidmanager.cpp +++ b/src/plugins/android/androidmanager.cpp @@ -205,11 +205,6 @@ void AndroidManager::apkInfo(const Utils::FilePath &apkPath, } } -QString AndroidManager::intentName(ProjectExplorer::Target *target) -{ - return packageName(target) + QLatin1Char('/') + activityName(target); -} - QString AndroidManager::activityName(ProjectExplorer::Target *target) { QDomDocument doc; @@ -287,7 +282,7 @@ QJsonObject AndroidManager::deploymentSettings(const Target *target) if (!qt) return {}; - auto tc = ProjectExplorer::ToolChainKitAspect::toolChain(target->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID); + auto tc = ToolChainKitAspect::cxxToolChain(target->kit()); if (!tc || tc->typeId() != Constants::ANDROID_TOOLCHAIN_TYPEID) return {}; QJsonObject settings; diff --git a/src/plugins/android/androidmanager.h b/src/plugins/android/androidmanager.h index e141636c17..eed226d440 100644 --- a/src/plugins/android/androidmanager.h +++ b/src/plugins/android/androidmanager.h @@ -78,7 +78,6 @@ public: QString *packageName = nullptr, int *version = nullptr, QString *activityPath = nullptr); - static QString intentName(ProjectExplorer::Target *target); static QString activityName(ProjectExplorer::Target *target); static QString deviceSerialNumber(ProjectExplorer::Target *target); diff --git a/src/plugins/android/androidmanifesteditoriconcontainerwidget.cpp b/src/plugins/android/androidmanifesteditoriconcontainerwidget.cpp new file mode 100644 index 0000000000..9a9c01da3e --- /dev/null +++ b/src/plugins/android/androidmanifesteditoriconcontainerwidget.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** 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 +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "androidmanifesteditoriconcontainerwidget.h" +#include "androidmanifesteditoriconwidget.h" + +#include <utils/utilsicons.h> + +#include <QFrame> +#include <QHBoxLayout> + +namespace Android { +namespace Internal { + +namespace { +const QString highDpiIconPath = "/res/drawable-hdpi/icon.png"; +const QString mediumDpiIconPath = "/res/drawable-mdpi/icon.png"; +const QString lowDpiIconPath = "/res/drawable-ldpi/icon.png"; +const QSize lowDpiIconSize{32, 32}; +const QSize mediumDpiIconSize{48, 48}; +const QSize highDpiIconSize{72, 72}; +} + +AndroidManifestEditorIconContainerWidget::AndroidManifestEditorIconContainerWidget( + QWidget *parent, + TextEditor::TextEditorWidget *textEditorWidget) + : QWidget(parent) +{ + auto iconLayout = new QHBoxLayout(this); + auto masterIconButton = new AndroidManifestEditorIconWidget(this, + lowDpiIconSize, + tr("Master icon"), tr("Select master icon")); + masterIconButton->setIcon(QIcon::fromTheme(QLatin1String("document-open"), Utils::Icons::OPENFILE.icon())); + iconLayout->addWidget(masterIconButton); + iconLayout->addStretch(1); + + QFrame *line = new QFrame(this); + line->setFrameShape(QFrame::VLine); + line->setFrameShadow(QFrame::Sunken); + iconLayout->addWidget(line); + iconLayout->addStretch(1); + + auto lIconButton = new AndroidManifestEditorIconWidget(this, + lowDpiIconSize, + tr("Low DPI icon"), tr("Select low DPI icon"), + textEditorWidget, lowDpiIconPath); + iconLayout->addWidget(lIconButton); + m_iconButtons.push_back(lIconButton); + iconLayout->addStretch(1); + + auto mIconButton = new AndroidManifestEditorIconWidget(this, + mediumDpiIconSize, + tr("Medium DPI icon"), tr("Select medium DPI icon"), + textEditorWidget, mediumDpiIconPath); + iconLayout->addWidget(mIconButton); + m_iconButtons.push_back(mIconButton); + iconLayout->addStretch(1); + + auto hIconButton = new AndroidManifestEditorIconWidget(this, + highDpiIconSize, + tr("High DPI icon"), tr("Select high DPI icon"), + textEditorWidget, highDpiIconPath); + iconLayout->addWidget(hIconButton); + m_iconButtons.push_back(hIconButton); + iconLayout->addStretch(6); + + for (auto &&iconButton : m_iconButtons) { + connect(masterIconButton, &AndroidManifestEditorIconWidget::iconSelected, + iconButton, &AndroidManifestEditorIconWidget::setIconFromPath); + } +} + +void AndroidManifestEditorIconContainerWidget::loadIcons() +{ + for (auto &&iconButton : m_iconButtons) + iconButton->loadIcon(); +} + +bool AndroidManifestEditorIconContainerWidget::hasIcons() +{ + for (auto &&iconButton : m_iconButtons) { + if (iconButton->hasIcon()) + return true; + } + return false; +} + +} // namespace Internal +} // namespace Android diff --git a/src/plugins/boot2qt/qdbdeploystepfactory.h b/src/plugins/android/androidmanifesteditoriconcontainerwidget.h index fada4a8478..b1d0415e9b 100644 --- a/src/plugins/boot2qt/qdbdeploystepfactory.h +++ b/src/plugins/android/androidmanifesteditoriconcontainerwidget.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -25,22 +25,28 @@ #pragma once -#include <projectexplorer/buildstep.h> +#include <QVector> +#include <QWidget> -namespace Qdb { +namespace TextEditor { + class TextEditorWidget; +} + +namespace Android { namespace Internal { -class QdbMakeDefaultAppStepFactory : public ProjectExplorer::BuildStepFactory -{ -public: - QdbMakeDefaultAppStepFactory(); -}; +class AndroidManifestEditorIconWidget; -class QdbStopApplicationStepFactory : public ProjectExplorer::BuildStepFactory +class AndroidManifestEditorIconContainerWidget : public QWidget { public: - QdbStopApplicationStepFactory(); + explicit AndroidManifestEditorIconContainerWidget(QWidget *parent, + TextEditor::TextEditorWidget *textEditorWidget); + void loadIcons(); + bool hasIcons(); +private: + QVector<AndroidManifestEditorIconWidget *> m_iconButtons; }; } // namespace Internal -} // namespace Qdb +} // namespace Android diff --git a/src/plugins/android/androidmanifesteditoriconwidget.cpp b/src/plugins/android/androidmanifesteditoriconwidget.cpp new file mode 100644 index 0000000000..e609b17491 --- /dev/null +++ b/src/plugins/android/androidmanifesteditoriconwidget.cpp @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** 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 +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "androidmanifesteditoriconwidget.h" + +#include <texteditor/textdocument.h> +#include <texteditor/texteditor.h> +#include <utils/utilsicons.h> + +#include <QFileDialog> +#include <QFileInfo> +#include <QGridLayout> +#include <QLabel> +#include <QLoggingCategory> +#include <QToolButton> +#include <QVBoxLayout> + +namespace Android { +namespace Internal { + +namespace { +static Q_LOGGING_CATEGORY(androidManifestEditorLog, "qtc.android.manifestEditor", QtWarningMsg) +const auto fileDialogIconFiles = QWidget::tr("Images (*.png *.jpg *.webp *.svg)"); +QString manifestDir(TextEditor::TextEditorWidget *textEditorWidget) +{ + // Get the manifest file's directory from its filepath. + return textEditorWidget->textDocument()->filePath().toFileInfo().absolutePath(); +} +} + +AndroidManifestEditorIconWidget::AndroidManifestEditorIconWidget(QWidget *parent) : QWidget(parent) +{ + +} + +AndroidManifestEditorIconWidget::AndroidManifestEditorIconWidget( + QWidget *parent, const QSize &buttonSize, const QString &title, + const QString &tooltip, + TextEditor::TextEditorWidget *textEditorWidget, + const QString &targetIconPath) + : QWidget(parent), m_buttonSize(buttonSize), + m_textEditorWidget(textEditorWidget), m_targetIconPath(targetIconPath) +{ + auto iconLayout = new QVBoxLayout(this); + auto iconTitle = new QLabel(title, this); + auto iconButtonLayout = new QGridLayout(); + m_button = new QToolButton(this); + m_button->setMinimumSize(buttonSize); + m_button->setMaximumSize(buttonSize); + m_button->setToolTip(tooltip); + m_button->setIconSize(buttonSize); + QSize clearAndWarningSize(16, 16); + QToolButton *clearButton = nullptr; + if (textEditorWidget) { + clearButton = new QToolButton(this); + clearButton->setMinimumSize(clearAndWarningSize); + clearButton->setMaximumSize(clearAndWarningSize); + clearButton->setIcon(Utils::Icons::CLOSE_FOREGROUND.icon()); + } + if (textEditorWidget) { + m_scaleWarningLabel = new QLabel(this); + m_scaleWarningLabel->setMinimumSize(clearAndWarningSize); + m_scaleWarningLabel->setMaximumSize(clearAndWarningSize); + m_scaleWarningLabel->setPixmap(Utils::Icons::WARNING.icon().pixmap(clearAndWarningSize)); + m_scaleWarningLabel->setToolTip(tr("Icon scaled up")); + m_scaleWarningLabel->setVisible(false); + } + auto label = new QLabel(tr("Click to select..."), parent); + iconLayout->addWidget(iconTitle); + iconLayout->setAlignment(iconTitle, Qt::AlignHCenter); + iconButtonLayout->setColumnMinimumWidth(0, 16); + iconButtonLayout->addWidget(m_button, 0, 1, 1, 3); + iconButtonLayout->setAlignment(m_button, Qt::AlignVCenter); + if (textEditorWidget) { + iconButtonLayout->addWidget(clearButton, 0, 4, 1, 1); + iconButtonLayout->setAlignment(clearButton, Qt::AlignTop); + } + if (textEditorWidget) { + iconButtonLayout->addWidget(m_scaleWarningLabel, 0, 0, 1, 1); + iconButtonLayout->setAlignment(m_scaleWarningLabel, Qt::AlignTop); + } + iconLayout->addLayout(iconButtonLayout); + iconLayout->setAlignment(iconButtonLayout, Qt::AlignHCenter); + iconLayout->addWidget(label); + iconLayout->setAlignment(label, Qt::AlignHCenter); + this->setLayout(iconLayout); + connect(m_button, &QAbstractButton::clicked, + this, &AndroidManifestEditorIconWidget::selectIcon); + if (clearButton) + connect(clearButton, &QAbstractButton::clicked, + this, &AndroidManifestEditorIconWidget::removeIcon); + m_iconSelectionText = tooltip; +} + +void AndroidManifestEditorIconWidget::setIcon(const QIcon &icon) +{ + m_button->setIcon(icon); +} + +void AndroidManifestEditorIconWidget::loadIcon() +{ + QString baseDir = manifestDir(m_textEditorWidget); + QString iconFile = baseDir + m_targetIconPath; + setIconFromPath(iconFile); +} + +void AndroidManifestEditorIconWidget::setIconFromPath(const QString &iconPath) +{ + if (!m_textEditorWidget) { + iconSelected(iconPath); + return; + } + m_iconPath = iconPath; + QString baseDir = manifestDir(m_textEditorWidget); + copyIcon(); + QString iconFile = baseDir + m_targetIconPath; + m_button->setIcon(QIcon(iconFile)); +} + +void AndroidManifestEditorIconWidget::selectIcon() +{ + QString file = QFileDialog::getOpenFileName(this, m_iconSelectionText, + QDir::homePath(), fileDialogIconFiles); + if (file.isEmpty()) + return; + setIconFromPath(file); +} + +void AndroidManifestEditorIconWidget::removeIcon() +{ + QString baseDir = manifestDir(m_textEditorWidget); + const QString targetPath = baseDir + m_targetIconPath; + if (targetPath.isEmpty()) { + qCDebug(androidManifestEditorLog) << "Icon target path empty, cannot remove icon."; + return; + } + QFileInfo targetFile(targetPath); + if (targetFile.exists()) { + QDir rmRf(targetFile.absoluteDir()); + rmRf.removeRecursively(); + } + setScaleWarningLabelVisible(false); + m_button->setIcon(QIcon()); +} + +bool AndroidManifestEditorIconWidget::hasIcon() +{ + return !m_iconPath.isEmpty(); +} + +void AndroidManifestEditorIconWidget::setScaleWarningLabelVisible(bool visible) +{ + if (m_scaleWarningLabel) + m_scaleWarningLabel->setVisible(visible); +} + +void AndroidManifestEditorIconWidget::copyIcon() +{ + if (m_targetIconPath.isEmpty()) + return; + QString baseDir = manifestDir(m_textEditorWidget); + const QString targetPath = baseDir + m_targetIconPath; + if (targetPath.isEmpty()) { + qCDebug(androidManifestEditorLog) << "Icon target path empty, cannot copy icon."; + return; + } + QFileInfo targetFile(targetPath); + if (m_iconPath == targetPath) + return; + removeIcon(); + QImage original(m_iconPath); + if (!targetPath.isEmpty() && !original.isNull()) { + QDir dir; + if (!dir.mkpath(QFileInfo(targetPath).absolutePath())) { + qCDebug(androidManifestEditorLog) << "Cannot create icon target path."; + m_iconPath.clear(); + return; + } + QSize targetSize = m_buttonSize; + QImage scaled = original.scaled(targetSize.width(), targetSize.height(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); + setScaleWarningLabelVisible(scaled.width() > original.width() || scaled.height() > original.height()); + scaled.save(targetPath); + m_iconPath = m_targetIconPath; + } else { + m_iconPath.clear(); + } +} + +} // namespace Internal +} // namespace Android diff --git a/src/plugins/android/androidmanifesteditoriconwidget.h b/src/plugins/android/androidmanifesteditoriconwidget.h new file mode 100644 index 0000000000..955ac11b8e --- /dev/null +++ b/src/plugins/android/androidmanifesteditoriconwidget.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** 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 +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <QWidget> + +namespace TextEditor { + class TextEditorWidget; +} + +QT_BEGIN_NAMESPACE +class QLabel; +class QToolButton; +QT_END_NAMESPACE + +namespace Android { +namespace Internal { + +class AndroidManifestEditorIconWidget : public QWidget +{ + Q_OBJECT +public: + explicit AndroidManifestEditorIconWidget(QWidget *parent); + AndroidManifestEditorIconWidget(QWidget *parent, + const QSize &buttonSize, + const QString &title, + const QString &tooltip, + TextEditor::TextEditorWidget *textEditorWidget = nullptr, + const QString &targetIconPath = {}); + void setIcon(const QIcon &icon); + void loadIcon(); + void setIconFromPath(const QString &iconPath); + bool hasIcon(); + +signals: + void iconSelected(const QString &path); + +private: + void selectIcon(); + void removeIcon(); + void copyIcon(); + void setScaleWarningLabelVisible(bool visible); +private: + QToolButton *m_button = nullptr; + QSize m_buttonSize; + QLabel *m_scaleWarningLabel = nullptr; + TextEditor::TextEditorWidget *m_textEditorWidget = nullptr; + QString m_iconPath; + QString m_targetIconPath; + QString m_iconSelectionText; +}; + +} // namespace Internal +} // namespace Android diff --git a/src/plugins/android/androidmanifesteditorwidget.cpp b/src/plugins/android/androidmanifesteditorwidget.cpp index 72c6dc11b2..d82282238a 100644 --- a/src/plugins/android/androidmanifesteditorwidget.cpp +++ b/src/plugins/android/androidmanifesteditorwidget.cpp @@ -24,6 +24,7 @@ ****************************************************************************/ #include "androidmanifesteditorwidget.h" +#include "androidmanifesteditoriconcontainerwidget.h" #include "androidmanifesteditor.h" #include "androidconfigurations.h" #include "androidconstants.h" @@ -67,7 +68,6 @@ #include <QLabel> #include <QLineEdit> #include <QListView> -#include <QLoggingCategory> #include <QPushButton> #include <QScrollArea> #include <QSpinBox> @@ -77,11 +77,6 @@ #include <algorithm> #include <limits> - -namespace { -static Q_LOGGING_CATEGORY(androidManifestEditorLog, "qtc.android.manifestEditor", QtWarningMsg) -} - using namespace ProjectExplorer; using namespace Android; using namespace Android::Internal; @@ -252,54 +247,11 @@ void AndroidManifestEditorWidget::initializePage() m_styleExtractMethod->setItemData(i, styleMethodsMap.at(i).at(1), Qt::ToolTipRole); } - auto iconLayout = new QHBoxLayout(); - - createDPIButton(iconLayout, - applicationGroupBox, - m_masterIconButton, iconSize(LowDPI), - tr("Master icon"), tr("Select master icon.")); - - m_masterIconButton->setIcon(QIcon::fromTheme(QLatin1String("document-open"), Utils::Icons::OPENFILE.icon())); - - iconLayout->addStretch(1); - - QFrame* line = new QFrame(); - line->setFrameShape(QFrame::VLine); - line->setFrameShadow(QFrame::Sunken); - iconLayout->addWidget(line); - - iconLayout->addStretch(1); - - createDPIButton(iconLayout, - applicationGroupBox, - m_lIconButton, iconSize(LowDPI), - tr("Low DPI icon"), tr("Select low DPI icon."), - &m_lIconClearButton, - &m_lIconScaleWarningLabel); - - iconLayout->addStretch(1); - - createDPIButton(iconLayout, - applicationGroupBox, - m_mIconButton, iconSize(MediumDPI), - tr("Medium DPI icon"), tr("Select medium DPI icon."), - &m_mIconClearButton, - &m_mIconScaleWarningLabel); - - iconLayout->addStretch(1); - - createDPIButton(iconLayout, - applicationGroupBox, - m_hIconButton, iconSize(HighDPI), - tr("High DPI icon"), tr("Select high DPI icon."), - &m_hIconClearButton, - &m_hIconScaleWarningLabel); - - iconLayout->addStretch(6); + m_iconButtons = new AndroidManifestEditorIconContainerWidget(applicationGroupBox, m_textEditorWidget); formLayout->addRow(tr("Application icon:"), new QLabel()); - formLayout->addRow(QString(), iconLayout); + formLayout->addRow(QString(), m_iconButtons); applicationGroupBox->setLayout(formLayout); @@ -312,21 +264,6 @@ void AndroidManifestEditorWidget::initializePage() connect(m_styleExtractMethod, QOverload<int>::of(&QComboBox::currentIndexChanged), this, setDirtyFunc); - - connect(m_masterIconButton, &QAbstractButton::clicked, - this, &AndroidManifestEditorWidget::setMasterIcon); - connect(m_lIconButton, &QAbstractButton::clicked, - this, &AndroidManifestEditorWidget::setLDPIIcon); - connect(m_mIconButton, &QAbstractButton::clicked, - this, &AndroidManifestEditorWidget::setMDPIIcon); - connect(m_hIconButton, &QAbstractButton::clicked, - this, &AndroidManifestEditorWidget::setHDPIIcon); - connect(m_lIconClearButton, &QAbstractButton::clicked, - this, &AndroidManifestEditorWidget::clearLDPIIcon); - connect(m_mIconClearButton, &QAbstractButton::clicked, - this, &AndroidManifestEditorWidget::clearMDPIIcon); - connect(m_hIconClearButton, &QAbstractButton::clicked, - this, &AndroidManifestEditorWidget::clearHDPIIcon); } @@ -633,13 +570,7 @@ void AndroidManifestEditorWidget::preSave() if (activePage() != Source) syncToEditor(); - QString baseDir = m_textEditorWidget->textDocument()->filePath().toFileInfo().absolutePath(); - copyIcon(LowDPI, baseDir, m_lIconPath); - copyIcon(MediumDPI, baseDir, m_mIconPath); - copyIcon(HighDPI, baseDir, m_hIconPath); - // no need to emit changed() since this is called as part of saving - updateInfoBar(); } @@ -840,13 +771,6 @@ void AndroidManifestEditorWidget::syncToWidgets(const QDomDocument &doc) metadataElem = metadataElem.nextSiblingElement(QLatin1String("meta-data")); } - m_lIconButton->setIcon(icon(baseDir, LowDPI)); - m_mIconButton->setIcon(icon(baseDir, MediumDPI)); - m_hIconButton->setIcon(icon(baseDir, HighDPI)); - m_lIconPath = baseDir + iconPath(LowDPI); - m_mIconPath = baseDir + iconPath(MediumDPI); - m_hIconPath = baseDir + iconPath(HighDPI); - disconnect(m_defaultPermissonsCheckBox, &QCheckBox::stateChanged, this, &AndroidManifestEditorWidget::defaultPermissionOrFeatureCheckBoxClicked); disconnect(m_defaultFeaturesCheckBox, &QCheckBox::stateChanged, @@ -886,6 +810,8 @@ void AndroidManifestEditorWidget::syncToWidgets(const QDomDocument &doc) m_permissionsModel->setPermissions(permissions); updateAddRemovePermissionButtons(); + m_iconButtons->loadIcons(); + m_stayClean = false; m_dirty = false; } @@ -1048,9 +974,7 @@ void AndroidManifestEditorWidget::parseApplication(QXmlStreamReader &reader, QXm QStringList keys = {QLatin1String("android:label")}; QStringList values = {m_appNameLineEdit->text()}; QStringList remove; - bool ensureIconAttribute = !m_lIconPath.isEmpty() - || !m_mIconPath.isEmpty() - || !m_hIconPath.isEmpty(); + bool ensureIconAttribute = m_iconButtons->hasIcons(); if (ensureIconAttribute) { keys << QLatin1String("android:icon"); values << QLatin1String("@drawable/icon"); @@ -1276,246 +1200,6 @@ void AndroidManifestEditorWidget::parseUnknownElement(QXmlStreamReader &reader, } } -QString AndroidManifestEditorWidget::iconPath(IconDPI dpi) -{ - switch (dpi) { - case HighDPI: - return QString("/res/drawable-hdpi/icon.png"); - case MediumDPI: - return QString("/res/drawable-mdpi/icon.png"); - case LowDPI: - return QString("/res/drawable-ldpi/icon.png"); - } - return {}; -} - -QSize AndroidManifestEditorWidget::iconSize(IconDPI dpi) -{ - switch (dpi) { - case HighDPI: - return QSize(72, 72); - case MediumDPI: - return QSize(48, 48); - case LowDPI: - return QSize(32, 32); - } - return QSize(72, 72); -} - -void AndroidManifestEditorWidget::updateIconPath(const QString &newPath, IconDPI dpi) -{ - switch (dpi) { - case HighDPI: - m_hIconPath = newPath; - break; - case MediumDPI: - m_mIconPath = newPath; - break; - case LowDPI: - m_lIconPath = newPath; - break; - } -} - -QIcon AndroidManifestEditorWidget::icon(const QString &baseDir, IconDPI dpi) -{ - - if (dpi == HighDPI && !m_hIconPath.isEmpty()) - return QIcon(m_hIconPath); - - if (dpi == MediumDPI && !m_mIconPath.isEmpty()) - return QIcon(m_mIconPath); - - if (dpi == LowDPI && !m_lIconPath.isEmpty()) - return QIcon(m_lIconPath); - - QString fileName = baseDir + iconPath(dpi); - if (fileName.isEmpty()) - return QIcon(); - return QIcon(fileName); -} - -void AndroidManifestEditorWidget::copyIcon(IconDPI dpi, const QString &baseDir, const QString &filePath) -{ - const QString targetPath = baseDir + iconPath(dpi); - if (targetPath.isEmpty()) { - qCDebug(androidManifestEditorLog) << "Icon target path empty, cannot copy icon."; - return; - } - QFileInfo targetFile(targetPath); - if (filePath == targetPath) - return; - removeIcon(dpi, baseDir); - QImage original(filePath); - if (!targetPath.isEmpty() && !original.isNull()) { - QDir dir; - dir.mkpath(QFileInfo(targetPath).absolutePath()); - QSize targetSize = iconSize(dpi); - QImage scaled = original.scaled(targetSize.width(), targetSize.height(), - Qt::KeepAspectRatio, Qt::SmoothTransformation); - toggleIconScaleWarning(dpi, scaled.width() > original.width() || scaled.height() > original.height()); - scaled.save(targetPath); - updateIconPath(targetPath, dpi); - } -} - -void AndroidManifestEditorWidget::removeIcon(IconDPI dpi, const QString &baseDir) -{ - const QString targetPath = baseDir + iconPath(dpi); - if (targetPath.isEmpty()) { - qCDebug(androidManifestEditorLog) << "Icon target path empty, cannot remove icon."; - return; - } - QFileInfo targetFile(targetPath); - if (targetFile.exists()) { - QDir rmRf(targetFile.absoluteDir()); - rmRf.removeRecursively(); - } - toggleIconScaleWarning(dpi, false); -} - -void AndroidManifestEditorWidget::toggleIconScaleWarning(IconDPI dpi, bool visible) -{ - switch (dpi) { - case HighDPI: - m_hIconScaleWarningLabel->setVisible(visible); - break; - case MediumDPI: - m_mIconScaleWarningLabel->setVisible(visible); - break; - case LowDPI: - m_lIconScaleWarningLabel->setVisible(visible); - break; - } -} - -const auto fileDialogIconFiles = QWidget::tr("Images (*.png *.jpg *.webp *.svg)"); - -void AndroidManifestEditorWidget::setMasterIcon() -{ - QString file = QFileDialog::getOpenFileName(this, tr("Choose Master Icon"), QDir::homePath(), fileDialogIconFiles); - if (file.isEmpty()) - return; - QString baseDir = m_textEditorWidget->textDocument()->filePath().toFileInfo().absolutePath(); - copyIcon(LowDPI, baseDir, file); - copyIcon(MediumDPI, baseDir, file); - copyIcon(HighDPI, baseDir, file); - m_lIconButton->setIcon(icon(baseDir, LowDPI)); - m_mIconButton->setIcon(icon(baseDir, MediumDPI)); - m_hIconButton->setIcon(icon(baseDir, HighDPI)); -} - -void AndroidManifestEditorWidget::setLDPIIcon() -{ - QString file = QFileDialog::getOpenFileName(this, tr("Choose Low DPI Icon"), QDir::homePath(), fileDialogIconFiles); - if (file.isEmpty()) - return; - m_lIconPath = file; - QString baseDir = m_textEditorWidget->textDocument()->filePath().toFileInfo().absolutePath(); - copyIcon(LowDPI, baseDir, m_lIconPath); - m_lIconButton->setIcon(icon(baseDir, LowDPI)); -} - -void AndroidManifestEditorWidget::setMDPIIcon() -{ - QString file = QFileDialog::getOpenFileName(this, tr("Choose Medium DPI Icon"), QDir::homePath(), fileDialogIconFiles); - if (file.isEmpty()) - return; - m_mIconPath = file; - QString baseDir = m_textEditorWidget->textDocument()->filePath().toFileInfo().absolutePath(); - copyIcon(MediumDPI, baseDir, m_mIconPath); - m_mIconButton->setIcon(icon(baseDir, MediumDPI)); -} - -void AndroidManifestEditorWidget::setHDPIIcon() -{ - QString file = QFileDialog::getOpenFileName(this, tr("Choose High DPI Icon"), QDir::homePath(), fileDialogIconFiles); - if (file.isEmpty()) - return; - m_hIconPath = file; - QString baseDir = m_textEditorWidget->textDocument()->filePath().toFileInfo().absolutePath(); - copyIcon(HighDPI, baseDir, m_hIconPath); - m_hIconButton->setIcon(icon(baseDir, HighDPI)); -} - -void AndroidManifestEditorWidget::clearLDPIIcon() -{ - m_lIconPath.clear(); - m_lIconButton->setIcon(QIcon()); - QString baseDir = m_textEditorWidget->textDocument()->filePath().toFileInfo().absolutePath(); - removeIcon(LowDPI, baseDir); -} - -void AndroidManifestEditorWidget::clearMDPIIcon() -{ - m_mIconPath.clear(); - m_mIconButton->setIcon(QIcon()); - QString baseDir = m_textEditorWidget->textDocument()->filePath().toFileInfo().absolutePath(); - removeIcon(MediumDPI, baseDir); -} - -void AndroidManifestEditorWidget::clearHDPIIcon() -{ - m_hIconPath.clear(); - m_hIconButton->setIcon(QIcon()); - QString baseDir = m_textEditorWidget->textDocument()->filePath().toFileInfo().absolutePath(); - removeIcon(HighDPI, baseDir); -} - -void AndroidManifestEditorWidget::createDPIButton(QHBoxLayout *layout, - QWidget *parent, - QToolButton *&button, - const QSize &buttonSize, - const QString &title, - const QString &tooltip, - QToolButton **clearButton, - QLabel **scaleWarningLabel) -{ - auto iconLayout = new QVBoxLayout(); - auto iconTitle = new QLabel(title, parent); - auto iconButtonLayout = new QGridLayout(); - button = new QToolButton(parent); - button->setMinimumSize(buttonSize); - button->setMaximumSize(buttonSize); - button->setToolTip(tooltip); - button->setIconSize(buttonSize); - QSize clearAndWarningSize(16, 16); - if (clearButton) { - *clearButton = new QToolButton(parent); - (*clearButton)->setMinimumSize(clearAndWarningSize); - (*clearButton)->setMaximumSize(clearAndWarningSize); - (*clearButton)->setIcon(Utils::Icons::CLOSE_FOREGROUND.icon()); - } - if (scaleWarningLabel) { - *scaleWarningLabel = new QLabel(parent); - (*scaleWarningLabel)->setMinimumSize(clearAndWarningSize); - (*scaleWarningLabel)->setMaximumSize(clearAndWarningSize); - (*scaleWarningLabel)->setPixmap(Utils::Icons::WARNING.icon().pixmap(clearAndWarningSize)); - (*scaleWarningLabel)->setToolTip(tr("Icon scaled up")); - (*scaleWarningLabel)->setVisible(false); - } - auto label = new QLabel(tr("Click to select"), parent); - iconLayout->addWidget(iconTitle); - iconLayout->setAlignment(iconTitle, Qt::AlignHCenter); - iconButtonLayout->setColumnMinimumWidth(0, 16); - iconButtonLayout->addWidget(button, 0, 1, 1, 3); - iconButtonLayout->setAlignment(button, Qt::AlignVCenter); - if (clearButton) { - iconButtonLayout->addWidget(*clearButton, 0, 4, 1, 1); - iconButtonLayout->setAlignment(*clearButton, Qt::AlignTop); - } - if (scaleWarningLabel) { - iconButtonLayout->addWidget(*scaleWarningLabel, 0, 0, 1, 1); - iconButtonLayout->setAlignment(*scaleWarningLabel, Qt::AlignTop); - } - iconLayout->addLayout(iconButtonLayout); - iconLayout->setAlignment(iconButtonLayout, Qt::AlignHCenter); - iconLayout->addWidget(label); - iconLayout->setAlignment(label, Qt::AlignHCenter); - - layout->addLayout(iconLayout); -} - void AndroidManifestEditorWidget::defaultPermissionOrFeatureCheckBoxClicked() { setDirty(true); diff --git a/src/plugins/android/androidmanifesteditorwidget.h b/src/plugins/android/androidmanifesteditorwidget.h index 8e38773cd6..2384264257 100644 --- a/src/plugins/android/androidmanifesteditorwidget.h +++ b/src/plugins/android/androidmanifesteditorwidget.h @@ -52,9 +52,9 @@ namespace Core { class IEditor; } namespace Android { namespace Internal { class AndroidManifestEditor; +class AndroidManifestEditorIconContainerWidget; class AndroidManifestEditorWidget; - class PermissionsModel: public QAbstractListModel { Q_OBJECT @@ -116,21 +116,6 @@ protected: void focusInEvent(QFocusEvent *event) override; private: - void setMasterIcon(); - void clearMasterIcon(); - void setLDPIIcon(); - void setMDPIIcon(); - void setHDPIIcon(); - void clearLDPIIcon(); - void clearMDPIIcon(); - void clearHDPIIcon(); - void createDPIButton(QHBoxLayout *layout, - QWidget *parent, - QToolButton *&button, const QSize &buttonSize, - const QString &title, const QString &tooltip, - QToolButton **clearButton = nullptr, - QLabel **scaleWarningLabel = nullptr - ); void defaultPermissionOrFeatureCheckBoxClicked(); void addPermission(); void removePermission(); @@ -148,14 +133,6 @@ private: bool checkDocument(const QDomDocument &doc, QString *errorMessage, int *errorLine, int *errorColumn); - enum IconDPI { LowDPI, MediumDPI, HighDPI }; - QIcon icon(const QString &baseDir, IconDPI dpi); - QString iconPath(IconDPI dpi); - QSize iconSize(IconDPI dpi); - void updateIconPath(const QString &newPath, IconDPI dpi); - void copyIcon(IconDPI dpi, const QString &baseDir, const QString &filePath); - void removeIcon(IconDPI dpi, const QString &baseDir); - void toggleIconScaleWarning(IconDPI dpi, bool visible); void updateInfoBar(const QString &errorMessage, int line, int column); void hideInfoBar(); @@ -190,19 +167,7 @@ private: QLineEdit *m_activityNameLineEdit; QComboBox *m_targetLineEdit; QComboBox *m_styleExtractMethod; - QToolButton *m_masterIconButton; - QToolButton *m_lIconButton; - QToolButton *m_lIconClearButton; - QLabel *m_lIconScaleWarningLabel; - QToolButton *m_mIconButton; - QToolButton *m_mIconClearButton; - QLabel *m_mIconScaleWarningLabel; - QToolButton *m_hIconButton; - QToolButton *m_hIconClearButton; - QLabel *m_hIconScaleWarningLabel; - QString m_lIconPath; - QString m_mIconPath; - QString m_hIconPath; + AndroidManifestEditorIconContainerWidget *m_iconButtons; // Permissions QCheckBox *m_defaultPermissonsCheckBox; diff --git a/src/plugins/android/androidpackageinstallationstep.cpp b/src/plugins/android/androidpackageinstallationstep.cpp index 9017513974..4e029fda6b 100644 --- a/src/plugins/android/androidpackageinstallationstep.cpp +++ b/src/plugins/android/androidpackageinstallationstep.cpp @@ -28,13 +28,14 @@ #include "androidconstants.h" #include "androidmanager.h" -#include <projectexplorer/buildsteplist.h> -#include <projectexplorer/target.h> +#include <projectexplorer/abstractprocessstep.h> #include <projectexplorer/buildconfiguration.h> +#include <projectexplorer/buildsteplist.h> #include <projectexplorer/gnumakeparser.h> #include <projectexplorer/kitinformation.h> #include <projectexplorer/processparameters.h> #include <projectexplorer/projectexplorerconstants.h> +#include <projectexplorer/target.h> #include <projectexplorer/toolchain.h> #include <utils/hostosinfo.h> @@ -44,9 +45,38 @@ using namespace ProjectExplorer; using namespace Utils; -using namespace Android::Internal; namespace Android { +namespace Internal { + +class AndroidPackageInstallationStep final : public AbstractProcessStep +{ + Q_DECLARE_TR_FUNCTIONS(Android::AndroidPackageInstallationStep) + +public: + AndroidPackageInstallationStep(BuildStepList *bsl, Core::Id id); + + BuildStepConfigWidget *createConfigWidget() final; + +private: + bool init() final; + void doRun() final; + + QStringList m_androidDirsToClean; +}; + +class AndroidPackageInstallationStepWidget final : public BuildStepConfigWidget +{ + Q_DECLARE_TR_FUNCTIONS(Android::AndroidPackageInstallationStepWidget) + +public: + AndroidPackageInstallationStepWidget(BuildStep *step) + : BuildStepConfigWidget(step) + { + setDisplayName(tr("Make install")); + setSummaryText("<b>" + tr("Make install") + "</b>"); + } +}; AndroidPackageInstallationStep::AndroidPackageInstallationStep(BuildStepList *bsl, Core::Id id) : AbstractProcessStep(bsl, id) @@ -60,25 +90,23 @@ AndroidPackageInstallationStep::AndroidPackageInstallationStep(BuildStepList *bs bool AndroidPackageInstallationStep::init() { - BuildConfiguration *bc = buildConfiguration(); - QString dirPath = bc->buildDirectory().pathAppended(Constants::ANDROID_BUILDDIRECTORY).toString(); + QString dirPath = buildDirectory().pathAppended(Constants::ANDROID_BUILDDIRECTORY).toString(); if (HostOsInfo::isWindowsHost()) - if (bc->environment().searchInPath("sh.exe").isEmpty()) + if (buildEnvironment().searchInPath("sh.exe").isEmpty()) dirPath = QDir::toNativeSeparators(dirPath); - ToolChain *tc = ToolChainKitAspect::toolChain(target()->kit(), - ProjectExplorer::Constants::CXX_LANGUAGE_ID); + ToolChain *tc = ToolChainKitAspect::cxxToolChain(target()->kit()); QTC_ASSERT(tc, return false); - CommandLine cmd{tc->makeCommand(bc->environment())}; + CommandLine cmd{tc->makeCommand(buildEnvironment())}; const QString innerQuoted = QtcProcess::quoteArg(dirPath); const QString outerQuoted = QtcProcess::quoteArg("INSTALL_ROOT=" + innerQuoted); cmd.addArgs(outerQuoted + " install", CommandLine::Raw); ProcessParameters *pp = processParameters(); - pp->setMacroExpander(bc->macroExpander()); - pp->setWorkingDirectory(bc->buildDirectory()); - Environment env = bc->environment(); + pp->setMacroExpander(macroExpander()); + pp->setWorkingDirectory(buildDirectory()); + Environment env = buildEnvironment(); Environment::setupEnglishOutput(&env); pp->setEnvironment(env); pp->setCommandLine(cmd); @@ -119,20 +147,6 @@ BuildStepConfigWidget *AndroidPackageInstallationStep::createConfigWidget() return new AndroidPackageInstallationStepWidget(this); } - -// -// AndroidPackageInstallationStepWidget -// - -namespace Internal { - -AndroidPackageInstallationStepWidget::AndroidPackageInstallationStepWidget(AndroidPackageInstallationStep *step) - : BuildStepConfigWidget(step) -{ - setDisplayName(tr("Make install")); - setSummaryText("<b>" + tr("Make install") + "</b>"); -} - // // AndroidPackageInstallationStepFactory // diff --git a/src/plugins/android/androidpackageinstallationstep.h b/src/plugins/android/androidpackageinstallationstep.h index f9e2c7d493..80300f2997 100644 --- a/src/plugins/android/androidpackageinstallationstep.h +++ b/src/plugins/android/androidpackageinstallationstep.h @@ -25,39 +25,12 @@ #pragma once -#include "android_global.h" - #include <projectexplorer/buildstep.h> -#include <projectexplorer/abstractprocessstep.h> namespace Android { - -class ANDROID_EXPORT AndroidPackageInstallationStep : public ProjectExplorer::AbstractProcessStep -{ - Q_OBJECT - -public: - AndroidPackageInstallationStep(ProjectExplorer::BuildStepList *bsl, Core::Id id); - - ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override; - -private: - bool init() override; - void doRun() override; - - QStringList m_androidDirsToClean; -}; - namespace Internal { -class AndroidPackageInstallationStepWidget : public ProjectExplorer::BuildStepConfigWidget -{ - Q_OBJECT -public: - AndroidPackageInstallationStepWidget(AndroidPackageInstallationStep *step); -}; - -class AndroidPackageInstallationFactory: public ProjectExplorer::BuildStepFactory +class AndroidPackageInstallationFactory final : public ProjectExplorer::BuildStepFactory { public: AndroidPackageInstallationFactory(); diff --git a/src/plugins/android/androidrunner.cpp b/src/plugins/android/androidrunner.cpp index 62328589b5..16098ae179 100644 --- a/src/plugins/android/androidrunner.cpp +++ b/src/plugins/android/androidrunner.cpp @@ -132,7 +132,10 @@ AndroidRunner::AndroidRunner(RunControl *runControl, const QString &intentName) m_checkAVDTimer.setInterval(2000); connect(&m_checkAVDTimer, &QTimer::timeout, this, &AndroidRunner::checkAVD); - QString intent = intentName.isEmpty() ? AndroidManager::intentName(m_target) : intentName; + QString intent = intentName; + if (intent.isEmpty()) + intent = AndroidManager::packageName(m_target) + '/' + AndroidManager::activityName(m_target); + m_packageName = intent.left(intent.indexOf('/')); qCDebug(androidRunnerLog) << "Intent name:" << intent << "Package name" << m_packageName; @@ -212,14 +215,14 @@ void AndroidRunner::qmlServerPortReady(Port port) void AndroidRunner::remoteOutput(const QString &output) { Core::MessageManager::write("LOGCAT: " + output, Core::MessageManager::Silent); - appendMessage(output, Utils::StdOutFormatSameLine); + appendMessage(output, Utils::StdOutFormat); m_outputParser.processOutput(output); } void AndroidRunner::remoteErrorOutput(const QString &output) { Core::MessageManager::write("LOGCAT: " + output, Core::MessageManager::Silent); - appendMessage(output, Utils::StdErrFormatSameLine); + appendMessage(output, Utils::StdErrFormat); m_outputParser.processOutput(output); } diff --git a/src/plugins/android/androidsdkmanagerwidget.cpp b/src/plugins/android/androidsdkmanagerwidget.cpp index 84dfe948d9..b098078f0b 100644 --- a/src/plugins/android/androidsdkmanagerwidget.cpp +++ b/src/plugins/android/androidsdkmanagerwidget.cpp @@ -436,10 +436,8 @@ void AndroidSdkManagerWidget::cancelPendingOperations() void AndroidSdkManagerWidget::switchView(AndroidSdkManagerWidget::View view) { - if (m_currentView == PackageListing) { + if (m_currentView == PackageListing) m_formatter->clear(); - m_ui->outputEdit->clear(); - } m_currentView = view; if (m_currentView == PackageListing) emit updatingSdkFinished(); diff --git a/src/plugins/android/androidtoolchain.cpp b/src/plugins/android/androidtoolchain.cpp index 2c45eba1e5..84aa82f4c9 100644 --- a/src/plugins/android/androidtoolchain.cpp +++ b/src/plugins/android/androidtoolchain.cpp @@ -76,7 +76,7 @@ static ToolChain *findToolChain(Utils::FilePath &compilerPath, Core::Id lang, co AndroidToolChain::AndroidToolChain() : ClangToolChain(Constants::ANDROID_TOOLCHAIN_TYPEID) { - setTypeDisplayName(AndroidToolChainFactory::tr("Android Clang")); + setTypeDisplayName(AndroidToolChain::tr("Android Clang")); } Utils::FilePath AndroidToolChain::ndkLocation() const @@ -163,7 +163,7 @@ GccToolChain::DetectedAbisResult AndroidToolChain::detectSupportedAbis() const AndroidToolChainFactory::AndroidToolChainFactory() { - setDisplayName(tr("Android Clang")); + setDisplayName(AndroidToolChain::tr("Android Clang")); setSupportedToolChainType(Constants::ANDROID_TOOLCHAIN_TYPEID); setSupportedLanguages({ProjectExplorer::Constants::CXX_LANGUAGE_ID}); setToolchainConstructor([] { return new AndroidToolChain; }); diff --git a/src/plugins/android/androidtoolchain.h b/src/plugins/android/androidtoolchain.h index 4002cef75f..0624892aab 100644 --- a/src/plugins/android/androidtoolchain.h +++ b/src/plugins/android/androidtoolchain.h @@ -36,6 +36,8 @@ using ToolChainList = QList<ProjectExplorer::ToolChain *>; class AndroidToolChain : public ProjectExplorer::ClangToolChain { + Q_DECLARE_TR_FUNCTIONS(Android::Internal::AndroidToolChain) + public: ~AndroidToolChain() override; @@ -62,8 +64,6 @@ private: class AndroidToolChainFactory : public ProjectExplorer::ToolChainFactory { - Q_OBJECT - public: AndroidToolChainFactory(); diff --git a/src/plugins/android/createandroidmanifestwizard.cpp b/src/plugins/android/createandroidmanifestwizard.cpp index 4a5e6968a7..ada75be278 100644 --- a/src/plugins/android/createandroidmanifestwizard.cpp +++ b/src/plugins/android/createandroidmanifestwizard.cpp @@ -389,18 +389,21 @@ void CreateAndroidManifestWizard::createAndroidTemplateFiles() if (node) { node->addFiles(addedFiles); androidPackageDir = node->data(Android::Constants::AndroidPackageSourceDir).toString(); - } - if (androidPackageDir.isEmpty()) { - // and now time for some magic - const BuildTargetInfo bti = target->buildTarget(m_buildKey); - const QString value = "$$PWD/" + bti.projectFilePath.toFileInfo().absoluteDir().relativeFilePath(m_directory); - bool result = node->setData(Android::Constants::AndroidPackageSourceDir, value); - - if (!result) { - QMessageBox::warning(this, tr("Project File not Updated"), - tr("Could not update the project file %1.") - .arg(bti.projectFilePath.toUserOutput())); + if (androidPackageDir.isEmpty()) { + // and now time for some magic + const BuildTargetInfo bti = target->buildTarget(m_buildKey); + const QString value = "$$PWD/" + + bti.projectFilePath.toFileInfo().absoluteDir().relativeFilePath( + m_directory); + bool result = node->setData(Android::Constants::AndroidPackageSourceDir, value); + + if (!result) { + QMessageBox::warning(this, + tr("Project File not Updated"), + tr("Could not update the project file %1.") + .arg(bti.projectFilePath.toUserOutput())); + } } } Core::EditorManager::openEditor(m_directory + QLatin1String("/AndroidManifest.xml")); diff --git a/src/plugins/autotest/CMakeLists.txt b/src/plugins/autotest/CMakeLists.txt index b624c4eff3..0180d72238 100644 --- a/src/plugins/autotest/CMakeLists.txt +++ b/src/plugins/autotest/CMakeLists.txt @@ -72,7 +72,6 @@ add_qtc_plugin(AutoTest testtreeitemdelegate.cpp testtreeitemdelegate.h testtreemodel.cpp testtreemodel.h testtreeview.cpp testtreeview.h - EXPLICIT_MOC boost/boosttestsettingspage.h ) extend_qtc_plugin(AutoTest diff --git a/src/plugins/autotest/autotestplugin.cpp b/src/plugins/autotest/autotestplugin.cpp index 46e00c8267..5b8c796ac3 100644 --- a/src/plugins/autotest/autotestplugin.cpp +++ b/src/plugins/autotest/autotestplugin.cpp @@ -86,12 +86,10 @@ class AutotestPluginPrivate : public QObject { Q_OBJECT public: - explicit AutotestPluginPrivate(AutotestPlugin *parent); + AutotestPluginPrivate(); ~AutotestPluginPrivate() override; - AutotestPlugin *q = nullptr; TestFrameworkManager *m_frameworkManager = nullptr; - TestSettingsPage *m_testSettingPage = nullptr; TestNavigationWidgetFactory *m_navigationWidgetFactory = nullptr; TestResultsPane *m_resultsPane = nullptr; QMap<QString, ChoicePair> m_runconfigCache; @@ -101,30 +99,30 @@ public: void onRunSelectedTriggered(); void onRunFileTriggered(); void onRunUnderCursorTriggered(TestRunMode mode); + + TestSettings m_settings; + TestSettingsPage m_testSettingPage{&m_settings}; }; -static AutotestPlugin *s_instance = nullptr; +static AutotestPluginPrivate *dd = nullptr; static QHash<ProjectExplorer::Project *, TestProjectSettings *> s_projectSettings; AutotestPlugin::AutotestPlugin() - : m_settings(new TestSettings) { // needed to be used in QueuedConnection connects qRegisterMetaType<TestResult>(); qRegisterMetaType<TestTreeItem *>(); qRegisterMetaType<TestCodeLocationAndType>(); - - s_instance = this; } AutotestPlugin::~AutotestPlugin() { - delete d; + delete dd; } -AutotestPluginPrivate::AutotestPluginPrivate(AutotestPlugin *parent) - : q(parent) +AutotestPluginPrivate::AutotestPluginPrivate() { + dd = this; // Needed as the code below access it via the static plugin interface m_frameworkManager = TestFrameworkManager::instance(); initializeMenuEntries(); m_frameworkManager->registerTestFramework(new QtTestFramework); @@ -133,7 +131,6 @@ AutotestPluginPrivate::AutotestPluginPrivate(AutotestPlugin *parent) m_frameworkManager->registerTestFramework(new BoostTestFramework); m_frameworkManager->synchronizeSettings(ICore::settings()); - m_testSettingPage = new TestSettingsPage(q->settings()); m_navigationWidgetFactory = new TestNavigationWidgetFactory; m_resultsPane = TestResultsPane::instance(); @@ -146,7 +143,7 @@ AutotestPluginPrivate::AutotestPluginPrivate(AutotestPlugin *parent) }); ProjectExplorer::ProjectPanelFactory::registerFactory(panelFactory); - m_frameworkManager->activateFrameworksFromSettings(q->settings()); + m_frameworkManager->activateFrameworksFromSettings(&m_settings); TestTreeModel::instance()->synchronizeTestFrameworks(); auto sessionManager = ProjectExplorer::SessionManager::instance(); @@ -172,13 +169,12 @@ AutotestPluginPrivate::~AutotestPluginPrivate() delete m_navigationWidgetFactory; delete m_resultsPane; - delete m_testSettingPage; delete m_frameworkManager; } -QSharedPointer<TestSettings> AutotestPlugin::settings() +TestSettings *AutotestPlugin::settings() { - return s_instance->m_settings; + return &dd->m_settings; } TestProjectSettings *AutotestPlugin::projectSettings(ProjectExplorer::Project *project) @@ -259,7 +255,7 @@ bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorStri Q_UNUSED(arguments) Q_UNUSED(errorString) - d = new AutotestPluginPrivate(this); + dd = new AutotestPluginPrivate; return true; } @@ -275,7 +271,7 @@ void AutotestPlugin::extensionsInitialized() Command *command = ActionManager::registerAction(action, Constants::ACTION_RUN_UCURSOR); connect(action, &QAction::triggered, - std::bind(&AutotestPluginPrivate::onRunUnderCursorTriggered, d, TestRunMode::Run)); + std::bind(&AutotestPluginPrivate::onRunUnderCursorTriggered, dd, TestRunMode::Run)); contextMenu->addSeparator(); contextMenu->addAction(command); @@ -285,7 +281,7 @@ void AutotestPlugin::extensionsInitialized() command = ActionManager::registerAction(action, Constants::ACTION_RUN_DBG_UCURSOR); connect(action, &QAction::triggered, - std::bind(&AutotestPluginPrivate::onRunUnderCursorTriggered, d, TestRunMode::Debug)); + std::bind(&AutotestPluginPrivate::onRunUnderCursorTriggered, dd, TestRunMode::Debug)); contextMenu->addAction(command); contextMenu->addSeparator(); } @@ -404,25 +400,25 @@ void AutotestPlugin::updateMenuItemsEnabledState() void AutotestPlugin::cacheRunConfigChoice(const QString &buildTargetKey, const ChoicePair &choice) { - if (s_instance) - s_instance->d->m_runconfigCache.insert(buildTargetKey, choice); + if (dd) + dd->m_runconfigCache.insert(buildTargetKey, choice); } ChoicePair AutotestPlugin::cachedChoiceFor(const QString &buildTargetKey) { - return s_instance ? s_instance->d->m_runconfigCache.value(buildTargetKey) : ChoicePair(); + return dd ? dd->m_runconfigCache.value(buildTargetKey) : ChoicePair(); } void AutotestPlugin::clearChoiceCache() { - if (s_instance) - s_instance->d->m_runconfigCache.clear(); + if (dd) + dd->m_runconfigCache.clear(); } void AutotestPlugin::popupResultsPane() { - if (s_instance) - s_instance->d->m_resultsPane->popup(Core::IOutputPane::NoModeSwitch); + if (dd) + dd->m_resultsPane->popup(Core::IOutputPane::NoModeSwitch); } QVector<QObject *> AutotestPlugin::createTestObjects() const diff --git a/src/plugins/autotest/autotestplugin.h b/src/plugins/autotest/autotestplugin.h index b34fd95c36..c30db79e12 100644 --- a/src/plugins/autotest/autotestplugin.h +++ b/src/plugins/autotest/autotestplugin.h @@ -29,8 +29,6 @@ #include <extensionsystem/iplugin.h> -#include <QMap> - namespace ProjectExplorer { class Project; class RunConfiguration; @@ -65,7 +63,7 @@ public: void extensionsInitialized() override; ShutdownFlag aboutToShutdown() override; - static QSharedPointer<TestSettings> settings(); + static TestSettings *settings(); static TestProjectSettings *projectSettings(ProjectExplorer::Project *project); static void updateMenuItemsEnabledState(); static void cacheRunConfigChoice(const QString &buildTargetKey, const ChoicePair &choice); @@ -75,8 +73,6 @@ public: private: QVector<QObject *> createTestObjects() const override; - class AutotestPluginPrivate *d = nullptr; - const QSharedPointer<TestSettings> m_settings; }; } // namespace Internal diff --git a/src/plugins/autotest/autotestunittests.cpp b/src/plugins/autotest/autotestunittests.cpp index 4897e98efa..812dd1fd55 100644 --- a/src/plugins/autotest/autotestunittests.cpp +++ b/src/plugins/autotest/autotestunittests.cpp @@ -67,8 +67,7 @@ void AutoTestUnitTests::initTestCase() m_isQt4 = qtVersion->qtVersionString().startsWith('4'); else QSKIP("Could not figure out which Qt version is used for default kit."); - const ToolChain * const toolchain = ToolChainKitAspect::toolChain(allKits.first(), - ProjectExplorer::Constants::CXX_LANGUAGE_ID); + const ToolChain * const toolchain = ToolChainKitAspect::cxxToolChain(allKits.first()); if (!toolchain) QSKIP("This test requires that there is a kit with a toolchain."); diff --git a/src/plugins/autotest/boost/boosttestconfiguration.cpp b/src/plugins/autotest/boost/boosttestconfiguration.cpp index e24b45196d..cdae7a40f8 100644 --- a/src/plugins/autotest/boost/boosttestconfiguration.cpp +++ b/src/plugins/autotest/boost/boosttestconfiguration.cpp @@ -35,12 +35,12 @@ namespace Autotest { namespace Internal { -static QSharedPointer<BoostTestSettings> getBoostSettings() +static BoostTestSettings *getBoostSettings() { const Core::Id id = Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix( BoostTest::Constants::FRAMEWORK_NAME); TestFrameworkManager *manager = TestFrameworkManager::instance(); - return qSharedPointerCast<BoostTestSettings>(manager->settingsForTestFramework(id)); + return dynamic_cast<BoostTestSettings *>(manager->settingsForTestFramework(id)); } TestOutputReader *BoostTestConfiguration::outputReader(const QFutureInterface<TestResultPtr> &fi, diff --git a/src/plugins/autotest/boost/boosttestframework.cpp b/src/plugins/autotest/boost/boosttestframework.cpp index d54881540a..fc4f76a125 100644 --- a/src/plugins/autotest/boost/boosttestframework.cpp +++ b/src/plugins/autotest/boost/boosttestframework.cpp @@ -25,8 +25,6 @@ #include "boosttestframework.h" #include "boosttestconstants.h" -#include "boosttestsettings.h" -#include "boosttestsettingspage.h" #include "boosttesttreeitem.h" #include "boosttestparser.h" #include "../testframeworkmanager.h" @@ -34,9 +32,9 @@ namespace Autotest { namespace Internal { -ITestParser *BoostTestFramework::createTestParser() const +ITestParser *BoostTestFramework::createTestParser() { - return new BoostTestParser; + return new BoostTestParser(this); } TestTreeItem *BoostTestFramework::createRootNode() const @@ -57,20 +55,5 @@ unsigned BoostTestFramework::priority() const return BoostTest::Constants::FRAMEWORK_PRIORITY; } -IFrameworkSettings *BoostTestFramework::createFrameworkSettings() const -{ - return new BoostTestSettings; -} - -Core::IOptionsPage *BoostTestFramework::createSettingsPage(QSharedPointer<IFrameworkSettings> settings) const -{ - return new BoostTestSettingsPage(settings, settingsId()); -} - -bool BoostTestFramework::hasFrameworkSettings() const -{ - return true; -} - } // namespace Internal } // namespace Autotest diff --git a/src/plugins/autotest/boost/boosttestframework.h b/src/plugins/autotest/boost/boosttestframework.h index dfe46dd0fe..ac011c422a 100644 --- a/src/plugins/autotest/boost/boosttestframework.h +++ b/src/plugins/autotest/boost/boosttestframework.h @@ -27,6 +27,9 @@ #include "../itestframework.h" +#include "boosttestsettings.h" +#include "boosttestsettingspage.h" + namespace Autotest { namespace Internal { @@ -34,14 +37,16 @@ class BoostTestFramework : public ITestFramework { public: BoostTestFramework() : ITestFramework(true) {} + +private: const char *name() const override; unsigned priority() const override; - IFrameworkSettings *createFrameworkSettings() const override; - Core::IOptionsPage *createSettingsPage(QSharedPointer<IFrameworkSettings> settings) const override; - bool hasFrameworkSettings() const override; -protected: - ITestParser *createTestParser() const override; + IFrameworkSettings *frameworkSettings() override { return &m_settings; } + ITestParser *createTestParser() override; TestTreeItem *createRootNode() const override; + + BoostTestSettings m_settings; + BoostTestSettingsPage m_settingsPage{&m_settings, settingsId()}; }; } // namespace Internal diff --git a/src/plugins/autotest/boost/boosttestparser.cpp b/src/plugins/autotest/boost/boosttestparser.cpp index 09c216c1b6..e6f85ce2d3 100644 --- a/src/plugins/autotest/boost/boosttestparser.cpp +++ b/src/plugins/autotest/boost/boosttestparser.cpp @@ -98,10 +98,10 @@ static bool hasBoostTestMacros(const CPlusPlus::Document::Ptr &doc) } static BoostTestParseResult *createParseResult(const QString &name, const QString &filePath, - const QString &projectFile, const Core::Id &id, + const QString &projectFile, ITestFramework *framework, TestTreeItem::Type type, const BoostTestInfo &info) { - BoostTestParseResult *partialSuite = new BoostTestParseResult(id); + BoostTestParseResult *partialSuite = new BoostTestParseResult(framework); partialSuite->itemType = type; partialSuite->fileName = filePath; partialSuite->name = info.fullName; @@ -117,7 +117,7 @@ static BoostTestParseResult *createParseResult(const QString &name, const QStrin static bool handleBoostTest(QFutureInterface<TestParseResultPtr> futureInterface, const CPlusPlus::Document::Ptr &doc, const CPlusPlus::Snapshot &snapshot, - const Core::Id &id) + ITestFramework *framework) { const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); const QString &filePath = doc->fileName(); @@ -139,7 +139,7 @@ static bool handleBoostTest(QFutureInterface<TestParseResultPtr> futureInterface BoostTestInfo firstSuite = suitesStates.first(); QStringList suites = firstSuite.fullName.split('/'); BoostTestParseResult *topLevelSuite = createParseResult(suites.first(), filePath, - projectFile, id, + projectFile, framework, TestTreeItem::TestSuite, firstSuite); BoostTestParseResult *currentSuite = topLevelSuite; @@ -148,7 +148,7 @@ static bool handleBoostTest(QFutureInterface<TestParseResultPtr> futureInterface firstSuite = suitesStates.first(); suites = firstSuite.fullName.split('/'); BoostTestParseResult *suiteResult = createParseResult(suites.last(), filePath, - projectFile, id, + projectFile, framework, TestTreeItem::TestSuite, firstSuite); currentSuite->children.append(suiteResult); @@ -161,7 +161,7 @@ static bool handleBoostTest(QFutureInterface<TestParseResultPtr> futureInterface locationAndType.m_suitesState.last().fullName + "::" + locationAndType.m_name, locationAndType.m_state, locationAndType.m_line}; BoostTestParseResult *funcResult = createParseResult(locationAndType.m_name, filePath, - projectFile, id, + projectFile, framework, locationAndType.m_type, tmpInfo); currentSuite->children.append(funcResult); @@ -177,7 +177,7 @@ bool BoostTestParser::processDocument(QFutureInterface<TestParseResultPtr> futur CPlusPlus::Document::Ptr doc = document(fileName); if (doc.isNull() || !includesBoostTest(doc, m_cppSnapshot) || !hasBoostTestMacros(doc)) return false; - return handleBoostTest(futureInterface, doc, m_cppSnapshot, id()); + return handleBoostTest(futureInterface, doc, m_cppSnapshot, framework()); } } // namespace Internal diff --git a/src/plugins/autotest/boost/boosttestparser.h b/src/plugins/autotest/boost/boosttestparser.h index 678b859cc9..bba9640ef2 100644 --- a/src/plugins/autotest/boost/boosttestparser.h +++ b/src/plugins/autotest/boost/boosttestparser.h @@ -34,7 +34,7 @@ namespace Internal { class BoostTestParseResult : public TestParseResult { public: - explicit BoostTestParseResult(const Core::Id &id) : TestParseResult(id) {} + explicit BoostTestParseResult(ITestFramework *framework) : TestParseResult(framework) {} TestTreeItem *createTestTreeItem() const override; // TODO special attributes/states (labeled, timeout,...?) BoostTestTreeItem::TestStates state = BoostTestTreeItem::Enabled; @@ -43,6 +43,7 @@ public: class BoostTestParser : public CppParser { public: + explicit BoostTestParser(ITestFramework *framework) : CppParser(framework) {} bool processDocument(QFutureInterface<TestParseResultPtr> futureInterface, const QString &fileName) override; }; diff --git a/src/plugins/autotest/boost/boosttestsettingspage.cpp b/src/plugins/autotest/boost/boosttestsettingspage.cpp index 28afad5c15..ea9d41a0d5 100644 --- a/src/plugins/autotest/boost/boosttestsettingspage.cpp +++ b/src/plugins/autotest/boost/boosttestsettingspage.cpp @@ -39,7 +39,7 @@ class BoostTestSettingsWidget : public Core::IOptionsPageWidget Q_DECLARE_TR_FUNCTIONS(Autotest::Internal::BoostTestSettingsWidget) public: - explicit BoostTestSettingsWidget(QSharedPointer<BoostTestSettings> settings); + explicit BoostTestSettingsWidget(BoostTestSettings *settings); void apply() final; @@ -49,10 +49,10 @@ public: private: void fillComboBoxes(); Ui::BoostSettingsPage m_ui; - QSharedPointer<BoostTestSettings> m_settings; + BoostTestSettings *m_settings; }; -BoostTestSettingsWidget::BoostTestSettingsWidget(QSharedPointer<BoostTestSettings> settings) +BoostTestSettingsWidget::BoostTestSettingsWidget(BoostTestSettings *settings) : m_settings(settings) { m_ui.setupUi(this); @@ -101,16 +101,13 @@ void BoostTestSettingsWidget::fillComboBoxes() m_ui.reportLevelCB->addItem("No", QVariant::fromValue(ReportLevel::No)); } -BoostTestSettingsPage::BoostTestSettingsPage(QSharedPointer<IFrameworkSettings> settings, - Core::Id settingsId) +BoostTestSettingsPage::BoostTestSettingsPage(BoostTestSettings *settings, Core::Id settingsId) { setId(settingsId); setCategory(Constants::AUTOTEST_SETTINGS_CATEGORY); setDisplayName(QCoreApplication::translate("BoostTestFramework", BoostTest::Constants::FRAMEWORK_SETTINGS_CATEGORY)); - setWidgetCreator([settings] { - return new BoostTestSettingsWidget(qSharedPointerCast<BoostTestSettings>(settings)); - }); + setWidgetCreator([settings] { return new BoostTestSettingsWidget(settings); }); } } // Internal diff --git a/src/plugins/autotest/boost/boosttestsettingspage.h b/src/plugins/autotest/boost/boosttestsettingspage.h index 27a7efd2c1..0c5340d91a 100644 --- a/src/plugins/autotest/boost/boosttestsettingspage.h +++ b/src/plugins/autotest/boost/boosttestsettingspage.h @@ -28,15 +28,14 @@ #include <coreplugin/dialogs/ioptionspage.h> namespace Autotest { - -class IFrameworkSettings; - namespace Internal { +class BoostTestSettings; + class BoostTestSettingsPage final : public Core::IOptionsPage { public: - BoostTestSettingsPage(QSharedPointer<IFrameworkSettings> settings, Core::Id settingsId); + BoostTestSettingsPage(BoostTestSettings *settings, Core::Id settingsId); }; } // Internal diff --git a/src/plugins/autotest/boost/boosttesttreeitem.cpp b/src/plugins/autotest/boost/boosttesttreeitem.cpp index 995331f625..d85fa439cf 100644 --- a/src/plugins/autotest/boost/boosttesttreeitem.cpp +++ b/src/plugins/autotest/boost/boosttesttreeitem.cpp @@ -74,7 +74,7 @@ TestTreeItem *BoostTestTreeItem::find(const TestParseResult *result) switch (type()) { case Root: - if (TestFrameworkManager::instance()->groupingEnabled(result->frameworkId)) { + if (result->framework->grouping()) { const QFileInfo fileInfo(bResult->fileName); const QFileInfo base(fileInfo.absolutePath()); for (int row = 0; row < childCount(); ++row) { diff --git a/src/plugins/autotest/gtest/gtestconfiguration.cpp b/src/plugins/autotest/gtest/gtestconfiguration.cpp index e662f3702f..eb5a829959 100644 --- a/src/plugins/autotest/gtest/gtestconfiguration.cpp +++ b/src/plugins/autotest/gtest/gtestconfiguration.cpp @@ -87,8 +87,8 @@ QStringList GTestConfiguration::argumentsForTestRunner(QStringList *omitted) con arguments << "--gtest_filter=" + testSets.join(':'); TestFrameworkManager *manager = TestFrameworkManager::instance(); - auto gSettings = qSharedPointerCast<GTestSettings>(manager->settingsForTestFramework(id)); - if (gSettings.isNull()) + auto gSettings = dynamic_cast<GTestSettings *>(manager->settingsForTestFramework(id)); + if (!gSettings) return arguments; if (gSettings->runDisabled) diff --git a/src/plugins/autotest/gtest/gtestframework.cpp b/src/plugins/autotest/gtest/gtestframework.cpp index 7e5ea7b681..ed46d7e4b7 100644 --- a/src/plugins/autotest/gtest/gtestframework.cpp +++ b/src/plugins/autotest/gtest/gtestframework.cpp @@ -24,8 +24,6 @@ ****************************************************************************/ #include "gtestframework.h" -#include "gtestsettings.h" -#include "gtestsettingspage.h" #include "gtesttreeitem.h" #include "gtestparser.h" #include "../testframeworkmanager.h" @@ -33,9 +31,17 @@ namespace Autotest { namespace Internal { -ITestParser *GTestFramework::createTestParser() const +static GTestSettings *g_settings; + +GTestFramework::GTestFramework() + : ITestFramework(true) +{ + g_settings = &m_settings; +} + +ITestParser *GTestFramework::createTestParser() { - return new GTestParser; + return new GTestParser(this); } TestTreeItem *GTestFramework::createRootNode() const @@ -56,29 +62,9 @@ unsigned GTestFramework::priority() const return GTest::Constants::FRAMEWORK_PRIORITY; } -IFrameworkSettings *GTestFramework::createFrameworkSettings() const -{ - return new GTestSettings; -} - -Core::IOptionsPage *GTestFramework::createSettingsPage(QSharedPointer<IFrameworkSettings> settings) const -{ - return new GTestSettingsPage(settings, settingsId()); -} - -bool GTestFramework::hasFrameworkSettings() const -{ - return true; -} - QString GTestFramework::currentGTestFilter() { - static const Core::Id id - = Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix(GTest::Constants::FRAMEWORK_NAME); - const auto manager = TestFrameworkManager::instance(); - - auto gSettings = qSharedPointerCast<GTestSettings>(manager->settingsForTestFramework(id)); - return gSettings.isNull() ? QString(GTest::Constants::DEFAULT_FILTER) : gSettings->gtestFilter; + return g_settings->gtestFilter; } QString GTestFramework::groupingToolTip() const @@ -90,14 +76,7 @@ QString GTestFramework::groupingToolTip() const GTest::Constants::GroupMode GTestFramework::groupMode() { - static const Core::Id id - = Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix(GTest::Constants::FRAMEWORK_NAME); - const auto manager = TestFrameworkManager::instance(); - if (!manager->groupingEnabled(id)) - return GTest::Constants::None; - - auto gSettings = qSharedPointerCast<GTestSettings>(manager->settingsForTestFramework(id)); - return gSettings.isNull() ? GTest::Constants::Directory : gSettings->groupMode; + return g_settings->groupMode; } } // namespace Internal diff --git a/src/plugins/autotest/gtest/gtestframework.h b/src/plugins/autotest/gtest/gtestframework.h index e6f1618c7b..b1f196419c 100644 --- a/src/plugins/autotest/gtest/gtestframework.h +++ b/src/plugins/autotest/gtest/gtestframework.h @@ -27,6 +27,8 @@ #include "../itestframework.h" #include "gtestconstants.h" +#include "gtestsettings.h" +#include "gtestsettingspage.h" namespace Autotest { namespace Internal { @@ -34,18 +36,21 @@ namespace Internal { class GTestFramework : public ITestFramework { public: - GTestFramework() : ITestFramework(true) {} - const char *name() const override; - unsigned priority() const override; - IFrameworkSettings *createFrameworkSettings() const override; - Core::IOptionsPage *createSettingsPage(QSharedPointer<IFrameworkSettings> settings) const override; - bool hasFrameworkSettings() const override; + GTestFramework(); + static GTest::Constants::GroupMode groupMode(); static QString currentGTestFilter(); + +private: + const char *name() const override; + unsigned priority() const override; QString groupingToolTip() const override; -protected: - ITestParser *createTestParser() const override; + IFrameworkSettings *frameworkSettings() override { return &m_settings; } + ITestParser *createTestParser() override; TestTreeItem *createRootNode() const override; + + GTestSettings m_settings; + GTestSettingsPage m_settingsPage{&m_settings, settingsId()}; }; } // namespace Internal diff --git a/src/plugins/autotest/gtest/gtestparser.cpp b/src/plugins/autotest/gtest/gtestparser.cpp index e5eecf44ff..e60a9a7d9d 100644 --- a/src/plugins/autotest/gtest/gtestparser.cpp +++ b/src/plugins/autotest/gtest/gtestparser.cpp @@ -89,7 +89,7 @@ static bool hasGTestNames(const CPlusPlus::Document::Ptr &document) static bool handleGTest(QFutureInterface<TestParseResultPtr> futureInterface, const CPlusPlus::Document::Ptr &doc, const CPlusPlus::Snapshot &snapshot, - const Core::Id &id) + ITestFramework *framework) { const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); const QString &filePath = doc->fileName(); @@ -109,7 +109,7 @@ static bool handleGTest(QFutureInterface<TestParseResultPtr> futureInterface, return false; // happens if shutting down while parsing for (const GTestCaseSpec &testSpec : result.keys()) { - GTestParseResult *parseResult = new GTestParseResult(id); + GTestParseResult *parseResult = new GTestParseResult(framework); parseResult->itemType = TestTreeItem::TestSuite; parseResult->fileName = filePath; parseResult->name = testSpec.testCaseName; @@ -119,7 +119,7 @@ static bool handleGTest(QFutureInterface<TestParseResultPtr> futureInterface, parseResult->proFile = proFile; for (const GTestCodeLocationAndType &location : result.value(testSpec)) { - GTestParseResult *testSet = new GTestParseResult(id); + GTestParseResult *testSet = new GTestParseResult(framework); testSet->name = location.m_name; testSet->fileName = filePath; testSet->line = location.m_line; @@ -142,7 +142,7 @@ bool GTestParser::processDocument(QFutureInterface<TestParseResultPtr> futureInt CPlusPlus::Document::Ptr doc = document(fileName); if (doc.isNull() || !includesGTest(doc, m_cppSnapshot) || !hasGTestNames(doc)) return false; - return handleGTest(futureInterface, doc, m_cppSnapshot, id()); + return handleGTest(futureInterface, doc, m_cppSnapshot, framework()); } } // namespace Internal diff --git a/src/plugins/autotest/gtest/gtestparser.h b/src/plugins/autotest/gtest/gtestparser.h index 67e2e074d4..781c9fe902 100644 --- a/src/plugins/autotest/gtest/gtestparser.h +++ b/src/plugins/autotest/gtest/gtestparser.h @@ -33,7 +33,7 @@ namespace Internal { class GTestParseResult : public TestParseResult { public: - explicit GTestParseResult(const Core::Id &id) : TestParseResult(id) {} + explicit GTestParseResult(ITestFramework *framework) : TestParseResult(framework) {} TestTreeItem *createTestTreeItem() const override; bool parameterized = false; bool typed = false; @@ -43,6 +43,7 @@ public: class GTestParser : public CppParser { public: + explicit GTestParser(ITestFramework *framework) : CppParser(framework) {} bool processDocument(QFutureInterface<TestParseResultPtr> futureInterface, const QString &fileName) override; }; diff --git a/src/plugins/autotest/gtest/gtestresult.cpp b/src/plugins/autotest/gtest/gtestresult.cpp index b2f3aae67b..ee3be04821 100644 --- a/src/plugins/autotest/gtest/gtestresult.cpp +++ b/src/plugins/autotest/gtest/gtestresult.cpp @@ -96,7 +96,9 @@ static QString normalizeTestName(const QString &testname) const TestTreeItem *GTestResult::findTestTreeItem() const { auto id = Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix(GTest::Constants::FRAMEWORK_NAME); - const TestTreeItem *rootNode = TestFrameworkManager::instance()->rootNodeForTestFramework(id); + ITestFramework *framework = TestFrameworkManager::frameworkForId(id); + QTC_ASSERT(framework, return nullptr); + const TestTreeItem *rootNode = framework->rootNode(); if (!rootNode) return nullptr; diff --git a/src/plugins/autotest/gtest/gtestsettingspage.cpp b/src/plugins/autotest/gtest/gtestsettingspage.cpp index f285fafde5..c788d201af 100644 --- a/src/plugins/autotest/gtest/gtestsettingspage.cpp +++ b/src/plugins/autotest/gtest/gtestsettingspage.cpp @@ -46,17 +46,17 @@ class GTestSettingsWidget final : public Core::IOptionsPageWidget Q_DECLARE_TR_FUNCTIONS(Autotest::Internal::GTestSettingsWidget) public: - explicit GTestSettingsWidget(const QSharedPointer<GTestSettings> &settings); + explicit GTestSettingsWidget(GTestSettings *settings); private: void apply() final; Ui::GTestSettingsPage m_ui; QString m_currentGTestFilter; - QSharedPointer<GTestSettings> m_settings; + GTestSettings *m_settings; }; -GTestSettingsWidget::GTestSettingsWidget(const QSharedPointer<GTestSettings> &settings) +GTestSettingsWidget::GTestSettingsWidget(GTestSettings *settings) : m_settings(settings) { m_ui.setupUi(this); @@ -109,14 +109,13 @@ void GTestSettingsWidget::apply() TestTreeModel::instance()->rebuild({id}); } -GTestSettingsPage::GTestSettingsPage(QSharedPointer<IFrameworkSettings> settings, - Core::Id settingsId) +GTestSettingsPage::GTestSettingsPage(GTestSettings *settings, Core::Id settingsId) { setId(settingsId); setCategory(Constants::AUTOTEST_SETTINGS_CATEGORY); setDisplayName(QCoreApplication::translate("GTestFramework", GTest::Constants::FRAMEWORK_SETTINGS_CATEGORY)); - setWidgetCreator([settings] { return new GTestSettingsWidget(qSharedPointerCast<GTestSettings>(settings)); }); + setWidgetCreator([settings] { return new GTestSettingsWidget(settings); }); } } // namespace Internal diff --git a/src/plugins/autotest/gtest/gtestsettingspage.h b/src/plugins/autotest/gtest/gtestsettingspage.h index d789fd4622..8cc20ae8b0 100644 --- a/src/plugins/autotest/gtest/gtestsettingspage.h +++ b/src/plugins/autotest/gtest/gtestsettingspage.h @@ -28,15 +28,14 @@ #include <coreplugin/dialogs/ioptionspage.h> namespace Autotest { - -class IFrameworkSettings; - namespace Internal { +class GTestSettings; + class GTestSettingsPage final : public Core::IOptionsPage { public: - GTestSettingsPage(QSharedPointer<IFrameworkSettings> settings, Core::Id settingsId); + GTestSettingsPage(GTestSettings *settings, Core::Id settingsId); }; } // namespace Internal diff --git a/src/plugins/autotest/gtest/gtesttreeitem.cpp b/src/plugins/autotest/gtest/gtesttreeitem.cpp index fdae1fa309..49d1138b8a 100644 --- a/src/plugins/autotest/gtest/gtesttreeitem.cpp +++ b/src/plugins/autotest/gtest/gtesttreeitem.cpp @@ -331,7 +331,7 @@ TestTreeItem *GTestTreeItem::find(const TestParseResult *result) states |= GTestTreeItem::Typed; switch (type()) { case Root: - if (TestFrameworkManager::instance()->groupingEnabled(result->frameworkId)) { + if (result->framework->grouping()) { if (GTestFramework::groupMode() == GTest::Constants::Directory) { const QFileInfo fileInfo(parseResult->fileName); const QFileInfo base(fileInfo.absolutePath()); diff --git a/src/plugins/autotest/itestframework.h b/src/plugins/autotest/itestframework.h index 11bdfa31cc..bc3e5cb386 100644 --- a/src/plugins/autotest/itestframework.h +++ b/src/plugins/autotest/itestframework.h @@ -28,8 +28,6 @@ #include "testtreeitem.h" #include "itestparser.h" -namespace Core { class IOptionsPage; } - namespace Autotest { class IFrameworkSettings; @@ -46,13 +44,8 @@ public: virtual const char *name() const = 0; virtual unsigned priority() const = 0; // should this be modifyable? - virtual bool hasFrameworkSettings() const { return false; } - virtual IFrameworkSettings *createFrameworkSettings() const { return nullptr; } - virtual Core::IOptionsPage *createSettingsPage(QSharedPointer<IFrameworkSettings> settings) const - { - Q_UNUSED(settings) - return nullptr; - } + + virtual IFrameworkSettings *frameworkSettings() { return nullptr; } TestTreeItem *rootNode() { if (!m_rootNode) @@ -69,6 +62,8 @@ public: Core::Id settingsId() const; + Core::Id id() const { return Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix(name()); } + bool active() const { return m_active; } void setActive(bool active) { m_active = active; } bool grouping() const { return m_grouping; } @@ -76,7 +71,7 @@ public: // framework specific tool tip to be displayed on the general settings page virtual QString groupingToolTip() const { return QString(); } protected: - virtual ITestParser *createTestParser() const = 0; + virtual ITestParser *createTestParser() = 0; virtual TestTreeItem *createRootNode() const = 0; private: @@ -86,4 +81,6 @@ private: bool m_grouping = false; }; +using TestFrameworks = QList<ITestFramework *>; + } // namespace Autotest diff --git a/src/plugins/autotest/itestparser.cpp b/src/plugins/autotest/itestparser.cpp index 316245cdee..335c56cbab 100644 --- a/src/plugins/autotest/itestparser.cpp +++ b/src/plugins/autotest/itestparser.cpp @@ -33,7 +33,8 @@ namespace Autotest { static CppParser *s_parserInstance = nullptr; -CppParser::CppParser() +CppParser::CppParser(ITestFramework *framework) + : ITestParser(framework) { s_parserInstance = this; } diff --git a/src/plugins/autotest/itestparser.h b/src/plugins/autotest/itestparser.h index d9a8c92801..e2ea592e09 100644 --- a/src/plugins/autotest/itestparser.h +++ b/src/plugins/autotest/itestparser.h @@ -35,16 +35,18 @@ namespace Autotest { +class ITestFramework; + class TestParseResult { public: - explicit TestParseResult(const Core::Id &id) : frameworkId(id) {} + explicit TestParseResult(ITestFramework *framework) : framework(framework) {} virtual ~TestParseResult() { qDeleteAll(children); } virtual TestTreeItem *createTestTreeItem() const = 0; QVector<TestParseResult *> children; - Core::Id frameworkId; + ITestFramework *framework; TestTreeItem::Type itemType = TestTreeItem::Root; QString displayName; QString fileName; @@ -59,22 +61,23 @@ using TestParseResultPtr = QSharedPointer<TestParseResult>; class ITestParser { public: + explicit ITestParser(ITestFramework *framework) : m_framework(framework) {} virtual ~ITestParser() { } virtual void init(const QStringList &filesToParse, bool fullParse) = 0; virtual bool processDocument(QFutureInterface<TestParseResultPtr> futureInterface, const QString &fileName) = 0; virtual void release() = 0; - void setId(const Core::Id &id) { m_id = id; } - Core::Id id() const { return m_id; } + + ITestFramework *framework() const { return m_framework; } private: - Core::Id m_id; + ITestFramework *m_framework; }; class CppParser : public ITestParser { public: - CppParser(); + explicit CppParser(ITestFramework *framework); void init(const QStringList &filesToParse, bool fullParse) override; static bool selectedForBuilding(const QString &fileName); static QByteArray getFileContent(const QString &filePath); diff --git a/src/plugins/autotest/projectsettingswidget.cpp b/src/plugins/autotest/projectsettingswidget.cpp index 4fb66be7f8..dd3a80ee89 100644 --- a/src/plugins/autotest/projectsettingswidget.cpp +++ b/src/plugins/autotest/projectsettingswidget.cpp @@ -105,16 +105,14 @@ ProjectTestSettingsWidget::ProjectTestSettingsWidget(ProjectExplorer::Project *p TestTreeModel::instance(), &TestTreeModel::synchronizeTestFrameworks); } -void ProjectTestSettingsWidget::populateFrameworks(const QMap<Core::Id, bool> &frameworks) +void ProjectTestSettingsWidget::populateFrameworks(const QMap<ITestFramework *, bool> &frameworks) { - TestFrameworkManager *frameworkManager = TestFrameworkManager::instance(); auto end = frameworks.cend(); for (auto it = frameworks.cbegin(); it != end; ++it) { - auto *item = new QTreeWidgetItem(m_activeFrameworks, - QStringList(frameworkManager->frameworkNameForId(it.key()))); + auto item = new QTreeWidgetItem(m_activeFrameworks, QStringList(QLatin1String(it.key()->name()))); item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable); item->setCheckState(0, it.value() ? Qt::Checked : Qt::Unchecked); - item->setData(0, FrameworkIdRole, it.key().toSetting()); + item->setData(0, FrameworkIdRole, it.key()->id().toSetting()); } } diff --git a/src/plugins/autotest/projectsettingswidget.h b/src/plugins/autotest/projectsettingswidget.h index 66da382f02..d921d56e88 100644 --- a/src/plugins/autotest/projectsettingswidget.h +++ b/src/plugins/autotest/projectsettingswidget.h @@ -34,10 +34,12 @@ class QTreeWidget; class QTreeWidgetItem; QT_END_NAMESPACE -namespace Core { class Id; } namespace ProjectExplorer { class Project; } namespace Autotest { + +class ITestFramework; + namespace Internal { class TestProjectSettings; @@ -49,7 +51,7 @@ public: explicit ProjectTestSettingsWidget(ProjectExplorer::Project *project, QWidget *parent = nullptr); private: - void populateFrameworks(const QMap<Core::Id, bool> &frameworks); + void populateFrameworks(const QMap<Autotest::ITestFramework *, bool> &frameworks); void onActiveFrameworkChanged(QTreeWidgetItem *item, int column); TestProjectSettings *m_projectSettings; QComboBox *m_useGlobalSettings = nullptr; diff --git a/src/plugins/autotest/qtest/qttest_utils.cpp b/src/plugins/autotest/qtest/qttest_utils.cpp index ff49155a98..6cf5fd679c 100644 --- a/src/plugins/autotest/qtest/qttest_utils.cpp +++ b/src/plugins/autotest/qtest/qttest_utils.cpp @@ -46,10 +46,10 @@ bool isQTestMacro(const QByteArray ¯o) return valid.contains(macro); } -QHash<QString, QString> testCaseNamesForFiles(const Core::Id &id, const QStringList &files) +QHash<QString, QString> testCaseNamesForFiles(ITestFramework *framework, const QStringList &files) { QHash<QString, QString> result; - TestTreeItem *rootNode = TestFrameworkManager::instance()->rootNodeForTestFramework(id); + TestTreeItem *rootNode = framework->rootNode(); QTC_ASSERT(rootNode, return result); rootNode->forFirstLevelChildren([&result, &files](TestTreeItem *child) { @@ -63,10 +63,10 @@ QHash<QString, QString> testCaseNamesForFiles(const Core::Id &id, const QStringL return result; } -QMultiHash<QString, QString> alternativeFiles(const Core::Id &id, const QStringList &files) +QMultiHash<QString, QString> alternativeFiles(ITestFramework *framework, const QStringList &files) { QMultiHash<QString, QString> result; - TestTreeItem *rootNode = TestFrameworkManager::instance()->rootNodeForTestFramework(id); + TestTreeItem *rootNode = framework->rootNode(); QTC_ASSERT(rootNode, return result); rootNode->forFirstLevelChildren([&result, &files](TestTreeItem *child) { diff --git a/src/plugins/autotest/qtest/qttest_utils.h b/src/plugins/autotest/qtest/qttest_utils.h index 23820c05d9..4d13df0d1e 100644 --- a/src/plugins/autotest/qtest/qttest_utils.h +++ b/src/plugins/autotest/qtest/qttest_utils.h @@ -31,12 +31,15 @@ namespace Core { class Id; } namespace Utils { class Environment; } namespace Autotest { + +class ITestFramework; + namespace Internal { namespace QTestUtils { bool isQTestMacro(const QByteArray ¯o); -QHash<QString, QString> testCaseNamesForFiles(const Core::Id &id, const QStringList &files); -QMultiHash<QString, QString> alternativeFiles(const Core::Id &id, const QStringList &files); +QHash<QString, QString> testCaseNamesForFiles(ITestFramework *framework, const QStringList &files); +QMultiHash<QString, QString> alternativeFiles(ITestFramework *framework, const QStringList &files); QStringList filterInterfering(const QStringList &provided, QStringList *omitted, bool isQuickTest); Utils::Environment prepareBasicEnvironment(const Utils::Environment &env); diff --git a/src/plugins/autotest/qtest/qttestconfiguration.cpp b/src/plugins/autotest/qtest/qttestconfiguration.cpp index 1212f3b852..81618dfb14 100644 --- a/src/plugins/autotest/qtest/qttestconfiguration.cpp +++ b/src/plugins/autotest/qtest/qttestconfiguration.cpp @@ -41,7 +41,7 @@ TestOutputReader *QtTestConfiguration::outputReader(const QFutureInterface<TestR static const Core::Id id = Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix(QtTest::Constants::FRAMEWORK_NAME); TestFrameworkManager *manager = TestFrameworkManager::instance(); - auto qtSettings = qSharedPointerCast<QtTestSettings>(manager->settingsForTestFramework(id)); + auto qtSettings = dynamic_cast<QtTestSettings *>(manager->settingsForTestFramework(id)); const QtTestOutputReader::OutputMode mode = qtSettings && qtSettings->useXMLOutput ? QtTestOutputReader::XML : QtTestOutputReader::PlainText; @@ -60,8 +60,8 @@ QStringList QtTestConfiguration::argumentsForTestRunner(QStringList *omitted) co omitted, false)); } TestFrameworkManager *manager = TestFrameworkManager::instance(); - auto qtSettings = qSharedPointerCast<QtTestSettings>(manager->settingsForTestFramework(id)); - if (qtSettings.isNull()) + auto qtSettings = dynamic_cast<QtTestSettings *>(manager->settingsForTestFramework(id)); + if (!qtSettings) return arguments; if (qtSettings->useXMLOutput) arguments << "-xml"; diff --git a/src/plugins/autotest/qtest/qttestframework.cpp b/src/plugins/autotest/qtest/qttestframework.cpp index bbf42a844a..0248407967 100644 --- a/src/plugins/autotest/qtest/qttestframework.cpp +++ b/src/plugins/autotest/qtest/qttestframework.cpp @@ -26,16 +26,14 @@ #include "qttestframework.h" #include "qttestconstants.h" #include "qttestparser.h" -#include "qttestsettings.h" -#include "qttestsettingspage.h" #include "qttesttreeitem.h" namespace Autotest { namespace Internal { -ITestParser *QtTestFramework::createTestParser() const +ITestParser *QtTestFramework::createTestParser() { - return new QtTestParser; + return new QtTestParser(this); } TestTreeItem *QtTestFramework::createRootNode() const @@ -46,21 +44,6 @@ TestTreeItem *QtTestFramework::createRootNode() const QString(), TestTreeItem::Root); } -IFrameworkSettings *QtTestFramework::createFrameworkSettings() const -{ - return new QtTestSettings; -} - -Core::IOptionsPage *QtTestFramework::createSettingsPage(QSharedPointer<IFrameworkSettings> settings) const -{ - return new QtTestSettingsPage(settings, settingsId()); -} - -bool QtTestFramework::hasFrameworkSettings() const -{ - return true; -} - const char *QtTestFramework::name() const { return QtTest::Constants::FRAMEWORK_NAME; diff --git a/src/plugins/autotest/qtest/qttestframework.h b/src/plugins/autotest/qtest/qttestframework.h index a6cfcb9f2a..803079f593 100644 --- a/src/plugins/autotest/qtest/qttestframework.h +++ b/src/plugins/autotest/qtest/qttestframework.h @@ -27,6 +27,9 @@ #include "../itestframework.h" +#include "qttestsettings.h" +#include "qttestsettingspage.h" + namespace Autotest { namespace Internal { @@ -34,15 +37,16 @@ class QtTestFramework : public ITestFramework { public: QtTestFramework() : ITestFramework(true) {} + +private: const char *name() const override; unsigned priority() const override; - IFrameworkSettings *createFrameworkSettings() const override; - Core::IOptionsPage *createSettingsPage(QSharedPointer<IFrameworkSettings> settings) const override; - bool hasFrameworkSettings() const override; - -protected: - ITestParser *createTestParser() const override; + ITestParser *createTestParser() override; TestTreeItem *createRootNode() const override; + IFrameworkSettings *frameworkSettings() override { return &m_settings; } + + QtTestSettings m_settings; + QtTestSettingsPage m_settingsPage{&m_settings, settingsId()}; }; } // namespace Internal diff --git a/src/plugins/autotest/qtest/qttestparser.cpp b/src/plugins/autotest/qtest/qttestparser.cpp index 564be5df26..41a8463cc6 100644 --- a/src/plugins/autotest/qtest/qttestparser.cpp +++ b/src/plugins/autotest/qtest/qttestparser.cpp @@ -284,7 +284,7 @@ static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface, const CPlusPlus::Snapshot &snapshot, const QString &oldTestCaseName, const QStringList &alternativeFiles, - const Core::Id &id) + ITestFramework *framework) { const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); const QString &fileName = document->fileName(); @@ -321,7 +321,7 @@ static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface, for (const QString &file : files) Utils::addToHash(&dataTags, checkForDataTags(file, snapshot)); - QtTestParseResult *parseResult = new QtTestParseResult(id); + QtTestParseResult *parseResult = new QtTestParseResult(framework); parseResult->itemType = TestTreeItem::TestCase; parseResult->fileName = declaringDoc->fileName(); parseResult->name = testCaseName; @@ -338,7 +338,7 @@ static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface, const QtTestCodeLocationAndType &location = it.value(); QString functionName = it.key(); functionName = functionName.mid(functionName.lastIndexOf(':') + 1); - QtTestParseResult *func = new QtTestParseResult(id); + QtTestParseResult *func = new QtTestParseResult(framework); func->itemType = location.m_type; func->name = testCaseName + "::" + functionName; func->displayName = functionName; @@ -349,7 +349,7 @@ static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface, const QtTestCodeLocationList &tagLocations = tagLocationsFor(func, dataTags); for (const QtTestCodeLocationAndType &tag : tagLocations) { - QtTestParseResult *dataTag = new QtTestParseResult(id); + QtTestParseResult *dataTag = new QtTestParseResult(framework); dataTag->itemType = tag.m_type; dataTag->name = tag.m_name; dataTag->displayName = tag.m_name; @@ -372,8 +372,8 @@ static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface, void QtTestParser::init(const QStringList &filesToParse, bool fullParse) { if (!fullParse) { // in a full parse cached information might lead to wrong results - m_testCaseNames = QTestUtils::testCaseNamesForFiles(id(), filesToParse); - m_alternativeFiles = QTestUtils::alternativeFiles(id(), filesToParse); + m_testCaseNames = QTestUtils::testCaseNamesForFiles(framework(), filesToParse); + m_alternativeFiles = QTestUtils::alternativeFiles(framework(), filesToParse); } CppParser::init(filesToParse, fullParse); } @@ -396,7 +396,7 @@ bool QtTestParser::processDocument(QFutureInterface<TestParseResultPtr> futureIn if ((!includesQtTest(doc, m_cppSnapshot) || !qtTestLibDefined(fileName)) && oldName.isEmpty()) return false; - return handleQtTest(futureInterface, doc, m_cppSnapshot, oldName, alternativeFiles, id()); + return handleQtTest(futureInterface, doc, m_cppSnapshot, oldName, alternativeFiles, framework()); } } // namespace Internal diff --git a/src/plugins/autotest/qtest/qttestparser.h b/src/plugins/autotest/qtest/qttestparser.h index 9cf0709c7d..dac8a5d094 100644 --- a/src/plugins/autotest/qtest/qttestparser.h +++ b/src/plugins/autotest/qtest/qttestparser.h @@ -33,7 +33,7 @@ namespace Internal { class QtTestParseResult : public TestParseResult { public: - explicit QtTestParseResult(const Core::Id &id) : TestParseResult(id) {} + explicit QtTestParseResult(ITestFramework *framework) : TestParseResult(framework) {} void setInherited(bool inherited) { m_inherited = inherited; } bool inherited() const { return m_inherited; } TestTreeItem *createTestTreeItem() const override; @@ -44,6 +44,8 @@ private: class QtTestParser : public CppParser { public: + explicit QtTestParser(ITestFramework *framework) : CppParser(framework) {} + void init(const QStringList &filesToParse, bool fullParse) override; void release() override; bool processDocument(QFutureInterface<TestParseResultPtr> futureInterface, diff --git a/src/plugins/autotest/qtest/qttestresult.cpp b/src/plugins/autotest/qtest/qttestresult.cpp index 65ec0c8270..38fefa171b 100644 --- a/src/plugins/autotest/qtest/qttestresult.cpp +++ b/src/plugins/autotest/qtest/qttestresult.cpp @@ -136,7 +136,9 @@ const TestTreeItem *QtTestResult::findTestTreeItem() const id = Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix(QtTest::Constants::FRAMEWORK_NAME); else id = Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix(QuickTest::Constants::FRAMEWORK_NAME); - const TestTreeItem *rootNode = TestFrameworkManager::instance()->rootNodeForTestFramework(id); + ITestFramework *framework = TestFrameworkManager::frameworkForId(id); + QTC_ASSERT(framework, return nullptr); + const TestTreeItem *rootNode = framework->rootNode(); QTC_ASSERT(rootNode, return nullptr); const auto item = rootNode->findAnyChild([this](const Utils::TreeItem *item) { diff --git a/src/plugins/autotest/qtest/qttestsettingspage.cpp b/src/plugins/autotest/qtest/qttestsettingspage.cpp index fcc01853a1..02a74cb344 100644 --- a/src/plugins/autotest/qtest/qttestsettingspage.cpp +++ b/src/plugins/autotest/qtest/qttestsettingspage.cpp @@ -41,16 +41,16 @@ class QtTestSettingsWidget final : public Core::IOptionsPageWidget Q_DECLARE_TR_FUNCTIONS(Autotest::Internal::QtTestSettingsWidget) public: - explicit QtTestSettingsWidget(QSharedPointer<QtTestSettings> settings); + explicit QtTestSettingsWidget(QtTestSettings *settings); void apply() final; private: Ui::QtTestSettingsPage m_ui; - QSharedPointer<QtTestSettings> m_settings; + QtTestSettings *m_settings; }; -QtTestSettingsWidget::QtTestSettingsWidget(QSharedPointer<QtTestSettings> settings) +QtTestSettingsWidget::QtTestSettingsWidget(QtTestSettings *settings) : m_settings(settings) { m_ui.setupUi(this); @@ -100,16 +100,13 @@ void QtTestSettingsWidget::apply() m_settings->toSettings(Core::ICore::settings()); } -QtTestSettingsPage::QtTestSettingsPage(QSharedPointer<IFrameworkSettings> settings, - Core::Id settingsId) +QtTestSettingsPage::QtTestSettingsPage(QtTestSettings *settings, Core::Id settingsId) { setId(settingsId); setCategory(Constants::AUTOTEST_SETTINGS_CATEGORY); setDisplayName(QCoreApplication::translate("QtTestFramework", QtTest::Constants::FRAMEWORK_SETTINGS_CATEGORY)); - setWidgetCreator([settings] { - return new QtTestSettingsWidget(qSharedPointerCast<QtTestSettings>(settings)); - }); + setWidgetCreator([settings] { return new QtTestSettingsWidget(settings); }); } } // namespace Internal diff --git a/src/plugins/autotest/qtest/qttestsettingspage.h b/src/plugins/autotest/qtest/qttestsettingspage.h index 6818ea441c..3ed9c76eaa 100644 --- a/src/plugins/autotest/qtest/qttestsettingspage.h +++ b/src/plugins/autotest/qtest/qttestsettingspage.h @@ -28,15 +28,14 @@ #include <coreplugin/dialogs/ioptionspage.h> namespace Autotest { - -class IFrameworkSettings; - namespace Internal { +class QtTestSettings; + class QtTestSettingsPage final : public Core::IOptionsPage { public: - QtTestSettingsPage(QSharedPointer<IFrameworkSettings> settings, Core::Id settingsId); + QtTestSettingsPage(QtTestSettings *settings, Core::Id settingsId); }; } // namespace Internal diff --git a/src/plugins/autotest/qtest/qttesttreeitem.cpp b/src/plugins/autotest/qtest/qttesttreeitem.cpp index 7069e29961..df15f38558 100644 --- a/src/plugins/autotest/qtest/qttesttreeitem.cpp +++ b/src/plugins/autotest/qtest/qttesttreeitem.cpp @@ -269,7 +269,7 @@ TestTreeItem *QtTestTreeItem::find(const TestParseResult *result) switch (type()) { case Root: - if (TestFrameworkManager::instance()->groupingEnabled(result->frameworkId)) { + if (result->framework->grouping()) { const QString path = QFileInfo(result->fileName).absolutePath(); for (int row = 0; row < childCount(); ++row) { TestTreeItem *group = childAt(row); diff --git a/src/plugins/autotest/quick/quicktest_utils.cpp b/src/plugins/autotest/quick/quicktest_utils.cpp index 92a36a9a19..eab91c9324 100644 --- a/src/plugins/autotest/quick/quicktest_utils.cpp +++ b/src/plugins/autotest/quick/quicktest_utils.cpp @@ -43,10 +43,10 @@ bool isQuickTestMacro(const QByteArray ¯o) return valid.contains(macro); } -QHash<QString, QString> proFilesForQmlFiles(const Core::Id &id, const QStringList &files) +QHash<QString, QString> proFilesForQmlFiles(ITestFramework *framework, const QStringList &files) { QHash<QString, QString> result; - TestTreeItem *rootNode = TestFrameworkManager::instance()->rootNodeForTestFramework(id); + TestTreeItem *rootNode = framework->rootNode(); QTC_ASSERT(rootNode, return result); if (files.isEmpty()) diff --git a/src/plugins/autotest/quick/quicktest_utils.h b/src/plugins/autotest/quick/quicktest_utils.h index af5cfdb7bf..8eca2a2569 100644 --- a/src/plugins/autotest/quick/quicktest_utils.h +++ b/src/plugins/autotest/quick/quicktest_utils.h @@ -30,11 +30,14 @@ namespace Core { class Id; } namespace Autotest { + +class ITestFramework; + namespace Internal { namespace QuickTestUtils { bool isQuickTestMacro(const QByteArray ¯o); -QHash<QString, QString> proFilesForQmlFiles(const Core::Id &id, const QStringList &files); +QHash<QString, QString> proFilesForQmlFiles(ITestFramework *framework, const QStringList &files); } // namespace QuickTestUtils } // namespace Internal diff --git a/src/plugins/autotest/quick/quicktestconfiguration.cpp b/src/plugins/autotest/quick/quicktestconfiguration.cpp index 57d075fe7d..c2ae540b43 100644 --- a/src/plugins/autotest/quick/quicktestconfiguration.cpp +++ b/src/plugins/autotest/quick/quicktestconfiguration.cpp @@ -46,7 +46,7 @@ TestOutputReader *QuickTestConfiguration::outputReader(const QFutureInterface<Te static const Core::Id id = Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix(QtTest::Constants::FRAMEWORK_NAME); TestFrameworkManager *manager = TestFrameworkManager::instance(); - auto qtSettings = qSharedPointerCast<QtTestSettings>(manager->settingsForTestFramework(id)); + auto qtSettings = dynamic_cast<QtTestSettings *>(manager->settingsForTestFramework(id)); const QtTestOutputReader::OutputMode mode = qtSettings && qtSettings->useXMLOutput ? QtTestOutputReader::XML : QtTestOutputReader::PlainText; @@ -67,8 +67,8 @@ QStringList QuickTestConfiguration::argumentsForTestRunner(QStringList *omitted) } TestFrameworkManager *manager = TestFrameworkManager::instance(); - auto qtSettings = qSharedPointerCast<QtTestSettings>(manager->settingsForTestFramework(id)); - if (qtSettings.isNull()) + auto qtSettings = dynamic_cast<QtTestSettings *>(manager->settingsForTestFramework(id)); + if (!qtSettings) return arguments; if (qtSettings->useXMLOutput) arguments << "-xml"; diff --git a/src/plugins/autotest/quick/quicktestframework.cpp b/src/plugins/autotest/quick/quicktestframework.cpp index 81642ae6fd..69dd5eb7c7 100644 --- a/src/plugins/autotest/quick/quicktestframework.cpp +++ b/src/plugins/autotest/quick/quicktestframework.cpp @@ -30,9 +30,9 @@ namespace Autotest { namespace Internal { -ITestParser *QuickTestFramework::createTestParser() const +ITestParser *QuickTestFramework::createTestParser() { - return new QuickTestParser; + return new QuickTestParser(this); } TestTreeItem *QuickTestFramework::createRootNode() const diff --git a/src/plugins/autotest/quick/quicktestframework.h b/src/plugins/autotest/quick/quicktestframework.h index 80befb53d1..27982e8a2a 100644 --- a/src/plugins/autotest/quick/quicktestframework.h +++ b/src/plugins/autotest/quick/quicktestframework.h @@ -46,7 +46,7 @@ public: unsigned priority() const override; protected: - ITestParser *createTestParser() const override; + ITestParser *createTestParser() override; TestTreeItem *createRootNode() const override; }; diff --git a/src/plugins/autotest/quick/quicktestparser.cpp b/src/plugins/autotest/quick/quicktestparser.cpp index 478735048c..053e9c88b1 100644 --- a/src/plugins/autotest/quick/quicktestparser.cpp +++ b/src/plugins/autotest/quick/quicktestparser.cpp @@ -179,7 +179,7 @@ QList<Document::Ptr> QuickTestParser::scanDirectoryForQuickTestQmlFiles(const QS static bool checkQmlDocumentForQuickTestCode(QFutureInterface<TestParseResultPtr> futureInterface, const Document::Ptr &qmlJSDoc, - const Core::Id &id, + ITestFramework *framework, const QString &proFile = QString()) { if (qmlJSDoc.isNull()) @@ -197,7 +197,7 @@ static bool checkQmlDocumentForQuickTestCode(QFutureInterface<TestParseResultPtr for (const QuickTestCaseSpec &testCase : testCases) { const QString testCaseName = testCase.m_caseName; - QuickTestParseResult *parseResult = new QuickTestParseResult(id); + QuickTestParseResult *parseResult = new QuickTestParseResult(framework); parseResult->proFile = proFile; parseResult->itemType = TestTreeItem::TestCase; if (!testCaseName.isEmpty()) { @@ -208,7 +208,7 @@ static bool checkQmlDocumentForQuickTestCode(QFutureInterface<TestParseResultPtr } for (auto function : testCase.m_functions) { - QuickTestParseResult *funcResult = new QuickTestParseResult(id); + QuickTestParseResult *funcResult = new QuickTestParseResult(framework); funcResult->name = function.m_functionName; funcResult->displayName = function.m_functionName; funcResult->itemType = function.m_locationAndType.m_type; @@ -227,7 +227,7 @@ static bool checkQmlDocumentForQuickTestCode(QFutureInterface<TestParseResultPtr bool QuickTestParser::handleQtQuickTest(QFutureInterface<TestParseResultPtr> futureInterface, CPlusPlus::Document::Ptr document, - const Core::Id &id) + ITestFramework *framework) { const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); if (quickTestName(document, m_cppSnapshot).isEmpty()) @@ -250,7 +250,7 @@ bool QuickTestParser::handleQtQuickTest(QFutureInterface<TestParseResultPtr> fut for (const Document::Ptr &qmlJSDoc : qmlDocs) { if (futureInterface.isCanceled()) break; - result |= checkQmlDocumentForQuickTestCode(futureInterface, qmlJSDoc, id, proFile); + result |= checkQmlDocumentForQuickTestCode(futureInterface, qmlJSDoc, framework, proFile); } return result; } @@ -298,8 +298,8 @@ void QuickTestParser::doUpdateWatchPaths(const QStringList &directories) } } -QuickTestParser::QuickTestParser() - : CppParser() +QuickTestParser::QuickTestParser(ITestFramework *framework) + : CppParser(framework) { connect(ProjectExplorer::SessionManager::instance(), &ProjectExplorer::SessionManager::startupProjectChanged, [this] { @@ -319,7 +319,7 @@ void QuickTestParser::init(const QStringList &filesToParse, bool fullParse) m_qmlSnapshot = QmlJSTools::Internal::ModelManager::instance()->snapshot(); if (!fullParse) { // in a full parse we get the correct entry points by the respective main - m_proFilesForQmlFiles = QuickTestUtils::proFilesForQmlFiles(id(), filesToParse); + m_proFilesForQmlFiles = QuickTestUtils::proFilesForQmlFiles(framework(), filesToParse); // get rid of cached main cpp files that are going to get processed anyhow for (const QString &file : filesToParse) { if (m_mainCppFiles.contains(file)) { @@ -350,14 +350,14 @@ bool QuickTestParser::processDocument(QFutureInterface<TestParseResultPtr> futur if (proFile.isEmpty()) return false; Document::Ptr qmlJSDoc = m_qmlSnapshot.document(fileName); - return checkQmlDocumentForQuickTestCode(futureInterface, qmlJSDoc, id(), proFile); + return checkQmlDocumentForQuickTestCode(futureInterface, qmlJSDoc, framework(), proFile); } if (!m_cppSnapshot.contains(fileName) || !selectedForBuilding(fileName)) return false; CPlusPlus::Document::Ptr document = m_cppSnapshot.find(fileName).value(); if (!includesQtQuickTest(document, m_cppSnapshot)) return false; - return handleQtQuickTest(futureInterface, document, id()); + return handleQtQuickTest(futureInterface, document, framework()); } QString QuickTestParser::projectFileForMainCppFile(const QString &fileName) const diff --git a/src/plugins/autotest/quick/quicktestparser.h b/src/plugins/autotest/quick/quicktestparser.h index c05fa607dd..21e7667832 100644 --- a/src/plugins/autotest/quick/quicktestparser.h +++ b/src/plugins/autotest/quick/quicktestparser.h @@ -37,7 +37,7 @@ namespace Internal { class QuickTestParseResult : public TestParseResult { public: - explicit QuickTestParseResult(const Core::Id &id) : TestParseResult(id) {} + explicit QuickTestParseResult(ITestFramework *framework) : TestParseResult(framework) {} TestTreeItem *createTestTreeItem() const override; }; @@ -45,7 +45,7 @@ class QuickTestParser : public QObject, public CppParser { Q_OBJECT public: - QuickTestParser(); + explicit QuickTestParser(ITestFramework *framework); void init(const QStringList &filesToParse, bool fullParse) override; void release() override; bool processDocument(QFutureInterface<TestParseResultPtr> futureInterface, @@ -55,7 +55,7 @@ signals: void updateWatchPaths(const QStringList &directories) const; private: bool handleQtQuickTest(QFutureInterface<TestParseResultPtr> futureInterface, - CPlusPlus::Document::Ptr document, const Core::Id &id); + CPlusPlus::Document::Ptr document, ITestFramework *framework); void handleDirectoryChanged(const QString &directory); void doUpdateWatchPaths(const QStringList &directories); QList<QmlJS::Document::Ptr> scanDirectoryForQuickTestQmlFiles(const QString &srcDir) const; diff --git a/src/plugins/autotest/quick/quicktesttreeitem.cpp b/src/plugins/autotest/quick/quicktesttreeitem.cpp index bb09159af1..9675b05719 100644 --- a/src/plugins/autotest/quick/quicktesttreeitem.cpp +++ b/src/plugins/autotest/quick/quicktesttreeitem.cpp @@ -318,7 +318,7 @@ TestTreeItem *QuickTestTreeItem::find(const TestParseResult *result) case Root: if (result->name.isEmpty()) return unnamedQuickTests(); - if (TestFrameworkManager::instance()->groupingEnabled(result->frameworkId)) { + if (result->framework->grouping()) { const QString path = QFileInfo(result->fileName).absolutePath(); TestTreeItem *group = findFirstLevelChild([path](TestTreeItem *group) { return group->filePath() == path; @@ -433,11 +433,12 @@ void QuickTestTreeItem::markForRemovalRecursively(const QString &filePath) static const Core::Id id = Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix( QuickTest::Constants::FRAMEWORK_NAME); TestTreeItem::markForRemovalRecursively(filePath); - auto parser = dynamic_cast<QuickTestParser *>(TestFrameworkManager::instance() - ->testParserForTestFramework(id)); + ITestFramework *framework = TestFrameworkManager::frameworkForId(id); + QTC_ASSERT(framework, return); + auto parser = dynamic_cast<QuickTestParser *>(framework->testParser()); const QString proFile = parser->projectFileForMainCppFile(filePath); if (!proFile.isEmpty()) { - TestTreeItem *root = TestFrameworkManager::instance()->rootNodeForTestFramework(id); + TestTreeItem *root = framework->rootNode(); root->forAllChildren([proFile](TestTreeItem *it) { if (it->proFile() == proFile) it->markForRemoval(true); diff --git a/src/plugins/autotest/testcodeparser.cpp b/src/plugins/autotest/testcodeparser.cpp index deb5085ade..e5336a9bda 100644 --- a/src/plugins/autotest/testcodeparser.cpp +++ b/src/plugins/autotest/testcodeparser.cpp @@ -110,7 +110,7 @@ void TestCodeParser::setState(State state) } } -void TestCodeParser::syncTestFrameworks(const QList<Core::Id> &frameworkIds) +void TestCodeParser::syncTestFrameworks(const QList<ITestFramework *> &frameworks) { if (m_parserState != Idle) { // there's a running parse @@ -119,10 +119,9 @@ void TestCodeParser::syncTestFrameworks(const QList<Core::Id> &frameworkIds) Core::ProgressManager::instance()->cancelTasks(Constants::TASK_PARSE); } m_testCodeParsers.clear(); - TestFrameworkManager *frameworkManager = TestFrameworkManager::instance(); - qCDebug(LOG) << "Setting" << frameworkIds << "as current parsers"; - for (const Core::Id &id : frameworkIds) { - ITestParser *testParser = frameworkManager->testParserForTestFramework(id); + qCDebug(LOG) << "Setting" << frameworks << "as current parsers"; + for (ITestFramework *framework : frameworks) { + ITestParser *testParser = framework->testParser(); QTC_ASSERT(testParser, continue); m_testCodeParsers.append(testParser); } @@ -133,7 +132,7 @@ void TestCodeParser::emitUpdateTestTree(ITestParser *parser) if (m_testCodeParsers.isEmpty()) return; if (parser) - m_updateParsers.insert(parser->id()); + m_updateParsers.insert(parser->framework()); else m_updateParsers.clear(); if (m_singleShotScheduled) { @@ -146,18 +145,18 @@ void TestCodeParser::emitUpdateTestTree(ITestParser *parser) QTimer::singleShot(1000, this, [this]() { updateTestTree(m_updateParsers); }); } -void TestCodeParser::updateTestTree(const QSet<Core::Id> &frameworkIds) +void TestCodeParser::updateTestTree(const QSet<ITestFramework *> &frameworks) { m_singleShotScheduled = false; if (m_codeModelParsing) { m_fullUpdatePostponed = true; m_partialUpdatePostponed = false; m_postponedFiles.clear(); - if (frameworkIds.isEmpty()) { + if (frameworks.isEmpty()) { m_updateParsers.clear(); } else { - for (const Core::Id &id : frameworkIds) - m_updateParsers.insert(id); + for (ITestFramework *framework : frameworks) + m_updateParsers.insert(framework); } return; } @@ -167,11 +166,8 @@ void TestCodeParser::updateTestTree(const QSet<Core::Id> &frameworkIds) m_fullUpdatePostponed = false; qCDebug(LOG) << "calling scanForTests (updateTestTree)"; - QList<Core::Id> sortedFrameworks = Utils::toList(frameworkIds); - Utils::sort(sortedFrameworks, [manager = TestFrameworkManager::instance()] - (const Core::Id &lhs, const Core::Id &rhs) { - return manager->priority(lhs) < manager->priority(rhs); - }); + TestFrameworks sortedFrameworks = Utils::toList(frameworks); + Utils::sort(sortedFrameworks, &ITestFramework::priority); scanForTests(QStringList(), sortedFrameworks); } @@ -307,7 +303,7 @@ static void parseFileForTests(const QList<ITestParser *> &parsers, } } -void TestCodeParser::scanForTests(const QStringList &fileList, const QList<Core::Id> &parserIds) +void TestCodeParser::scanForTests(const QStringList &fileList, const QList<ITestFramework *> &parsers) { if (m_parserState == Shutdown || m_testCodeParsers.isEmpty()) return; @@ -341,23 +337,21 @@ void TestCodeParser::scanForTests(const QStringList &fileList, const QList<Core: } parsingHasFailed = false; - TestFrameworkManager *manager = TestFrameworkManager::instance(); if (isFullParse) { // remove qml files as they will be found automatically by the referencing cpp file list = Utils::filtered(list, [] (const QString &fn) { return !fn.endsWith(".qml"); }); - if (!parserIds.isEmpty()) { - for (const Core::Id &id : parserIds) - manager->rootNodeForTestFramework(id)->markForRemovalRecursively(true); + if (!parsers.isEmpty()) { + for (ITestFramework *framework : parsers) + framework->rootNode()->markForRemovalRecursively(true); } else { m_model->markAllForRemoval(); } - } else if (!parserIds.isEmpty()) { - for (const Core::Id &id : parserIds) { - TestTreeItem *root = manager->rootNodeForTestFramework(id); + } else if (!parsers.isEmpty()) { + for (ITestFramework *framework : parsers) { for (const QString &filePath : list) - root->markForRemovalRecursively(filePath); + framework->rootNode()->markForRemovalRecursively(filePath); } } else { for (const QString &filePath : list) @@ -368,10 +362,8 @@ void TestCodeParser::scanForTests(const QStringList &fileList, const QList<Core: // use only a single parser or all current active? const QList<ITestParser *> codeParsers - = parserIds.isEmpty() ? m_testCodeParsers - : Utils::transform(parserIds, [](const Core::Id &id) { - return TestFrameworkManager::instance()->testParserForTestFramework(id); - }); + = parsers.isEmpty() ? m_testCodeParsers + : Utils::transform(parsers, &ITestFramework::testParser); qCDebug(LOG) << QDateTime::currentDateTime().toString("hh:mm:ss.zzz") << "StartParsing"; for (ITestParser *parser : codeParsers) parser->init(list, isFullParse); diff --git a/src/plugins/autotest/testcodeparser.h b/src/plugins/autotest/testcodeparser.h index 867a6349e6..57b65f0633 100644 --- a/src/plugins/autotest/testcodeparser.h +++ b/src/plugins/autotest/testcodeparser.h @@ -43,6 +43,9 @@ class QThreadPool; QT_END_NAMESPACE namespace Autotest { + +class ITestFramework; + namespace Internal { class TestCodeParser : public QObject @@ -61,7 +64,7 @@ public: State state() const { return m_parserState; } bool isParsing() const { return m_parserState == PartialParse || m_parserState == FullParse; } void setDirty() { m_dirty = true; } - void syncTestFrameworks(const QList<Core::Id> &frameworkIds); + void syncTestFrameworks(const QList<ITestFramework *> &frameworks); #ifdef WITH_TESTS bool furtherParsingExpected() const { return m_singleShotScheduled || m_fullUpdatePostponed || m_partialUpdatePostponed; } @@ -76,7 +79,7 @@ signals: public: void emitUpdateTestTree(ITestParser *parser = nullptr); - void updateTestTree(const QSet<Core::Id> &frameworkIds = {}); + void updateTestTree(const QSet<ITestFramework *> &frameworks = {}); void onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document); void onQmlDocumentUpdated(const QmlJS::Document::Ptr &document); void onStartupProjectChanged(ProjectExplorer::Project *project); @@ -86,7 +89,7 @@ public: private: bool postponed(const QStringList &fileList); void scanForTests(const QStringList &fileList = QStringList(), - const QList<Core::Id> &parserIds = {}); + const QList<ITestFramework *> &parserIds = {}); // qml files must be handled slightly different void onDocumentUpdated(const QString &fileName, bool isQmlFile = false); @@ -110,7 +113,7 @@ private: QFutureWatcher<TestParseResultPtr> m_futureWatcher; QList<ITestParser *> m_testCodeParsers; // ptrs are still owned by TestFrameworkManager QTimer m_reparseTimer; - QSet<Core::Id> m_updateParsers; + QSet<ITestFramework *> m_updateParsers; QThreadPool *m_threadPool = nullptr; }; diff --git a/src/plugins/autotest/testframeworkmanager.cpp b/src/plugins/autotest/testframeworkmanager.cpp index 43eb59d847..87893c3bca 100644 --- a/src/plugins/autotest/testframeworkmanager.cpp +++ b/src/plugins/autotest/testframeworkmanager.cpp @@ -67,8 +67,6 @@ TestFrameworkManager::~TestFrameworkManager() { delete m_testRunner; delete m_testTreeModel; - qDeleteAll(m_frameworkSettingsPages); - m_frameworkSettingsPages.clear(); for (ITestFramework *framework : m_registeredFrameworks.values()) delete framework; } @@ -76,22 +74,19 @@ TestFrameworkManager::~TestFrameworkManager() bool TestFrameworkManager::registerTestFramework(ITestFramework *framework) { QTC_ASSERT(framework, return false); - Id id = Id(Constants::FRAMEWORK_PREFIX).withSuffix(framework->name()); + Id id = framework->id(); QTC_ASSERT(!m_registeredFrameworks.contains(id), delete framework; return false); // TODO check for unique priority before registering qCDebug(LOG) << "Registering" << id; m_registeredFrameworks.insert(id, framework); - if (framework->hasFrameworkSettings()) { - QSharedPointer<IFrameworkSettings> frameworkSettings(framework->createFrameworkSettings()); + if (IFrameworkSettings *frameworkSettings = framework->frameworkSettings()) m_frameworkSettings.insert(id, frameworkSettings); - if (auto page = framework->createSettingsPage(frameworkSettings)) - m_frameworkSettingsPages.append(page); - } + return true; } -void TestFrameworkManager::activateFrameworksFromSettings(QSharedPointer<Internal::TestSettings> settings) +void TestFrameworkManager::activateFrameworksFromSettings(const Internal::TestSettings *settings) { FrameworkIterator it = m_registeredFrameworks.begin(); FrameworkIterator end = m_registeredFrameworks.end(); @@ -101,108 +96,57 @@ void TestFrameworkManager::activateFrameworksFromSettings(QSharedPointer<Interna } } -QString TestFrameworkManager::frameworkNameForId(const Id &id) const +TestFrameworks TestFrameworkManager::registeredFrameworks() const { - ITestFramework *framework = m_registeredFrameworks.value(id, nullptr); - return framework ? QString::fromLatin1(framework->name()) : QString(); + return m_registeredFrameworks.values(); } -QList<Id> TestFrameworkManager::registeredFrameworkIds() const +TestFrameworks TestFrameworkManager::sortedRegisteredFrameworks() const { - return m_registeredFrameworks.keys(); -} - -QList<Id> TestFrameworkManager::sortedRegisteredFrameworkIds() const -{ - QList<Id> registered = m_registeredFrameworks.keys(); - Utils::sort(registered, [this] (const Id &lhs, const Id &rhs) { - return m_registeredFrameworks[lhs]->priority() < m_registeredFrameworks[rhs]->priority(); - }); + TestFrameworks registered = m_registeredFrameworks.values(); + Utils::sort(registered, &ITestFramework::priority); qCDebug(LOG) << "Registered frameworks sorted by priority" << registered; return registered; } -QList<Id> TestFrameworkManager::activeFrameworkIds() const +TestFrameworks TestFrameworkManager::activeFrameworks() const { - QList<Id> active; - FrameworkIterator it = m_registeredFrameworks.begin(); - FrameworkIterator end = m_registeredFrameworks.end(); - for ( ; it != end; ++it) { - if (it.value()->active()) - active.append(it.key()); + TestFrameworks active; + for (ITestFramework *framework : m_registeredFrameworks) { + if (framework->active()) + active.append(framework); } return active; } -QList<Id> TestFrameworkManager::sortedActiveFrameworkIds() const +TestFrameworks TestFrameworkManager::sortedActiveFrameworks() const { - QList<Id> active = activeFrameworkIds(); - Utils::sort(active, [this] (const Id &lhs, const Id &rhs) { - return m_registeredFrameworks[lhs]->priority() < m_registeredFrameworks[rhs]->priority(); - }); + TestFrameworks active = activeFrameworks(); + Utils::sort(active, &ITestFramework::priority); qCDebug(LOG) << "Active frameworks sorted by priority" << active; return active; } -TestTreeItem *TestFrameworkManager::rootNodeForTestFramework(const Id &frameworkId) const +ITestFramework *TestFrameworkManager::frameworkForId(Id frameworkId) { - ITestFramework *framework = m_registeredFrameworks.value(frameworkId, nullptr); - return framework ? framework->rootNode() : nullptr; + return instance()->m_registeredFrameworks.value(frameworkId, nullptr); } -ITestParser *TestFrameworkManager::testParserForTestFramework(const Id &frameworkId) const -{ - ITestFramework *framework = m_registeredFrameworks.value(frameworkId, nullptr); - if (!framework) - return nullptr; - ITestParser *testParser = framework->testParser(); - qCDebug(LOG) << "Setting" << frameworkId << "as Id for test parser"; - testParser->setId(frameworkId); - return testParser; -} - -QSharedPointer<IFrameworkSettings> TestFrameworkManager::settingsForTestFramework( +IFrameworkSettings *TestFrameworkManager::settingsForTestFramework( const Id &frameworkId) const { - return m_frameworkSettings.contains(frameworkId) ? m_frameworkSettings.value(frameworkId) - : QSharedPointer<IFrameworkSettings>(); + return m_frameworkSettings.value(frameworkId, nullptr); } void TestFrameworkManager::synchronizeSettings(QSettings *s) { Internal::AutotestPlugin::settings()->fromSettings(s); for (const Id &id : m_frameworkSettings.keys()) { - QSharedPointer<IFrameworkSettings> fSettings = settingsForTestFramework(id); - if (!fSettings.isNull()) + if (IFrameworkSettings *fSettings = settingsForTestFramework(id)) fSettings->fromSettings(s); } } -bool TestFrameworkManager::isActive(const Id &frameworkId) const -{ - ITestFramework *framework = m_registeredFrameworks.value(frameworkId); - return framework ? framework->active() : false; -} - -bool TestFrameworkManager::groupingEnabled(const Id &frameworkId) const -{ - ITestFramework *framework = m_registeredFrameworks.value(frameworkId); - return framework ? framework->grouping() : false; -} - -void TestFrameworkManager::setGroupingEnabledFor(const Id &frameworkId, bool enabled) -{ - if (ITestFramework *framework = m_registeredFrameworks.value(frameworkId)) - framework->setGrouping(enabled); -} - -QString TestFrameworkManager::groupingToolTip(const Id &frameworkId) const -{ - if (ITestFramework *framework = m_registeredFrameworks.value(frameworkId)) - return framework->groupingToolTip(); - return QString(); -} - bool TestFrameworkManager::hasActiveFrameworks() const { for (ITestFramework *framework : m_registeredFrameworks.values()) { @@ -212,13 +156,6 @@ bool TestFrameworkManager::hasActiveFrameworks() const return false; } -unsigned TestFrameworkManager::priority(const Id &frameworkId) const -{ - if (ITestFramework *framework = m_registeredFrameworks.value(frameworkId)) - return framework->priority(); - return unsigned(-1); -} - Id ITestFramework::settingsId() const { return Core::Id(Constants::SETTINGSPAGE_PREFIX) diff --git a/src/plugins/autotest/testframeworkmanager.h b/src/plugins/autotest/testframeworkmanager.h index fd0c4bea47..e572c58a0f 100644 --- a/src/plugins/autotest/testframeworkmanager.h +++ b/src/plugins/autotest/testframeworkmanager.h @@ -28,7 +28,6 @@ #include "itestframework.h" #include <QHash> -#include <QSharedPointer> QT_BEGIN_NAMESPACE class QSettings; @@ -55,30 +54,25 @@ class TestFrameworkManager public: static TestFrameworkManager *instance(); virtual ~TestFrameworkManager(); + + static ITestFramework *frameworkForId(Core::Id frameworkId); + bool registerTestFramework(ITestFramework *framework); - void activateFrameworksFromSettings(QSharedPointer<Internal::TestSettings> settings); - QString frameworkNameForId(const Core::Id &id) const; - QList<Core::Id> registeredFrameworkIds() const; - QList<Core::Id> sortedRegisteredFrameworkIds() const; - QList<Core::Id> sortedActiveFrameworkIds() const; + void activateFrameworksFromSettings(const Internal::TestSettings *settings); + TestFrameworks registeredFrameworks() const; + TestFrameworks sortedRegisteredFrameworks() const; + TestFrameworks sortedActiveFrameworks() const; - TestTreeItem *rootNodeForTestFramework(const Core::Id &frameworkId) const; - ITestParser *testParserForTestFramework(const Core::Id &frameworkId) const; - QSharedPointer<IFrameworkSettings> settingsForTestFramework(const Core::Id &frameworkId) const; + IFrameworkSettings *settingsForTestFramework(const Core::Id &frameworkId) const; void synchronizeSettings(QSettings *s); - bool isActive(const Core::Id &frameworkId) const; - bool groupingEnabled(const Core::Id &frameworkId) const; - void setGroupingEnabledFor(const Core::Id &frameworkId, bool enabled); - QString groupingToolTip(const Core::Id &frameworkId) const; bool hasActiveFrameworks() const; - unsigned priority(const Core::Id &frameworkId) const; + private: - QList<Core::Id> activeFrameworkIds() const; + TestFrameworks activeFrameworks() const; explicit TestFrameworkManager(); QHash<Core::Id, ITestFramework *> m_registeredFrameworks; - QHash<Core::Id, QSharedPointer<IFrameworkSettings> > m_frameworkSettings; - QVector<Core::IOptionsPage *> m_frameworkSettingsPages; + QHash<Core::Id, IFrameworkSettings *> m_frameworkSettings; TestTreeModel *m_testTreeModel; Internal::TestRunner *m_testRunner; diff --git a/src/plugins/autotest/testprojectsettings.cpp b/src/plugins/autotest/testprojectsettings.cpp index 47f672ea0f..6aab384aaf 100644 --- a/src/plugins/autotest/testprojectsettings.cpp +++ b/src/plugins/autotest/testprojectsettings.cpp @@ -60,9 +60,7 @@ void TestProjectSettings::setUseGlobalSettings(bool useGlobal) void TestProjectSettings::activateFramework(const Core::Id &id, bool activate) { - if (m_activeTestFrameworks.value(id) != activate) { - m_activeTestFrameworks[id] = activate; - } + m_activeTestFrameworks[TestFrameworkManager::instance()->frameworkForId(id)] = activate; } void TestProjectSettings::load() @@ -71,20 +69,20 @@ void TestProjectSettings::load() m_useGlobalSettings = useGlobal.isValid() ? useGlobal.toBool() : true; TestFrameworkManager *frameworkManager = TestFrameworkManager::instance(); - const QList<Core::Id> registered = frameworkManager->sortedRegisteredFrameworkIds(); + const TestFrameworks registered = frameworkManager->sortedRegisteredFrameworks(); const QVariant activeFrameworks = m_project->namedSettings(SK_ACTIVE_FRAMEWORKS); m_activeTestFrameworks.clear(); if (activeFrameworks.isValid()) { const QMap<QString, QVariant> frameworksMap = activeFrameworks.toMap(); - for (const Core::Id &id : registered) { - const QString idStr = id.toString(); - bool active = frameworksMap.value(idStr, frameworkManager->isActive(id)).toBool(); - m_activeTestFrameworks.insert(id, active); + for (ITestFramework *framework : registered) { + const Core::Id id = framework->id(); + bool active = frameworksMap.value(id.toString(), framework->active()).toBool(); + m_activeTestFrameworks.insert(framework, active); } } else { - for (const Core::Id &id : registered) - m_activeTestFrameworks.insert(id, frameworkManager->isActive(id)); + for (ITestFramework *framework : registered) + m_activeTestFrameworks.insert(framework, framework->active()); } const QVariant runAfterBuild = m_project->namedSettings(SK_RUN_AFTER_BUILD); @@ -98,7 +96,7 @@ void TestProjectSettings::save() QVariantMap activeFrameworks; auto end = m_activeTestFrameworks.cend(); for (auto it = m_activeTestFrameworks.cbegin(); it != end; ++it) - activeFrameworks.insert(it.key().toString(), it.value()); + activeFrameworks.insert(it.key()->id().toString(), it.value()); m_project->setNamedSettings(SK_ACTIVE_FRAMEWORKS, activeFrameworks); m_project->setNamedSettings(SK_RUN_AFTER_BUILD, int(m_runAfterBuild)); } diff --git a/src/plugins/autotest/testprojectsettings.h b/src/plugins/autotest/testprojectsettings.h index 595032ff0c..d0b35d5c5f 100644 --- a/src/plugins/autotest/testprojectsettings.h +++ b/src/plugins/autotest/testprojectsettings.h @@ -30,6 +30,9 @@ #include <projectexplorer/project.h> namespace Autotest { + +class ITestFramework; + namespace Internal { class TestProjectSettings : public QObject @@ -43,9 +46,9 @@ public: bool useGlobalSettings() const { return m_useGlobalSettings; } void setRunAfterBuild(RunAfterBuildMode mode) {m_runAfterBuild = mode; } RunAfterBuildMode runAfterBuild() const { return m_runAfterBuild; } - void setActiveFrameworks(const QMap<Core::Id, bool> enabledFrameworks) + void setActiveFrameworks(const QMap<ITestFramework *, bool> enabledFrameworks) { m_activeTestFrameworks = enabledFrameworks; } - QMap<Core::Id, bool> activeFrameworks() const { return m_activeTestFrameworks; } + QMap<ITestFramework *, bool> activeFrameworks() const { return m_activeTestFrameworks; } void activateFramework(const Core::Id &id, bool activate); private: void load(); @@ -54,7 +57,7 @@ private: ProjectExplorer::Project *m_project; bool m_useGlobalSettings = true; RunAfterBuildMode m_runAfterBuild = RunAfterBuildMode::None; - QMap<Core::Id, bool> m_activeTestFrameworks; + QMap<ITestFramework *, bool> m_activeTestFrameworks; }; } // namespace Internal diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp index 6942759947..1e32b8dbea 100644 --- a/src/plugins/autotest/testrunner.cpp +++ b/src/plugins/autotest/testrunner.cpp @@ -511,8 +511,8 @@ static void processOutput(TestOutputReader *outputreader, const QString &msg, { QByteArray message = msg.toUtf8(); switch (format) { - case Utils::OutputFormat::StdErrFormatSameLine: - case Utils::OutputFormat::StdOutFormatSameLine: + case Utils::OutputFormat::StdErrFormat: + case Utils::OutputFormat::StdOutFormat: case Utils::OutputFormat::DebugFormat: { static const QByteArray gdbSpecialOut = "Qt: gdb: -nograb added to command-line options.\n" "\t Use the -dograb option to enforce grabbing."; @@ -521,7 +521,7 @@ static void processOutput(TestOutputReader *outputreader, const QString &msg, message.chop(1); // all messages have an additional \n at the end for (auto line : message.split('\n')) { - if (format == Utils::OutputFormat::StdOutFormatSameLine) + if (format == Utils::OutputFormat::StdOutFormat) outputreader->processStdOutput(line); else outputreader->processStdError(line); diff --git a/src/plugins/autotest/testsettings.cpp b/src/plugins/autotest/testsettings.cpp index b8d9571f9d..9874499daa 100644 --- a/src/plugins/autotest/testsettings.cpp +++ b/src/plugins/autotest/testsettings.cpp @@ -70,8 +70,8 @@ void TestSettings::toSettings(QSettings *s) const s->setValue(runAfterBuildKey, int(runAfterBuild)); // store frameworks and their current active and grouping state for (const Core::Id &id : frameworks.keys()) { - s->setValue(QLatin1String(id.name()), frameworks.value(id)); - s->setValue(QLatin1String(id.name().append(groupSuffix)), frameworksGrouping.value(id)); + s->setValue(id.toString(), frameworks.value(id)); + s->setValue(id.toString() + groupSuffix, frameworksGrouping.value(id)); } s->endGroup(); } @@ -93,16 +93,16 @@ void TestSettings::fromSettings(QSettings *s) int(RunAfterBuildMode::None)).toInt()); // try to get settings for registered frameworks TestFrameworkManager *frameworkManager = TestFrameworkManager::instance(); - const QList<Core::Id> ®istered = frameworkManager->registeredFrameworkIds(); + const TestFrameworks ®istered = frameworkManager->registeredFrameworks(); frameworks.clear(); frameworksGrouping.clear(); - for (const Core::Id &id : registered) { + for (const ITestFramework *framework : registered) { // get their active state - frameworks.insert(id, s->value(QLatin1String(id.name()), - frameworkManager->isActive(id)).toBool()); + const Core::Id id = framework->id(); + const QString key = id.toString(); + frameworks.insert(id, s->value(key, framework->active()).toBool()); // and whether grouping is enabled - frameworksGrouping.insert(id, s->value(QLatin1String(id.name().append(groupSuffix)), - frameworkManager->groupingEnabled(id)).toBool()); + frameworksGrouping.insert(id, s->value(key + groupSuffix, framework->grouping()).toBool()); } s->endGroup(); } diff --git a/src/plugins/autotest/testsettingspage.cpp b/src/plugins/autotest/testsettingspage.cpp index 1f0ddca7c5..c5f95f4aec 100644 --- a/src/plugins/autotest/testsettingspage.cpp +++ b/src/plugins/autotest/testsettingspage.cpp @@ -94,19 +94,18 @@ TestSettings TestSettingsWidget::settings() const void TestSettingsWidget::populateFrameworksListWidget(const QHash<Core::Id, bool> &frameworks) { TestFrameworkManager *frameworkManager = TestFrameworkManager::instance(); - const QList<Core::Id> ®istered = frameworkManager->sortedRegisteredFrameworkIds(); + const TestFrameworks ®istered = frameworkManager->sortedRegisteredFrameworks(); m_ui.frameworkTreeWidget->clear(); - for (const Core::Id &id : registered) { - auto *item = new QTreeWidgetItem(m_ui.frameworkTreeWidget, - QStringList(frameworkManager->frameworkNameForId(id))); + for (const ITestFramework *framework : registered) { + const Core::Id id = framework->id(); + auto item = new QTreeWidgetItem(m_ui.frameworkTreeWidget, QStringList(QLatin1String(framework->name()))); item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable); item->setCheckState(0, frameworks.value(id) ? Qt::Checked : Qt::Unchecked); item->setData(0, Qt::UserRole, id.toSetting()); - item->setData(1, Qt::CheckStateRole, frameworkManager->groupingEnabled(id) ? Qt::Checked - : Qt::Unchecked); + item->setData(1, Qt::CheckStateRole, framework->grouping() ? Qt::Checked : Qt::Unchecked); item->setToolTip(0, tr("Enable or disable test frameworks to be handled by the AutoTest " "plugin.")); - QString toolTip = frameworkManager->groupingToolTip(id); + QString toolTip = framework->groupingToolTip(); if (toolTip.isEmpty()) toolTip = tr("Enable or disable grouping of test cases by folder."); item->setToolTip(1, toolTip); @@ -140,7 +139,7 @@ void TestSettingsWidget::onFrameworkItemChanged() m_ui.frameworksWarn->setVisible(true); } -TestSettingsPage::TestSettingsPage(const QSharedPointer<TestSettings> &settings) +TestSettingsPage::TestSettingsPage(TestSettings *settings) : m_settings(settings) { setId("A.AutoTest.0.General"); diff --git a/src/plugins/autotest/testsettingspage.h b/src/plugins/autotest/testsettingspage.h index a100500476..8834511313 100644 --- a/src/plugins/autotest/testsettingspage.h +++ b/src/plugins/autotest/testsettingspage.h @@ -57,14 +57,14 @@ class TestSettingsPage : public Core::IOptionsPage { Q_OBJECT public: - explicit TestSettingsPage(const QSharedPointer<TestSettings> &settings); + explicit TestSettingsPage(TestSettings *settings); QWidget *widget() override; void apply() override; void finish() override { } private: - QSharedPointer<TestSettings> m_settings; + TestSettings *m_settings; QPointer<TestSettingsWidget> m_widget; }; diff --git a/src/plugins/autotest/testtreemodel.cpp b/src/plugins/autotest/testtreemodel.cpp index b4f3e06d89..9e0b374514 100644 --- a/src/plugins/autotest/testtreemodel.cpp +++ b/src/plugins/autotest/testtreemodel.cpp @@ -205,23 +205,23 @@ QList<TestTreeItem *> TestTreeModel::testItemsByName(const QString &testName) void TestTreeModel::synchronizeTestFrameworks() { ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); - QList<Core::Id> sortedIds; + TestFrameworks sorted; TestFrameworkManager *manager = TestFrameworkManager::instance(); const QVariant useGlobal = project ? project->namedSettings(Constants::SK_USE_GLOBAL) : QVariant(); if (!useGlobal.isValid() || AutotestPlugin::projectSettings(project)->useGlobalSettings()) { - sortedIds = manager->sortedActiveFrameworkIds(); + sorted = manager->sortedActiveFrameworks(); } else { // we've got custom project settings const TestProjectSettings *settings = AutotestPlugin::projectSettings(project); - const QMap<Core::Id, bool> active = settings->activeFrameworks(); - sortedIds = Utils::filtered(active.keys(), [active](const Core::Id &id) { - return active.value(id); + const QMap<ITestFramework *, bool> active = settings->activeFrameworks(); + sorted = Utils::filtered(active.keys(), [active](ITestFramework *framework) { + return active.value(framework); }); } // pre-check to avoid further processing when frameworks are unchanged Utils::TreeItem *invisibleRoot = rootItem(); - QSet<Core::Id> newlyAdded; + QSet<ITestFramework *> newlyAdded; QList<Utils::TreeItem *> oldFrameworkRoots; for (Utils::TreeItem *oldFrameworkRoot : *invisibleRoot) oldFrameworkRoots.append(oldFrameworkRoot); @@ -229,19 +229,19 @@ void TestTreeModel::synchronizeTestFrameworks() for (Utils::TreeItem *oldFrameworkRoot : oldFrameworkRoots) takeItem(oldFrameworkRoot); // do NOT delete the ptr is still held by TestFrameworkManager - for (const Core::Id &id : sortedIds) { - TestTreeItem *frameworkRootNode = manager->rootNodeForTestFramework(id); + for (ITestFramework *framework : sorted) { + TestTreeItem *frameworkRootNode = framework->rootNode(); invisibleRoot->appendChild(frameworkRootNode); if (!oldFrameworkRoots.removeOne(frameworkRootNode)) - newlyAdded.insert(id); + newlyAdded.insert(framework); } for (Utils::TreeItem *oldFrameworkRoot : oldFrameworkRoots) oldFrameworkRoot->removeChildren(); - m_parser->syncTestFrameworks(sortedIds); + m_parser->syncTestFrameworks(sorted); if (!newlyAdded.isEmpty()) m_parser->updateTestTree(newlyAdded); - emit updatedActiveFrameworks(sortedIds.size()); + emit updatedActiveFrameworks(sorted.size()); } void TestTreeModel::filterAndInsert(TestTreeItem *item, TestTreeItem *root, bool groupingEnabled) @@ -257,10 +257,10 @@ void TestTreeModel::filterAndInsert(TestTreeItem *item, TestTreeItem *root, bool void TestTreeModel::rebuild(const QList<Core::Id> &frameworkIds) { - TestFrameworkManager *frameworkManager = TestFrameworkManager::instance(); for (const Core::Id &id : frameworkIds) { - TestTreeItem *frameworkRoot = frameworkManager->rootNodeForTestFramework(id); - const bool groupingEnabled = TestFrameworkManager::instance()->groupingEnabled(id); + ITestFramework *framework = TestFrameworkManager::frameworkForId(id); + TestTreeItem *frameworkRoot = framework->rootNode(); + const bool groupingEnabled = framework->grouping(); for (int row = frameworkRoot->childCount() - 1; row >= 0; --row) { auto testItem = frameworkRoot->childAt(row); if (testItem->type() == TestTreeItem::GroupNode) { @@ -450,16 +450,14 @@ void TestTreeModel::revalidateCheckState(TestTreeItem *item) void TestTreeModel::onParseResultReady(const TestParseResultPtr result) { - TestTreeItem *rootNode - = TestFrameworkManager::instance()->rootNodeForTestFramework(result->frameworkId); + TestTreeItem *rootNode = result->framework->rootNode(); QTC_ASSERT(rootNode, return); handleParseResult(result.data(), rootNode); } void TestTreeModel::handleParseResult(const TestParseResult *result, TestTreeItem *parentNode) { - const bool groupingEnabled = - TestFrameworkManager::instance()->groupingEnabled(result->frameworkId); + const bool groupingEnabled = result->framework->grouping(); // lookup existing items if (TestTreeItem *toBeModified = parentNode->find(result)) { // found existing item... Do not remove @@ -515,26 +513,26 @@ void TestTreeModel::removeTestRootNodes() // we're inside tests - so use some internal knowledge to make testing easier static TestTreeItem *qtRootNode() { - return TestFrameworkManager::instance()->rootNodeForTestFramework( - Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("QtTest")); + auto id = Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("QtTest"); + return TestFrameworkManager::frameworkForId(id)->rootNode(); } static TestTreeItem *quickRootNode() { - return TestFrameworkManager::instance()->rootNodeForTestFramework( - Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("QtQuickTest")); + auto id = Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("QtQuickTest"); + return TestFrameworkManager::frameworkForId(id)->rootNode(); } static TestTreeItem *gtestRootNode() { - return TestFrameworkManager::instance()->rootNodeForTestFramework( - Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("GTest")); + auto id = Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("GTest"); + return TestFrameworkManager::frameworkForId(id)->rootNode(); } static TestTreeItem *boostTestRootNode() { - return TestFrameworkManager::instance()->rootNodeForTestFramework( - Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("Boost")); + auto id = Core::Id(Constants::FRAMEWORK_PREFIX).withSuffix("Boost"); + return TestFrameworkManager::frameworkForId(id)->rootNode(); } int TestTreeModel::autoTestsCount() const diff --git a/src/plugins/autotoolsprojectmanager/autogenstep.cpp b/src/plugins/autotoolsprojectmanager/autogenstep.cpp index 07bc98024e..89d828d60a 100644 --- a/src/plugins/autotoolsprojectmanager/autogenstep.cpp +++ b/src/plugins/autotoolsprojectmanager/autogenstep.cpp @@ -86,12 +86,10 @@ AutogenStep::AutogenStep(BuildStepList *bsl, Core::Id id) : AbstractProcessStep( }); setSummaryUpdater([this] { - BuildConfiguration *bc = buildConfiguration(); - ProcessParameters param; - param.setMacroExpander(bc->macroExpander()); - param.setEnvironment(bc->environment()); - param.setWorkingDirectory(bc->target()->project()->projectDirectory()); + param.setMacroExpander(macroExpander()); + param.setEnvironment(buildEnvironment()); + param.setWorkingDirectory(project()->projectDirectory()); param.setCommandLine({FilePath::fromString("./autogen.sh"), m_additionalArgumentsAspect->value(), CommandLine::Raw}); @@ -102,12 +100,10 @@ AutogenStep::AutogenStep(BuildStepList *bsl, Core::Id id) : AbstractProcessStep( bool AutogenStep::init() { - BuildConfiguration *bc = buildConfiguration(); - ProcessParameters *pp = processParameters(); - pp->setMacroExpander(bc->macroExpander()); - pp->setEnvironment(bc->environment()); - pp->setWorkingDirectory(bc->target()->project()->projectDirectory()); + pp->setMacroExpander(macroExpander()); + pp->setEnvironment(buildEnvironment()); + pp->setWorkingDirectory(project()->projectDirectory()); pp->setCommandLine({FilePath::fromString("./autogen.sh"), m_additionalArgumentsAspect->value(), CommandLine::Raw}); @@ -117,10 +113,8 @@ bool AutogenStep::init() void AutogenStep::doRun() { - BuildConfiguration *bc = buildConfiguration(); - // Check whether we need to run autogen.sh - const QString projectDir = bc->target()->project()->projectDirectory().toString(); + const QString projectDir = project()->projectDirectory().toString(); const QFileInfo configureInfo(projectDir + "/configure"); const QFileInfo configureAcInfo(projectDir + "/configure.ac"); const QFileInfo makefileAmInfo(projectDir + "/Makefile.am"); diff --git a/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp b/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp index d3651e6f3b..3be62f4e71 100644 --- a/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp +++ b/src/plugins/autotoolsprojectmanager/autoreconfstep.cpp @@ -84,12 +84,10 @@ AutoreconfStep::AutoreconfStep(BuildStepList *bsl, Core::Id id) }); setSummaryUpdater([this] { - BuildConfiguration *bc = buildConfiguration(); - ProcessParameters param; - param.setMacroExpander(bc->macroExpander()); - param.setEnvironment(bc->environment()); - param.setWorkingDirectory(bc->target()->project()->projectDirectory()); + param.setMacroExpander(macroExpander()); + param.setEnvironment(buildEnvironment()); + param.setWorkingDirectory(project()->projectDirectory()); param.setCommandLine({Utils::FilePath::fromString("autoreconf"), m_additionalArgumentsAspect->value(), Utils::CommandLine::Raw}); @@ -100,12 +98,10 @@ AutoreconfStep::AutoreconfStep(BuildStepList *bsl, Core::Id id) bool AutoreconfStep::init() { - BuildConfiguration *bc = buildConfiguration(); - ProcessParameters *pp = processParameters(); - pp->setMacroExpander(bc->macroExpander()); - pp->setEnvironment(bc->environment()); - pp->setWorkingDirectory(bc->target()->project()->projectDirectory()); + pp->setMacroExpander(macroExpander()); + pp->setEnvironment(buildEnvironment()); + pp->setWorkingDirectory(project()->projectDirectory()); pp->setCommandLine({Utils::FilePath::fromString("autoreconf"), m_additionalArgumentsAspect->value(), Utils::CommandLine::Raw}); @@ -114,10 +110,8 @@ bool AutoreconfStep::init() void AutoreconfStep::doRun() { - BuildConfiguration *bc = buildConfiguration(); - // Check whether we need to run autoreconf - const QString projectDir(bc->target()->project()->projectDirectory().toString()); + const QString projectDir(project()->projectDirectory().toString()); if (!QFileInfo::exists(projectDir + "/configure")) m_runAutoreconf = true; diff --git a/src/plugins/autotoolsprojectmanager/configurestep.cpp b/src/plugins/autotoolsprojectmanager/configurestep.cpp index 044e8fd4c7..737840ef19 100644 --- a/src/plugins/autotoolsprojectmanager/configurestep.cpp +++ b/src/plugins/autotoolsprojectmanager/configurestep.cpp @@ -109,9 +109,9 @@ ConfigureStep::ConfigureStep(BuildStepList *bsl, Core::Id id) BuildConfiguration *bc = buildConfiguration(); ProcessParameters param; - param.setMacroExpander(bc->macroExpander()); - param.setEnvironment(bc->environment()); - param.setWorkingDirectory(bc->buildDirectory()); + param.setMacroExpander(macroExpander()); + param.setEnvironment(buildEnvironment()); + param.setWorkingDirectory(buildDirectory()); param.setCommandLine({FilePath::fromString(projectDirRelativeToBuildDir(bc) + "configure"), m_additionalArgumentsAspect->value(), CommandLine::Raw}); @@ -125,9 +125,9 @@ bool ConfigureStep::init() BuildConfiguration *bc = buildConfiguration(); ProcessParameters *pp = processParameters(); - pp->setMacroExpander(bc->macroExpander()); - pp->setEnvironment(bc->environment()); - pp->setWorkingDirectory(bc->buildDirectory()); + pp->setMacroExpander(macroExpander()); + pp->setEnvironment(buildEnvironment()); + pp->setWorkingDirectory(buildDirectory()); pp->setCommandLine({FilePath::fromString(projectDirRelativeToBuildDir(bc) + "configure"), m_additionalArgumentsAspect->value(), CommandLine::Raw}); @@ -137,12 +137,10 @@ bool ConfigureStep::init() void ConfigureStep::doRun() { - BuildConfiguration *bc = buildConfiguration(); - //Check whether we need to run configure - const QString projectDir(bc->target()->project()->projectDirectory().toString()); + const QString projectDir(project()->projectDirectory().toString()); const QFileInfo configureInfo(projectDir + "/configure"); - const QFileInfo configStatusInfo(bc->buildDirectory().toString() + "/config.status"); + const QFileInfo configStatusInfo(buildDirectory().toString() + "/config.status"); if (!configStatusInfo.exists() || configStatusInfo.lastModified() < configureInfo.lastModified()) { diff --git a/src/plugins/baremetal/baremetalplugin.cpp b/src/plugins/baremetal/baremetalplugin.cpp index e39790f80c..a01ae59551 100644 --- a/src/plugins/baremetal/baremetalplugin.cpp +++ b/src/plugins/baremetal/baremetalplugin.cpp @@ -70,7 +70,7 @@ class BareMetalPluginPrivate { public: IarToolChainFactory iarToolChainFactory; - KeilToolchainFactory keilToolChainFactory; + KeilToolChainFactory keilToolChainFactory; SdccToolChainFactory sdccToolChainFactory; BareMetalDeviceFactory deviceFactory; BareMetalRunConfigurationFactory runConfigurationFactory; diff --git a/src/plugins/baremetal/debugservers/uvsc/uvscserverprovider.cpp b/src/plugins/baremetal/debugservers/uvsc/uvscserverprovider.cpp index 1c10441f1b..a50765ad24 100644 --- a/src/plugins/baremetal/debugservers/uvsc/uvscserverprovider.cpp +++ b/src/plugins/baremetal/debugservers/uvsc/uvscserverprovider.cpp @@ -201,8 +201,12 @@ bool UvscServerProvider::aboutToRun(DebuggerRunTool *runTool, QString &errorMess if (!optFilePath.exists()) return false; + const FilePath peripheralDescriptionFile = FilePath::fromString(m_deviceSelection.svd); + Runnable inferior; inferior.executable = bin; + inferior.extraData.insert(Debugger::Constants::kPeripheralDescriptionFile, + peripheralDescriptionFile.toVariant()); inferior.extraData.insert(Debugger::Constants::kUVisionProjectFilePath, projFilePath.toString()); inferior.extraData.insert(Debugger::Constants::kUVisionOptionsFilePath, optFilePath.toString()); inferior.extraData.insert(Debugger::Constants::kUVisionSimulator, isSimulator()); diff --git a/src/plugins/baremetal/debugservers/uvsc/uvtargetdevicemodel.cpp b/src/plugins/baremetal/debugservers/uvsc/uvtargetdevicemodel.cpp index aaad906214..e9a3342857 100644 --- a/src/plugins/baremetal/debugservers/uvsc/uvtargetdevicemodel.cpp +++ b/src/plugins/baremetal/debugservers/uvsc/uvtargetdevicemodel.cpp @@ -452,8 +452,15 @@ DeviceSelection DeviceSelectionView::buildSelection(const DeviceSelectionItem *i if (!contains) mems.push_back(newMem); } - } while ((item->level() > 1) && (item = static_cast<const DeviceSelectionItem *>(item->parent()))); + + // Fix relative SVD file path to make it as absolute. + const QFileInfo fi(selection.svd); + if (!fi.isAbsolute()) { + const QDir dir(QFileInfo(selection.package.file).path()); + selection.svd = QFileInfo(dir, fi.filePath()).absoluteFilePath(); + } + return selection; } diff --git a/src/plugins/baremetal/debugservers/uvsc/uvtargetdeviceviewer.cpp b/src/plugins/baremetal/debugservers/uvsc/uvtargetdeviceviewer.cpp index 31a954c3c4..d75923f551 100644 --- a/src/plugins/baremetal/debugservers/uvsc/uvtargetdeviceviewer.cpp +++ b/src/plugins/baremetal/debugservers/uvsc/uvtargetdeviceviewer.cpp @@ -27,6 +27,8 @@ #include "uvtargetdevicemodel.h" #include "uvtargetdeviceviewer.h" +#include <utils/pathchooser.h> + #include <QDialogButtonBox> #include <QFormLayout> #include <QHBoxLayout> @@ -83,6 +85,14 @@ DeviceSelectorDetailsPanel::DeviceSelectorDetailsPanel(DeviceSelection &selectio layout->addRow(tr("Memory:"), m_memoryView); m_algorithmView = new DeviceSelectionAlgorithmView(m_selection); layout->addRow(tr("Flash algorithm"), m_algorithmView); + m_peripheralDescriptionFileChooser = new Utils::PathChooser(this); + m_peripheralDescriptionFileChooser->setExpectedKind(Utils::PathChooser::File); + m_peripheralDescriptionFileChooser->setPromptDialogFilter( + tr("Peripheral description files (*.svd)")); + m_peripheralDescriptionFileChooser->setPromptDialogTitle( + tr("Select Peripheral Description File")); + layout->addRow(tr("Peripheral description file:"), + m_peripheralDescriptionFileChooser); setLayout(layout); refresh(); @@ -95,6 +105,8 @@ DeviceSelectorDetailsPanel::DeviceSelectorDetailsPanel(DeviceSelection &selectio m_selection.algorithmIndex = index; emit selectionChanged(); }); + connect(m_peripheralDescriptionFileChooser, &Utils::PathChooser::pathChanged, + this, &DeviceSelectorDetailsPanel::selectionChanged); } static QString trimVendor(const QString &vendor) @@ -111,6 +123,7 @@ void DeviceSelectorDetailsPanel::refresh() m_memoryView->refresh(); m_algorithmView->refresh(); m_algorithmView->setAlgorithm(m_selection.algorithmIndex); + m_peripheralDescriptionFileChooser->setPath(m_selection.svd); } // DeviceSelector diff --git a/src/plugins/baremetal/debugservers/uvsc/uvtargetdeviceviewer.h b/src/plugins/baremetal/debugservers/uvsc/uvtargetdeviceviewer.h index abc00e9c1c..d65bc64153 100644 --- a/src/plugins/baremetal/debugservers/uvsc/uvtargetdeviceviewer.h +++ b/src/plugins/baremetal/debugservers/uvsc/uvtargetdeviceviewer.h @@ -38,6 +38,8 @@ class QLineEdit; class QPlainTextEdit; QT_END_NAMESPACE +namespace Utils { class PathChooser; } + namespace BareMetal { namespace Internal { namespace Uv { @@ -107,6 +109,7 @@ private: QPlainTextEdit *m_descEdit = nullptr; DeviceSelectionMemoryView *m_memoryView = nullptr; DeviceSelectionAlgorithmView *m_algorithmView = nullptr; + Utils::PathChooser *m_peripheralDescriptionFileChooser = nullptr; }; // DeviceSelectionDialog diff --git a/src/plugins/baremetal/iarewtoolchain.cpp b/src/plugins/baremetal/iarewtoolchain.cpp index b16d5465c7..a67ba48eda 100644 --- a/src/plugins/baremetal/iarewtoolchain.cpp +++ b/src/plugins/baremetal/iarewtoolchain.cpp @@ -238,8 +238,7 @@ static QString buildDisplayName(Abi::Architecture arch, Core::Id language, { const auto archName = Abi::toString(arch); const auto langName = ToolChainManager::displayNameOfLanguageId(language); - return IarToolChain::tr("IAREW %1 (%2, %3)") - .arg(version, langName, archName); + return IarToolChain::tr("IAREW %1 (%2, %3)").arg(version, langName, archName); } // IarToolChain @@ -247,7 +246,7 @@ static QString buildDisplayName(Abi::Architecture arch, Core::Id language, IarToolChain::IarToolChain() : ToolChain(Constants::IAREW_TOOLCHAIN_TYPEID) { - setTypeDisplayName(Internal::IarToolChainFactory::tr("IAREW")); + setTypeDisplayName(Internal::IarToolChain::tr("IAREW")); } void IarToolChain::setTargetAbi(const Abi &abi) @@ -416,7 +415,7 @@ FilePath IarToolChain::makeCommand(const Environment &env) const IarToolChainFactory::IarToolChainFactory() { - setDisplayName(tr("IAREW")); + setDisplayName(IarToolChain::tr("IAREW")); setSupportedToolChainType(Constants::IAREW_TOOLCHAIN_TYPEID); setSupportedLanguages({ProjectExplorer::Constants::C_LANGUAGE_ID, ProjectExplorer::Constants::CXX_LANGUAGE_ID}); diff --git a/src/plugins/baremetal/iarewtoolchain.h b/src/plugins/baremetal/iarewtoolchain.h index 3c8c95a325..59a67e02ef 100644 --- a/src/plugins/baremetal/iarewtoolchain.h +++ b/src/plugins/baremetal/iarewtoolchain.h @@ -96,8 +96,6 @@ private: class IarToolChainFactory final : public ProjectExplorer::ToolChainFactory { - Q_OBJECT - public: IarToolChainFactory(); diff --git a/src/plugins/baremetal/keiltoolchain.cpp b/src/plugins/baremetal/keiltoolchain.cpp index 80ae51240e..33b5986ad9 100644 --- a/src/plugins/baremetal/keiltoolchain.cpp +++ b/src/plugins/baremetal/keiltoolchain.cpp @@ -230,19 +230,19 @@ static QString buildDisplayName(Abi::Architecture arch, Core::Id language, { const auto archName = Abi::toString(arch); const auto langName = ToolChainManager::displayNameOfLanguageId(language); - return KeilToolchain::tr("KEIL %1 (%2, %3)") + return KeilToolChain::tr("KEIL %1 (%2, %3)") .arg(version, langName, archName); } // KeilToolchain -KeilToolchain::KeilToolchain() : +KeilToolChain::KeilToolChain() : ToolChain(Constants::KEIL_TOOLCHAIN_TYPEID) { - setTypeDisplayName(Internal::KeilToolchainFactory::tr("KEIL")); + setTypeDisplayName(tr("KEIL")); } -void KeilToolchain::setTargetAbi(const Abi &abi) +void KeilToolChain::setTargetAbi(const Abi &abi) { if (abi == m_targetAbi) return; @@ -250,17 +250,17 @@ void KeilToolchain::setTargetAbi(const Abi &abi) toolChainUpdated(); } -Abi KeilToolchain::targetAbi() const +Abi KeilToolChain::targetAbi() const { return m_targetAbi; } -bool KeilToolchain::isValid() const +bool KeilToolChain::isValid() const { return true; } -ToolChain::MacroInspectionRunner KeilToolchain::createMacroInspectionRunner() const +ToolChain::MacroInspectionRunner KeilToolChain::createMacroInspectionRunner() const { Environment env = Environment::systemEnvironment(); addToEnvironment(env); @@ -282,23 +282,23 @@ ToolChain::MacroInspectionRunner KeilToolchain::createMacroInspectionRunner() co }; } -Macros KeilToolchain::predefinedMacros(const QStringList &cxxflags) const +Macros KeilToolChain::predefinedMacros(const QStringList &cxxflags) const { return createMacroInspectionRunner()(cxxflags).macros; } -Utils::LanguageExtensions KeilToolchain::languageExtensions(const QStringList &) const +Utils::LanguageExtensions KeilToolChain::languageExtensions(const QStringList &) const { return LanguageExtension::None; } -WarningFlags KeilToolchain::warningFlags(const QStringList &cxxflags) const +WarningFlags KeilToolChain::warningFlags(const QStringList &cxxflags) const { Q_UNUSED(cxxflags) return WarningFlags::Default; } -ToolChain::BuiltInHeaderPathsRunner KeilToolchain::createBuiltInHeaderPathsRunner( +ToolChain::BuiltInHeaderPathsRunner KeilToolChain::createBuiltInHeaderPathsRunner( const Environment &) const { const Utils::FilePath compilerCommand = m_compilerCommand; @@ -317,14 +317,14 @@ ToolChain::BuiltInHeaderPathsRunner KeilToolchain::createBuiltInHeaderPathsRunne }; } -HeaderPaths KeilToolchain::builtInHeaderPaths(const QStringList &cxxFlags, +HeaderPaths KeilToolChain::builtInHeaderPaths(const QStringList &cxxFlags, const FilePath &fileName, const Environment &env) const { return createBuiltInHeaderPathsRunner(env)(cxxFlags, fileName.toString(), ""); } -void KeilToolchain::addToEnvironment(Environment &env) const +void KeilToolChain::addToEnvironment(Environment &env) const { if (!m_compilerCommand.isEmpty()) { const FilePath path = m_compilerCommand.parentDir(); @@ -332,12 +332,12 @@ void KeilToolchain::addToEnvironment(Environment &env) const } } -IOutputParser *KeilToolchain::outputParser() const +IOutputParser *KeilToolChain::outputParser() const { return new KeilParser; } -QVariantMap KeilToolchain::toMap() const +QVariantMap KeilToolChain::toMap() const { QVariantMap data = ToolChain::toMap(); data.insert(compilerCommandKeyC, m_compilerCommand.toString()); @@ -345,7 +345,7 @@ QVariantMap KeilToolchain::toMap() const return data; } -bool KeilToolchain::fromMap(const QVariantMap &data) +bool KeilToolChain::fromMap(const QVariantMap &data) { if (!ToolChain::fromMap(data)) return false; @@ -354,23 +354,23 @@ bool KeilToolchain::fromMap(const QVariantMap &data) return true; } -std::unique_ptr<ToolChainConfigWidget> KeilToolchain::createConfigurationWidget() +std::unique_ptr<ToolChainConfigWidget> KeilToolChain::createConfigurationWidget() { - return std::make_unique<KeilToolchainConfigWidget>(this); + return std::make_unique<KeilToolChainConfigWidget>(this); } -bool KeilToolchain::operator ==(const ToolChain &other) const +bool KeilToolChain::operator ==(const ToolChain &other) const { if (!ToolChain::operator ==(other)) return false; - const auto customTc = static_cast<const KeilToolchain *>(&other); + const auto customTc = static_cast<const KeilToolChain *>(&other); return m_compilerCommand == customTc->m_compilerCommand && m_targetAbi == customTc->m_targetAbi ; } -void KeilToolchain::setCompilerCommand(const FilePath &file) +void KeilToolChain::setCompilerCommand(const FilePath &file) { if (file == m_compilerCommand) return; @@ -378,12 +378,12 @@ void KeilToolchain::setCompilerCommand(const FilePath &file) toolChainUpdated(); } -FilePath KeilToolchain::compilerCommand() const +FilePath KeilToolChain::compilerCommand() const { return m_compilerCommand; } -FilePath KeilToolchain::makeCommand(const Environment &env) const +FilePath KeilToolChain::makeCommand(const Environment &env) const { Q_UNUSED(env) return {}; @@ -391,13 +391,13 @@ FilePath KeilToolchain::makeCommand(const Environment &env) const // KeilToolchainFactory -KeilToolchainFactory::KeilToolchainFactory() +KeilToolChainFactory::KeilToolChainFactory() { - setDisplayName(tr("KEIL")); + setDisplayName(KeilToolChain::tr("KEIL")); setSupportedToolChainType(Constants::KEIL_TOOLCHAIN_TYPEID); setSupportedLanguages({ProjectExplorer::Constants::C_LANGUAGE_ID, ProjectExplorer::Constants::CXX_LANGUAGE_ID}); - setToolchainConstructor([] { return new KeilToolchain; }); + setToolchainConstructor([] { return new KeilToolChain; }); setUserCreatable(true); } @@ -445,7 +445,7 @@ static QString extractVersion(const QString &toolsFile, const QString §ion) return {}; } -QList<ToolChain *> KeilToolchainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown) +QList<ToolChain *> KeilToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown) { #ifdef Q_OS_WIN64 static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\" \ @@ -492,7 +492,7 @@ QList<ToolChain *> KeilToolchainFactory::autoDetect(const QList<ToolChain *> &al return autoDetectToolchains(candidates, alreadyKnown); } -QList<ToolChain *> KeilToolchainFactory::autoDetectToolchains( +QList<ToolChain *> KeilToolChainFactory::autoDetectToolchains( const Candidates &candidates, const QList<ToolChain *> &alreadyKnown) const { QList<ToolChain *> result; @@ -519,7 +519,7 @@ QList<ToolChain *> KeilToolchainFactory::autoDetectToolchains( return result; } -QList<ToolChain *> KeilToolchainFactory::autoDetectToolchain( +QList<ToolChain *> KeilToolChainFactory::autoDetectToolchain( const Candidate &candidate, Core::Id language) const { const auto env = Environment::systemEnvironment(); @@ -535,7 +535,7 @@ QList<ToolChain *> KeilToolchainFactory::autoDetectToolchain( return {}; } - const auto tc = new KeilToolchain; + const auto tc = new KeilToolChain; tc->setDetection(ToolChain::AutoDetection); tc->setLanguage(language); tc->setCompilerCommand(candidate.compilerPath); @@ -549,7 +549,7 @@ QList<ToolChain *> KeilToolchainFactory::autoDetectToolchain( // KeilToolchainConfigWidget -KeilToolchainConfigWidget::KeilToolchainConfigWidget(KeilToolchain *tc) : +KeilToolChainConfigWidget::KeilToolChainConfigWidget(KeilToolChain *tc) : ToolChainConfigWidget(tc), m_compilerCommand(new PathChooser), m_abiWidget(new AbiWidget) @@ -562,20 +562,20 @@ KeilToolchainConfigWidget::KeilToolchainConfigWidget(KeilToolchain *tc) : m_abiWidget->setEnabled(false); addErrorLabel(); - setFromToolchain(); + setFromToolChain(); connect(m_compilerCommand, &PathChooser::rawPathChanged, - this, &KeilToolchainConfigWidget::handleCompilerCommandChange); + this, &KeilToolChainConfigWidget::handleCompilerCommandChange); connect(m_abiWidget, &AbiWidget::abiChanged, this, &ToolChainConfigWidget::dirty); } -void KeilToolchainConfigWidget::applyImpl() +void KeilToolChainConfigWidget::applyImpl() { if (toolChain()->isAutoDetected()) return; - const auto tc = static_cast<KeilToolchain *>(toolChain()); + const auto tc = static_cast<KeilToolChain *>(toolChain()); const QString displayName = tc->displayName(); tc->setCompilerCommand(m_compilerCommand->fileName()); tc->setTargetAbi(m_abiWidget->currentAbi()); @@ -587,34 +587,34 @@ void KeilToolchainConfigWidget::applyImpl() const auto languageVersion = ToolChain::languageVersion(tc->language(), m_macros); tc->predefinedMacrosCache()->insert({}, {m_macros, languageVersion}); - setFromToolchain(); + setFromToolChain(); } -bool KeilToolchainConfigWidget::isDirtyImpl() const +bool KeilToolChainConfigWidget::isDirtyImpl() const { - const auto tc = static_cast<KeilToolchain *>(toolChain()); + const auto tc = static_cast<KeilToolChain *>(toolChain()); return m_compilerCommand->fileName() != tc->compilerCommand() || m_abiWidget->currentAbi() != tc->targetAbi() ; } -void KeilToolchainConfigWidget::makeReadOnlyImpl() +void KeilToolChainConfigWidget::makeReadOnlyImpl() { m_compilerCommand->setReadOnly(true); m_abiWidget->setEnabled(false); } -void KeilToolchainConfigWidget::setFromToolchain() +void KeilToolChainConfigWidget::setFromToolChain() { const QSignalBlocker blocker(this); - const auto tc = static_cast<KeilToolchain *>(toolChain()); + const auto tc = static_cast<KeilToolChain *>(toolChain()); m_compilerCommand->setFileName(tc->compilerCommand()); m_abiWidget->setAbis({}, tc->targetAbi()); const bool haveCompiler = compilerExists(m_compilerCommand->fileName()); m_abiWidget->setEnabled(haveCompiler && !tc->isAutoDetected()); } -void KeilToolchainConfigWidget::handleCompilerCommandChange() +void KeilToolChainConfigWidget::handleCompilerCommandChange() { const FilePath compilerPath = m_compilerCommand->fileName(); const bool haveCompiler = compilerExists(compilerPath); diff --git a/src/plugins/baremetal/keiltoolchain.h b/src/plugins/baremetal/keiltoolchain.h index a8b3c660a0..341e28a1b3 100644 --- a/src/plugins/baremetal/keiltoolchain.h +++ b/src/plugins/baremetal/keiltoolchain.h @@ -45,11 +45,11 @@ namespace ProjectExplorer { class AbiWidget; } namespace BareMetal { namespace Internal { -// KeilToolchain +// KeilToolChain -class KeilToolchain final : public ProjectExplorer::ToolChain +class KeilToolChain final : public ProjectExplorer::ToolChain { - Q_DECLARE_TR_FUNCTIONS(KeilToolchain) + Q_DECLARE_TR_FUNCTIONS(KeilToolChain) public: void setTargetAbi(const ProjectExplorer::Abi &abi); @@ -84,23 +84,21 @@ public: Utils::FilePath makeCommand(const Utils::Environment &env) const final; private: - KeilToolchain(); + KeilToolChain(); ProjectExplorer::Abi m_targetAbi; Utils::FilePath m_compilerCommand; - friend class KeilToolchainFactory; - friend class KeilToolchainConfigWidget; + friend class KeilToolChainFactory; + friend class KeilToolChainConfigWidget; }; // KeilToolchainFactory -class KeilToolchainFactory final : public ProjectExplorer::ToolChainFactory +class KeilToolChainFactory final : public ProjectExplorer::ToolChainFactory { - Q_OBJECT - public: - KeilToolchainFactory(); + KeilToolChainFactory(); QList<ProjectExplorer::ToolChain *> autoDetect( const QList<ProjectExplorer::ToolChain *> &alreadyKnown) final; @@ -114,20 +112,20 @@ private: // KeilToolchainConfigWidget -class KeilToolchainConfigWidget final : public ProjectExplorer::ToolChainConfigWidget +class KeilToolChainConfigWidget final : public ProjectExplorer::ToolChainConfigWidget { Q_OBJECT public: - explicit KeilToolchainConfigWidget(KeilToolchain *tc); + explicit KeilToolChainConfigWidget(KeilToolChain *tc); private: void applyImpl() final; - void discardImpl() final { setFromToolchain(); } + void discardImpl() final { setFromToolChain(); } bool isDirtyImpl() const final; void makeReadOnlyImpl() final; - void setFromToolchain(); + void setFromToolChain(); void handleCompilerCommandChange(); Utils::PathChooser *m_compilerCommand = nullptr; diff --git a/src/plugins/baremetal/sdcctoolchain.cpp b/src/plugins/baremetal/sdcctoolchain.cpp index a7b62686c8..84dd4134c7 100644 --- a/src/plugins/baremetal/sdcctoolchain.cpp +++ b/src/plugins/baremetal/sdcctoolchain.cpp @@ -217,7 +217,7 @@ static Utils::FilePath compilerPathFromEnvironment(const QString &compilerName) SdccToolChain::SdccToolChain() : ToolChain(Constants::SDCC_TOOLCHAIN_TYPEID) { - setTypeDisplayName(Internal::SdccToolChainFactory::tr("SDCC")); + setTypeDisplayName(Internal::SdccToolChain::tr("SDCC")); } void SdccToolChain::setTargetAbi(const Abi &abi) @@ -368,7 +368,7 @@ FilePath SdccToolChain::makeCommand(const Environment &env) const SdccToolChainFactory::SdccToolChainFactory() { - setDisplayName(tr("SDCC")); + setDisplayName(SdccToolChain::tr("SDCC")); setSupportedToolChainType(Constants::SDCC_TOOLCHAIN_TYPEID); setSupportedLanguages({ProjectExplorer::Constants::C_LANGUAGE_ID}); setToolchainConstructor([] { return new SdccToolChain; }); diff --git a/src/plugins/baremetal/sdcctoolchain.h b/src/plugins/baremetal/sdcctoolchain.h index ef851f4a78..aff4be1226 100644 --- a/src/plugins/baremetal/sdcctoolchain.h +++ b/src/plugins/baremetal/sdcctoolchain.h @@ -97,8 +97,6 @@ private: class SdccToolChainFactory final : public ProjectExplorer::ToolChainFactory { - Q_OBJECT - public: SdccToolChainFactory(); diff --git a/src/plugins/bookmarks/bookmarkmanager.cpp b/src/plugins/bookmarks/bookmarkmanager.cpp index f4147f02a3..7c1854ff29 100644 --- a/src/plugins/bookmarks/bookmarkmanager.cpp +++ b/src/plugins/bookmarks/bookmarkmanager.cpp @@ -274,7 +274,7 @@ void BookmarkView::removeBookmark(const QModelIndex& index) void BookmarkView::keyPressEvent(QKeyEvent *event) { - if (event->key() == Qt::Key_Delete) { + if (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) { removeBookmark(currentIndex()); event->accept(); return; diff --git a/src/plugins/boot2qt/CMakeLists.txt b/src/plugins/boot2qt/CMakeLists.txt index c557459698..d11cd580f9 100644 --- a/src/plugins/boot2qt/CMakeLists.txt +++ b/src/plugins/boot2qt/CMakeLists.txt @@ -6,7 +6,6 @@ add_qtc_plugin(Boot2Qt qdb_global.h qdbconstants.h qdbdeployconfigurationfactory.cpp qdbdeployconfigurationfactory.h - qdbdeploystepfactory.cpp qdbdeploystepfactory.h qdbdevice.cpp qdbdevice.h qdbdevicedebugsupport.cpp qdbdevicedebugsupport.h qdbmakedefaultappservice.cpp qdbmakedefaultappservice.h diff --git a/src/plugins/boot2qt/boot2qt.pro b/src/plugins/boot2qt/boot2qt.pro index 8c5f51e504..c6e5293845 100644 --- a/src/plugins/boot2qt/boot2qt.pro +++ b/src/plugins/boot2qt/boot2qt.pro @@ -16,7 +16,6 @@ HEADERS += \ qdbmakedefaultappservice.h \ qdbstopapplicationstep.h \ qdbstopapplicationservice.h \ - qdbdeploystepfactory.h \ qdbdevicedebugsupport.h \ qdbconstants.h \ qdb_global.h \ @@ -32,7 +31,6 @@ SOURCES += \ qdbmakedefaultappservice.cpp \ qdbstopapplicationstep.cpp \ qdbstopapplicationservice.cpp \ - qdbdeploystepfactory.cpp \ qdbdevicedebugsupport.cpp \ qdbplugin.cpp \ diff --git a/src/plugins/boot2qt/boot2qt.qbs b/src/plugins/boot2qt/boot2qt.qbs index ac6a33f279..3487e3eb94 100644 --- a/src/plugins/boot2qt/boot2qt.qbs +++ b/src/plugins/boot2qt/boot2qt.qbs @@ -23,8 +23,6 @@ QtcPlugin { "qdb_global.h", "qdbdeployconfigurationfactory.cpp", "qdbdeployconfigurationfactory.h", - "qdbdeploystepfactory.cpp", - "qdbdeploystepfactory.h", "qdbdevice.cpp", "qdbdevice.h", "qdbdevicedebugsupport.cpp", diff --git a/src/plugins/boot2qt/qdbconstants.h b/src/plugins/boot2qt/qdbconstants.h index 34471f43df..3ea41608e9 100644 --- a/src/plugins/boot2qt/qdbconstants.h +++ b/src/plugins/boot2qt/qdbconstants.h @@ -34,6 +34,9 @@ const char QdbLinuxOsType[] = "QdbLinuxOsType"; const char QdbDeployConfigurationId[] = "Qt4ProjectManager.Qdb.QdbDeployConfiguration"; +const char QdbStopApplicationStepId[] = "Qdb.StopApplicationStep"; +const char QdbMakeDefaultAppStepId[] = "Qdb.MakeDefaultAppStep"; + const Core::Id QdbHardwareDevicePrefix = "QdbHardwareDevice"; const char AppcontrollerFilepath[] = "/usr/bin/appcontroller"; diff --git a/src/plugins/boot2qt/qdbdeployconfigurationfactory.cpp b/src/plugins/boot2qt/qdbdeployconfigurationfactory.cpp index 7e973d86e1..a8b86a87ff 100644 --- a/src/plugins/boot2qt/qdbdeployconfigurationfactory.cpp +++ b/src/plugins/boot2qt/qdbdeployconfigurationfactory.cpp @@ -26,20 +26,15 @@ #include "qdbdeployconfigurationfactory.h" #include "qdbconstants.h" -#include "qdbstopapplicationstep.h" #include <projectexplorer/deploymentdataview.h> #include <projectexplorer/kitinformation.h> #include <projectexplorer/project.h> #include <projectexplorer/target.h> -#include <remotelinux/genericdirectuploadstep.h> -#include <remotelinux/makeinstallstep.h> -#include <remotelinux/remotelinuxcheckforfreediskspacestep.h> -#include <remotelinux/remotelinuxdeployconfiguration.h> +#include <remotelinux/remotelinux_constants.h> using namespace ProjectExplorer; -using namespace RemoteLinux; namespace Qdb { namespace Internal { @@ -52,14 +47,14 @@ QdbDeployConfigurationFactory::QdbDeployConfigurationFactory() "Deploy to Boot2Qt target")); setUseDeploymentDataView(); - addInitialStep(RemoteLinux::MakeInstallStep::stepId(), [](Target *target) { + addInitialStep(RemoteLinux::Constants::MakeInstallStepId, [](Target *target) { const Project * const prj = target->project(); return prj->deploymentKnowledge() == DeploymentKnowledge::Bad && prj->hasMakeInstallEquivalent(); }); - addInitialStep(RemoteLinuxCheckForFreeDiskSpaceStep::stepId()); - addInitialStep(QdbStopApplicationStep::stepId()); - addInitialStep(GenericDirectUploadStep::stepId()); + addInitialStep(RemoteLinux::Constants::CheckForFreeDiskSpaceId); + addInitialStep(Qdb::Constants::QdbStopApplicationStepId); + addInitialStep(RemoteLinux::Constants::DirectUploadStepId); } } // namespace Internal diff --git a/src/plugins/boot2qt/qdbdeployconfigurationfactory.h b/src/plugins/boot2qt/qdbdeployconfigurationfactory.h index 90fd93f239..0aaa09eb34 100644 --- a/src/plugins/boot2qt/qdbdeployconfigurationfactory.h +++ b/src/plugins/boot2qt/qdbdeployconfigurationfactory.h @@ -30,7 +30,7 @@ namespace Qdb { namespace Internal { -class QdbDeployConfigurationFactory : public ProjectExplorer::DeployConfigurationFactory +class QdbDeployConfigurationFactory final : public ProjectExplorer::DeployConfigurationFactory { public: QdbDeployConfigurationFactory(); diff --git a/src/plugins/boot2qt/qdbmakedefaultappstep.cpp b/src/plugins/boot2qt/qdbmakedefaultappstep.cpp index 917cbf1f41..8cb4ab2bdf 100644 --- a/src/plugins/boot2qt/qdbmakedefaultappstep.cpp +++ b/src/plugins/boot2qt/qdbmakedefaultappstep.cpp @@ -25,15 +25,28 @@ #include "qdbmakedefaultappstep.h" +#include "qdbconstants.h" #include "qdbmakedefaultappservice.h" #include <projectexplorer/runconfigurationaspects.h> +#include <remotelinux/abstractremotelinuxdeploystep.h> + using namespace ProjectExplorer; namespace Qdb { namespace Internal { +class QdbMakeDefaultAppStep final : public RemoteLinux::AbstractRemoteLinuxDeployStep +{ + Q_DECLARE_TR_FUNCTIONS(Qdb::Internal::QdbMakeDefaultAppStep) + +public: + QdbMakeDefaultAppStep(BuildStepList *bsl, Core::Id id); + + static QString stepDisplayName() { return tr("Change default application"); } +}; + QdbMakeDefaultAppStep::QdbMakeDefaultAppStep(BuildStepList *bsl, Core::Id id) : AbstractRemoteLinuxDeployStep(bsl, id) { @@ -52,14 +65,14 @@ QdbMakeDefaultAppStep::QdbMakeDefaultAppStep(BuildStepList *bsl, Core::Id id) }); } -Core::Id QdbMakeDefaultAppStep::stepId() -{ - return "Qdb.MakeDefaultAppStep"; -} +// QdbMakeDefaultAppStepFactory -QString QdbMakeDefaultAppStep::stepDisplayName() +QdbMakeDefaultAppStepFactory::QdbMakeDefaultAppStepFactory() { - return QStringLiteral("Change default application"); + registerStep<QdbMakeDefaultAppStep>(Constants::QdbMakeDefaultAppStepId); + setDisplayName(QdbMakeDefaultAppStep::stepDisplayName()); + setSupportedDeviceType(Qdb::Constants::QdbLinuxOsType); + setSupportedStepList(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY); } } // namespace Internal diff --git a/src/plugins/boot2qt/qdbmakedefaultappstep.h b/src/plugins/boot2qt/qdbmakedefaultappstep.h index 59c3c14afc..7f24bd2919 100644 --- a/src/plugins/boot2qt/qdbmakedefaultappstep.h +++ b/src/plugins/boot2qt/qdbmakedefaultappstep.h @@ -25,20 +25,15 @@ #pragma once -#include <remotelinux/abstractremotelinuxdeploystep.h> +#include <projectexplorer/buildstep.h> namespace Qdb { namespace Internal { -class QdbMakeDefaultAppStep : public RemoteLinux::AbstractRemoteLinuxDeployStep +class QdbMakeDefaultAppStepFactory final : public ProjectExplorer::BuildStepFactory { - Q_OBJECT - public: - QdbMakeDefaultAppStep(ProjectExplorer::BuildStepList *bsl, Core::Id id); - - static Core::Id stepId(); - static QString stepDisplayName(); + QdbMakeDefaultAppStepFactory(); }; } // namespace Internal diff --git a/src/plugins/boot2qt/qdbplugin.cpp b/src/plugins/boot2qt/qdbplugin.cpp index cad10b8ce0..cf6f67ebbd 100644 --- a/src/plugins/boot2qt/qdbplugin.cpp +++ b/src/plugins/boot2qt/qdbplugin.cpp @@ -27,7 +27,8 @@ #include "device-detection/devicedetector.h" #include "qdbdeployconfigurationfactory.h" -#include "qdbdeploystepfactory.h" +#include "qdbstopapplicationstep.h" +#include "qdbmakedefaultappstep.h" #include "qdbdevicedebugsupport.h" #include "qdbqtversion.h" #include "qdbrunconfiguration.h" @@ -44,9 +45,10 @@ #include <qtsupport/qtversionfactory.h> -#include <remotelinux/remotelinuxcheckforfreediskspacestep.h> #include <remotelinux/genericdirectuploadstep.h> #include <remotelinux/makeinstallstep.h> +#include <remotelinux/remotelinuxcheckforfreediskspacestep.h> +#include <remotelinux/remotelinux_constants.h> #include <utils/hostosinfo.h> #include <utils/fileutils.h> @@ -153,9 +155,9 @@ template <class Step> class QdbDeployStepFactory : public ProjectExplorer::BuildStepFactory { public: - QdbDeployStepFactory() + explicit QdbDeployStepFactory(Core::Id id) { - registerStep<Step>(Step::stepId()); + registerStep<Step>(id); setDisplayName(Step::displayName()); setSupportedConfiguration(Constants::QdbDeployConfigurationId); setSupportedStepList(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY); @@ -175,9 +177,11 @@ public: QdbMakeDefaultAppStepFactory m_makeDefaultAppStepFactory; QdbDeployStepFactory<RemoteLinux::RemoteLinuxCheckForFreeDiskSpaceStep> - m_checkForFreeDiskSpaceStepFactory; - QdbDeployStepFactory<RemoteLinux::GenericDirectUploadStep> m_directUploadStepFactory; - QdbDeployStepFactory<RemoteLinux::MakeInstallStep> m_makeInstallStepFactory; + m_checkForFreeDiskSpaceStepFactory{RemoteLinux::Constants::CheckForFreeDiskSpaceId}; + QdbDeployStepFactory<RemoteLinux::GenericDirectUploadStep> + m_directUploadStepFactory{RemoteLinux::Constants::DirectUploadStepId}; + QdbDeployStepFactory<RemoteLinux::MakeInstallStep> + m_makeInstallStepFactory{RemoteLinux::Constants::MakeInstallStepId}; const QList<Core::Id> supportedRunConfigs { m_runConfigFactory.id(), diff --git a/src/plugins/boot2qt/qdbstopapplicationstep.cpp b/src/plugins/boot2qt/qdbstopapplicationstep.cpp index 240d2b8bab..a6a329666e 100644 --- a/src/plugins/boot2qt/qdbstopapplicationstep.cpp +++ b/src/plugins/boot2qt/qdbstopapplicationstep.cpp @@ -25,12 +25,29 @@ #include "qdbstopapplicationstep.h" +#include "qdbconstants.h" #include "qdbstopapplicationservice.h" +#include <projectexplorer/projectexplorerconstants.h> + +#include <remotelinux/abstractremotelinuxdeploystep.h> + +using namespace ProjectExplorer; + namespace Qdb { namespace Internal { -QdbStopApplicationStep::QdbStopApplicationStep(ProjectExplorer::BuildStepList *bsl, Core::Id id) +class QdbStopApplicationStep final : public RemoteLinux::AbstractRemoteLinuxDeployStep +{ + Q_DECLARE_TR_FUNCTIONS(Qdb::Internal::QdbStopApplicationStep) + +public: + QdbStopApplicationStep(BuildStepList *bsl, Core::Id id); + + static QString stepDisplayName() { return tr("Stop already running application"); } +}; + +QdbStopApplicationStep::QdbStopApplicationStep(BuildStepList *bsl, Core::Id id) : AbstractRemoteLinuxDeployStep(bsl, id) { auto service = createDeployService<QdbStopApplicationService>(); @@ -41,14 +58,14 @@ QdbStopApplicationStep::QdbStopApplicationStep(ProjectExplorer::BuildStepList *b setInternalInitializer([service] { return service->isDeploymentPossible(); }); } -Core::Id QdbStopApplicationStep::stepId() -{ - return "Qdb.StopApplicationStep"; -} +// QdbStopApplicationStepFactory -QString QdbStopApplicationStep::stepDisplayName() +QdbStopApplicationStepFactory::QdbStopApplicationStepFactory() { - return tr("Stop already running application"); + registerStep<QdbStopApplicationStep>(Constants::QdbStopApplicationStepId); + setDisplayName(QdbStopApplicationStep::stepDisplayName()); + setSupportedDeviceType(Constants::QdbLinuxOsType); + setSupportedStepList(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY); } } // namespace Internal diff --git a/src/plugins/boot2qt/qdbstopapplicationstep.h b/src/plugins/boot2qt/qdbstopapplicationstep.h index a5e3418396..7115cf4c29 100644 --- a/src/plugins/boot2qt/qdbstopapplicationstep.h +++ b/src/plugins/boot2qt/qdbstopapplicationstep.h @@ -25,19 +25,15 @@ #pragma once -#include <remotelinux/abstractremotelinuxdeploystep.h> +#include <projectexplorer/buildstep.h> namespace Qdb { namespace Internal { -class QdbStopApplicationStep : public RemoteLinux::AbstractRemoteLinuxDeployStep +class QdbStopApplicationStepFactory final : public ProjectExplorer::BuildStepFactory { - Q_OBJECT public: - QdbStopApplicationStep(ProjectExplorer::BuildStepList *bsl, Core::Id id); - - static Core::Id stepId(); - static QString stepDisplayName(); + QdbStopApplicationStepFactory(); }; } // namespace Internal diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index 2734f23255..d2905e4834 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -60,6 +60,7 @@ using namespace ClangCodeModel; using namespace ClangCodeModel::Internal; using namespace Core; using namespace CppTools; +using namespace ProjectExplorer; namespace ClangCodeModel { namespace Utils { @@ -303,12 +304,11 @@ QString diagnosticCategoryPrefixRemoved(const QString &text) static ::Utils::FilePath compilerPath(const CppTools::ProjectPart &projectPart) { - ProjectExplorer::Target *target = projectPart.project->activeTarget(); + Target *target = projectPart.project->activeTarget(); if (!target) return ::Utils::FilePath(); - ProjectExplorer::ToolChain *toolchain = ProjectExplorer::ToolChainKitAspect::toolChain( - target->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID); + ToolChain *toolchain = ToolChainKitAspect::cxxToolChain(target->kit()); return toolchain->compilerCommand(); } diff --git a/src/plugins/clangtools/clangtool.cpp b/src/plugins/clangtools/clangtool.cpp index 7536f57ad9..ba7747d9a0 100644 --- a/src/plugins/clangtools/clangtool.cpp +++ b/src/plugins/clangtools/clangtool.cpp @@ -867,7 +867,7 @@ static bool canAnalyzeProject(Project *project) || project->projectLanguages().contains(cxx); return projectSupportsLanguage && CppModelManager::instance()->projectInfo(project).isValid() - && ToolChainKitAspect::toolChain(target->kit(), cxx); + && ToolChainKitAspect::cxxToolChain(target->kit()); } return false; } diff --git a/src/plugins/clangtools/clangtoolruncontrol.cpp b/src/plugins/clangtools/clangtoolruncontrol.cpp index 49bef96a7c..3932d5b440 100644 --- a/src/plugins/clangtools/clangtoolruncontrol.cpp +++ b/src/plugins/clangtools/clangtoolruncontrol.cpp @@ -223,8 +223,7 @@ ClangToolRunWorker::ClangToolRunWorker(RunControl *runControl, QTC_ASSERT(buildConfiguration, return); m_environment = buildConfiguration->environment(); - ToolChain *toolChain = ToolChainKitAspect::toolChain(target->kit(), - ProjectExplorer::Constants::CXX_LANGUAGE_ID); + ToolChain *toolChain = ToolChainKitAspect::cxxToolChain(target->kit()); QTC_ASSERT(toolChain, return); m_targetTriple = toolChain->originalTargetTriple(); m_toolChainType = toolChain->typeId(); diff --git a/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp b/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp index 2ed19354f2..f7319849e2 100644 --- a/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp +++ b/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp @@ -166,7 +166,7 @@ static QList<Target *> validTargets(Project *project) return false; } - const ToolChain * const toolchain = ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID); + const ToolChain * const toolchain = ToolChainKitAspect::cxxToolChain(kit); QTC_ASSERT(toolchain, return false); if (Core::ICore::clangExecutable(CLANG_BINDIR).isEmpty()) { diff --git a/src/plugins/clangtools/clangtoolsunittests.cpp b/src/plugins/clangtools/clangtoolsunittests.cpp index fdd9240e0d..74f79123c6 100644 --- a/src/plugins/clangtools/clangtoolsunittests.cpp +++ b/src/plugins/clangtools/clangtoolsunittests.cpp @@ -62,8 +62,7 @@ void ClangToolsUnitTests::initTestCase() const QList<Kit *> allKits = KitManager::kits(); if (allKits.count() != 1) QSKIP("This test requires exactly one kit to be present"); - const ToolChain *const toolchain = ToolChainKitAspect::toolChain(allKits.first(), - Constants::CXX_LANGUAGE_ID); + const ToolChain *const toolchain = ToolChainKitAspect::cxxToolChain(allKits.first()); if (!toolchain) QSKIP("This test requires that there is a kit with a toolchain."); @@ -100,9 +99,7 @@ void ClangToolsUnitTests::testProject() QFETCH(int, expectedDiagCount); QFETCH(ClangDiagnosticConfig, diagnosticConfig); if (projectFilePath.contains("mingw")) { - const ToolChain *const toolchain - = ToolChainKitAspect::toolChain(KitManager::kits().constFirst(), - Constants::CXX_LANGUAGE_ID); + const auto toolchain = ToolChainKitAspect::cxxToolChain(KitManager::kits().constFirst()); if (toolchain->typeId() != ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID) QSKIP("This test is mingw specific, does not run for other toolchains"); } diff --git a/src/plugins/cmakeprojectmanager/CMakeLists.txt b/src/plugins/cmakeprojectmanager/CMakeLists.txt index 0b2955646f..fbef084213 100644 --- a/src/plugins/cmakeprojectmanager/CMakeLists.txt +++ b/src/plugins/cmakeprojectmanager/CMakeLists.txt @@ -43,5 +43,4 @@ add_qtc_plugin(CMakeProjectManager projecttreehelper.cpp projecttreehelper.h servermode.cpp servermode.h servermodereader.cpp servermodereader.h - tealeafreader.cpp tealeafreader.h ) diff --git a/src/plugins/cmakeprojectmanager/builddirparameters.cpp b/src/plugins/cmakeprojectmanager/builddirparameters.cpp index 1c71396c76..770bbc5070 100644 --- a/src/plugins/cmakeprojectmanager/builddirparameters.cpp +++ b/src/plugins/cmakeprojectmanager/builddirparameters.cpp @@ -69,10 +69,10 @@ BuildDirParameters::BuildDirParameters(CMakeBuildConfiguration *bc) cmakeToolId = CMakeKitAspect::cmakeToolId(k); - auto tc = ToolChainKitAspect::toolChain(k, Constants::CXX_LANGUAGE_ID); + auto tc = ToolChainKitAspect::cxxToolChain(k); if (tc) cxxToolChainId = tc->id(); - tc = ToolChainKitAspect::toolChain(k, Constants::C_LANGUAGE_ID); + tc = ToolChainKitAspect::cToolChain(k); if (tc) cToolChainId = tc->id(); sysRoot = SysRootKitAspect::sysRoot(k); diff --git a/src/plugins/cmakeprojectmanager/builddirreader.cpp b/src/plugins/cmakeprojectmanager/builddirreader.cpp index ca808d36fd..031f1ec6c7 100644 --- a/src/plugins/cmakeprojectmanager/builddirreader.cpp +++ b/src/plugins/cmakeprojectmanager/builddirreader.cpp @@ -27,7 +27,6 @@ #include "fileapireader.h" #include "servermodereader.h" -#include "tealeafreader.h" #include <utils/qtcassert.h> @@ -51,7 +50,7 @@ std::unique_ptr<BuildDirReader> BuildDirReader::createReader(const BuildDirParam case CMakeTool::ServerMode: return std::make_unique<ServerModeReader>(); default: - return std::make_unique<TeaLeafReader>(); + return {}; } } diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index 9c9d60cdba..9d6da30f23 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -88,9 +88,7 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Core::Id id) const QString sysRoot = SysRootKitAspect::sysRoot(k).toString(); if (!sysRoot.isEmpty()) { config.append(CMakeConfigItem("CMAKE_SYSROOT", sysRoot.toUtf8())); - ToolChain *tc = ToolChainKitAspect::toolChain(k, - ProjectExplorer::Constants::CXX_LANGUAGE_ID); - if (tc) { + if (ToolChain *tc = ToolChainKitAspect::cxxToolChain(k)) { const QByteArray targetTriple = tc->originalTargetTriple().toUtf8(); config.append(CMakeConfigItem("CMAKE_C_COMPILER_TARGET", targetTriple)); config.append(CMakeConfigItem("CMAKE_CXX_COMPILER_TARGET ", targetTriple)); @@ -195,12 +193,6 @@ bool CMakeBuildConfiguration::fromMap(const QVariantMap &map) return true; } - - - - - - FilePath CMakeBuildConfiguration::shadowBuildDirectory(const FilePath &projectFilePath, const Kit *k, const QString &bcName, @@ -286,10 +278,7 @@ void CMakeBuildConfiguration::setConfigurationForCMake(const QList<ConfigModel:: return item.key.startsWith("ANDROID_BUILD_ABI_"); }) != -1) { // We always need to clean when we change the ANDROID_BUILD_ABI_ variables - QList<ProjectExplorer::BuildStepList *> stepLists; - const Core::Id clean = ProjectExplorer::Constants::BUILDSTEPS_CLEAN; - stepLists << cleanSteps(); - BuildManager::buildLists(stepLists, QStringList() << ProjectExplorerPlugin::displayNameForStepId(clean)); + BuildManager::buildLists({cleanSteps()}); } } @@ -377,12 +366,6 @@ void CMakeBuildConfiguration::setWarning(const QString &message) emit warningOccured(m_warning); } -bool CMakeBuildConfiguration::isQmlDebuggingEnabled() const -{ - return aspect<QtSupport::QmlDebuggingAspect>()->setting() == TriState::Enabled; -} - - QString CMakeBuildConfiguration::error() const { return m_error; diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h index 082b74c580..a45b871f85 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h @@ -46,11 +46,6 @@ class CMakeBuildConfiguration final : public ProjectExplorer::BuildConfiguration { Q_OBJECT - // used in DebuggerRunConfigurationAspect - Q_PROPERTY(bool linkQmlDebuggingLibrary - READ isQmlDebuggingEnabled - NOTIFY configurationForCMakeChanged) - friend class ProjectExplorer::BuildConfigurationFactory; CMakeBuildConfiguration(ProjectExplorer::Target *target, Core::Id id); ~CMakeBuildConfiguration() final; @@ -94,8 +89,6 @@ private: void setError(const QString &message); void setWarning(const QString &message); - bool isQmlDebuggingEnabled() const; - CMakeConfig m_configurationForCMake; CMakeConfig m_initialConfiguration; QString m_error; diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp index a50b4e19cc..6a7e5196e1 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp @@ -60,16 +60,36 @@ #include <QListWidget> #include <QRadioButton> -using namespace CMakeProjectManager; -using namespace CMakeProjectManager::Internal; using namespace ProjectExplorer; -namespace { +namespace CMakeProjectManager { +namespace Internal { + const char BUILD_TARGETS_KEY[] = "CMakeProjectManager.MakeStep.BuildTargets"; const char TOOL_ARGUMENTS_KEY[] = "CMakeProjectManager.MakeStep.AdditionalArguments"; const char ADD_RUNCONFIGURATION_ARGUMENT_KEY[] = "CMakeProjectManager.MakeStep.AddRunConfigurationArgument"; const char ADD_RUNCONFIGURATION_TEXT[] = "Current executable"; -} + +class CMakeBuildStepConfigWidget : public BuildStepConfigWidget +{ + Q_DECLARE_TR_FUNCTIONS(CMakeProjectManager::Internal::CMakeBuildStepConfigWidget) + +public: + explicit CMakeBuildStepConfigWidget(CMakeBuildStep *buildStep); + +private: + void itemChanged(QListWidgetItem *); + void toolArgumentsEdited(); + void updateDetails(); + void buildTargetsChanged(); + void updateBuildTarget(); + + QRadioButton *itemWidget(QListWidgetItem *item); + + CMakeBuildStep *m_buildStep; + QLineEdit *m_toolArguments; + QListWidget *m_buildTargetsList; +}; static bool isCurrentExecutableTarget(const QString &target) { @@ -131,18 +151,14 @@ bool CMakeBuildStep::fromMap(const QVariantMap &map) return BuildStep::fromMap(map); } - bool CMakeBuildStep::init() { bool canInit = true; CMakeBuildConfiguration *bc = cmakeBuildConfiguration(); - if (!bc) { - emit addTask(Task::buildConfigurationMissingTask()); - canInit = false; - } - if (bc && !bc->isEnabled()) { - emit addTask( - BuildSystemTask(Task::Error, tr("The build configuration is currently disabled."))); + QTC_ASSERT(bc, return false); + if (!bc->isEnabled()) { + emit addTask(BuildSystemTask(Task::Error, + tr("The build configuration is currently disabled."))); canInit = false; } @@ -209,15 +225,12 @@ bool CMakeBuildStep::init() void CMakeBuildStep::doRun() { // Make sure CMake state was written to disk before trying to build: - CMakeBuildConfiguration *bc = cmakeBuildConfiguration(); - QTC_ASSERT(bc, return); - m_waiting = false; - auto bs = static_cast<CMakeBuildSystem *>(buildConfiguration()->buildSystem()); + auto bs = static_cast<CMakeBuildSystem *>(buildSystem()); if (bs->persistCMakeState()) { emit addOutput(tr("Persisting CMake state..."), BuildStep::OutputFormat::NormalMessage); m_waiting = true; - } else if (buildConfiguration()->buildSystem()->isWaitingForParse()) { + } else if (buildSystem()->isWaitingForParse()) { emit addOutput(tr("Running CMake in preparation to build..."), BuildStep::OutputFormat::NormalMessage); m_waiting = true; } @@ -359,8 +372,8 @@ Utils::CommandLine CMakeBuildStep::cmakeCommand(RunConfiguration *rc) const QStringList CMakeBuildStep::knownBuildTargets() { - auto bc = qobject_cast<CMakeBuildSystem *>(buildConfiguration()->buildSystem()); - return bc ? bc->buildTargetTitles() : QStringList(); + auto bs = qobject_cast<CMakeBuildSystem *>(buildSystem()); + return bs ? bs->buildTargetTitles() : QStringList(); } QString CMakeBuildStep::cleanTarget() @@ -528,16 +541,10 @@ QRadioButton *CMakeBuildStepConfigWidget::itemWidget(QListWidgetItem *item) void CMakeBuildStepConfigWidget::updateDetails() { - BuildConfiguration *bc = m_buildStep->buildConfiguration(); - if (!bc) { - setSummaryText(tr("<b>No build configuration found on this kit.</b>")); - return; - } - ProcessParameters param; - param.setMacroExpander(bc->macroExpander()); - param.setEnvironment(bc->environment()); - param.setWorkingDirectory(bc->buildDirectory()); + param.setMacroExpander(m_buildStep->macroExpander()); + param.setEnvironment(m_buildStep->buildEnvironment()); + param.setWorkingDirectory(m_buildStep->buildDirectory()); param.setCommandLine(m_buildStep->cmakeCommand(nullptr)); setSummaryText(param.summary(displayName())); @@ -565,3 +572,6 @@ void CMakeBuildStep::processFinished(int exitCode, QProcess::ExitStatus status) AbstractProcessStep::processFinished(exitCode, status); emit progress(100, QString()); } + +} // Internal +} // CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.h b/src/plugins/cmakeprojectmanager/cmakebuildstep.h index 1938c88b10..cd41f77f41 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildstep.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.h @@ -27,22 +27,9 @@ #include <projectexplorer/abstractprocessstep.h> -#include <QRegExp> +namespace Utils { class CommandLine; } -QT_BEGIN_NAMESPACE -class QLineEdit; -class QListWidget; -class QListWidgetItem; -class QRadioButton; -QT_END_NAMESPACE - -namespace Utils { -class CommandLine; -} // Utils - -namespace ProjectExplorer { -class RunConfiguration; -} // ProjectManager +namespace ProjectExplorer { class RunConfiguration; } namespace CMakeProjectManager { namespace Internal { @@ -117,26 +104,6 @@ private: bool m_waiting = false; }; -class CMakeBuildStepConfigWidget : public ProjectExplorer::BuildStepConfigWidget -{ - Q_OBJECT -public: - CMakeBuildStepConfigWidget(CMakeBuildStep *buildStep); - -private: - void itemChanged(QListWidgetItem*); - void toolArgumentsEdited(); - void updateDetails(); - void buildTargetsChanged(); - void updateBuildTarget(); - - QRadioButton *itemWidget(QListWidgetItem *item); - - CMakeBuildStep *m_buildStep; - QLineEdit *m_toolArguments; - QListWidget *m_buildTargetsList; -}; - class CMakeBuildStepFactory : public ProjectExplorer::BuildStepFactory { public: diff --git a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp index 88f4b7726f..a5c2243c88 100644 --- a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp +++ b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp @@ -466,7 +466,20 @@ private: namespace { -struct GeneratorInfo { +class GeneratorInfo +{ +public: + GeneratorInfo() = default; + GeneratorInfo(const QString &generator_, + const QString &extraGenerator_ = QString(), + const QString &platform_ = QString(), + const QString &toolset_ = QString()) + : generator(generator_) + , extraGenerator(extraGenerator_) + , platform(platform_) + , toolset(toolset_) + {} + QVariant toVariant() const { QVariantMap result; result.insert(GENERATOR_KEY, generator); @@ -568,10 +581,12 @@ void CMakeGeneratorKitAspect::setToolset(Kit *k, const QString &toolset) } void CMakeGeneratorKitAspect::set(Kit *k, - const QString &generator, const QString &extraGenerator, - const QString &platform, const QString &toolset) + const QString &generator, + const QString &extraGenerator, + const QString &platform, + const QString &toolset) { - GeneratorInfo info = {generator, extraGenerator, platform, toolset}; + GeneratorInfo info(generator, extraGenerator, platform, toolset); setGeneratorInfo(k, info); } @@ -605,12 +620,9 @@ QVariant CMakeGeneratorKitAspect::defaultValue(const Kit *k) const if (!tool) return QVariant(); - const QString extraGenerator = "CodeBlocks"; - - QList<CMakeTool::Generator> known = tool->supportedGenerators(); - auto it = std::find_if(known.constBegin(), known.constEnd(), - [extraGenerator](const CMakeTool::Generator &g) { - return g.matches("Ninja", extraGenerator); + const QList<CMakeTool::Generator> known = tool->supportedGenerators(); + auto it = std::find_if(known.constBegin(), known.constEnd(), [](const CMakeTool::Generator &g) { + return g.matches("Ninja"); }); if (it != known.constEnd()) { const bool hasNinja = [k]() { @@ -626,29 +638,30 @@ QVariant CMakeGeneratorKitAspect::defaultValue(const Kit *k) const }(); if (hasNinja) - return GeneratorInfo({QString("Ninja"), extraGenerator, QString(), QString()}).toVariant(); + return GeneratorInfo("Ninja").toVariant(); } if (Utils::HostOsInfo::isWindowsHost()) { // *sigh* Windows with its zoo of incompatible stuff again... - ToolChain *tc = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID); + ToolChain *tc = ToolChainKitAspect::cxxToolChain(k); if (tc && tc->typeId() == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID) { - it = std::find_if(known.constBegin(), known.constEnd(), - [extraGenerator](const CMakeTool::Generator &g) { - return g.matches("MinGW Makefiles", extraGenerator); - }); + it = std::find_if(known.constBegin(), + known.constEnd(), + [](const CMakeTool::Generator &g) { + return g.matches("MinGW Makefiles"); + }); } else { - it = std::find_if(known.constBegin(), known.constEnd(), - [extraGenerator](const CMakeTool::Generator &g) { - return g.matches("NMake Makefiles", extraGenerator) - || g.matches("NMake Makefiles JOM", extraGenerator); - }); + it = std::find_if(known.constBegin(), + known.constEnd(), + [](const CMakeTool::Generator &g) { + return g.matches("NMake Makefiles") + || g.matches("NMake Makefiles JOM"); + }); } } else { // Unix-oid OSes: - it = std::find_if(known.constBegin(), known.constEnd(), - [extraGenerator](const CMakeTool::Generator &g) { - return g.matches("Unix Makefiles", extraGenerator); + it = std::find_if(known.constBegin(), known.constEnd(), [](const CMakeTool::Generator &g) { + return g.matches("Unix Makefiles"); }); } if (it == known.constEnd()) @@ -656,7 +669,7 @@ QVariant CMakeGeneratorKitAspect::defaultValue(const Kit *k) const if (it == known.constEnd()) return QVariant(); - return GeneratorInfo({it->name, extraGenerator, QString(), QString()}).toVariant(); + return GeneratorInfo(it->name).toVariant(); } Tasks CMakeGeneratorKitAspect::validate(const Kit *k) const @@ -723,9 +736,10 @@ void CMakeGeneratorKitAspect::fix(Kit *k) dv.fromVariant(defaultValue(k)); setGeneratorInfo(k, dv); } else { - const GeneratorInfo dv = {info.generator, info.extraGenerator, - it->supportsPlatform ? info.platform : QString(), - it->supportsToolset ? info.toolset : QString()}; + const GeneratorInfo dv(info.generator, + info.extraGenerator, + it->supportsPlatform ? info.platform : QString(), + it->supportsToolset ? info.toolset : QString()); setGeneratorInfo(k, dv); } } @@ -964,8 +978,8 @@ Tasks CMakeConfigurationKitAspect::validate(const Kit *k) const QTC_ASSERT(k, return Tasks()); const QtSupport::BaseQtVersion *const version = QtSupport::QtKitAspect::qtVersion(k); - const ToolChain *const tcC = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::C_LANGUAGE_ID); - const ToolChain *const tcCxx = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID); + const ToolChain *const tcC = ToolChainKitAspect::cToolChain(k); + const ToolChain *const tcCxx = ToolChainKitAspect::cxxToolChain(k); const CMakeConfig config = configuration(k); const bool isQt4 = version && version->qtVersion() < QtSupport::QtVersionNumber(5, 0, 0); diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro index c1b26eabd8..fe333b278c 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro @@ -39,8 +39,7 @@ HEADERS = builddirmanager.h \ fileapireader.h \ projecttreehelper.h \ servermode.h \ - servermodereader.h \ - tealeafreader.h + servermodereader.h SOURCES = builddirmanager.cpp \ builddirparameters.cpp \ @@ -77,8 +76,7 @@ SOURCES = builddirmanager.cpp \ fileapireader.cpp \ projecttreehelper.cpp \ servermode.cpp \ - servermodereader.cpp \ - tealeafreader.cpp + servermodereader.cpp RESOURCES += cmakeproject.qrc diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs index 6b002345ed..8b3ca447bd 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs @@ -95,8 +95,6 @@ QtcPlugin { "servermode.cpp", "servermode.h", "servermodereader.cpp", - "servermodereader.h", - "tealeafreader.cpp", - "tealeafreader.h" + "servermodereader.h" ] } diff --git a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp index c7d2c001ce..02536d6123 100644 --- a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp +++ b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp @@ -110,6 +110,7 @@ public: , m_isAutoRun(item->isAutoRun()) , m_autoCreateBuildDirectory(item->autoCreateBuildDirectory()) , m_autodetected(item->isAutoDetected()) + , m_isSupported(item->hasFileApi() || item->hasServerMode()) , m_changed(changed) { updateErrorFlags(); @@ -186,6 +187,10 @@ public: error = QCoreApplication::translate( "CMakeProjectManager::Internal::CMakeToolTreeItem", "CMake executable path is not executable."); + } else if (!m_isSupported) { + error = QCoreApplication::translate( + "CMakeProjectManager::Internal::CMakeToolTreeItem", + "CMake executable does not provided required IDE integration features."); } if (result.isEmpty() || error.isEmpty()) return QString("%1%2").arg(result).arg(error); @@ -216,6 +221,7 @@ public: bool m_pathIsExecutable = false; bool m_autoCreateBuildDirectory = false; bool m_autodetected = false; + bool m_isSupported = false; bool m_changed = true; }; diff --git a/src/plugins/cmakeprojectmanager/cmaketool.cpp b/src/plugins/cmakeprojectmanager/cmaketool.cpp index 52f6f67893..c602543681 100644 --- a/src/plugins/cmakeprojectmanager/cmaketool.cpp +++ b/src/plugins/cmakeprojectmanager/cmaketool.cpp @@ -60,7 +60,6 @@ bool CMakeTool::Generator::matches(const QString &n, const QString &ex) const namespace Internal { -const char READER_TYPE_TEALEAF[] = "tealeaf"; const char READER_TYPE_SERVERMODE[] = "servermode"; const char READER_TYPE_FILEAPI[] = "fileapi"; @@ -72,8 +71,6 @@ static bool ignoreFileApi() static Utils::optional<CMakeTool::ReaderType> readerTypeFromString(const QString &input) { - if (input == READER_TYPE_TEALEAF) - return CMakeTool::TeaLeaf; if (input == READER_TYPE_SERVERMODE) return CMakeTool::ServerMode; if (input == READER_TYPE_FILEAPI) @@ -84,14 +81,12 @@ static Utils::optional<CMakeTool::ReaderType> readerTypeFromString(const QString static QString readerTypeToString(const CMakeTool::ReaderType &type) { switch (type) { - case CMakeTool::TeaLeaf: - return QString(READER_TYPE_TEALEAF); case CMakeTool::ServerMode: return QString(READER_TYPE_SERVERMODE); case CMakeTool::FileApi: return QString(READER_TYPE_FILEAPI); } - return QString(); + return QString("<INVALID>"); } // -------------------------------------------------------------------- @@ -205,7 +200,7 @@ bool CMakeTool::isValid() const if (!m_introspection->m_didAttemptToRun) supportedGenerators(); - return m_introspection->m_didRun; + return m_introspection->m_didRun && (hasFileApi() || hasServerMode()); } Utils::SynchronousProcessResponse CMakeTool::run(const QStringList &args, int timeoutS) const @@ -386,7 +381,6 @@ CMakeTool::ReaderType CMakeTool::readerType() const } if (hasServerMode()) return ServerMode; - return TeaLeaf; } return m_readerType.value(); } diff --git a/src/plugins/cmakeprojectmanager/cmaketool.h b/src/plugins/cmakeprojectmanager/cmaketool.h index fd2c087c20..8c88ec40d4 100644 --- a/src/plugins/cmakeprojectmanager/cmaketool.h +++ b/src/plugins/cmakeprojectmanager/cmaketool.h @@ -51,7 +51,7 @@ class CMAKE_EXPORT CMakeTool public: enum Detection { ManualDetection, AutoDetection }; - enum ReaderType { TeaLeaf, ServerMode, FileApi }; + enum ReaderType { ServerMode, FileApi }; struct Version { @@ -73,7 +73,7 @@ public: bool supportsPlatform = true; bool supportsToolset = true; - bool matches(const QString &n, const QString &ex) const; + bool matches(const QString &n, const QString &ex = QString()) const; }; using PathMapper = std::function<Utils::FilePath (const Utils::FilePath &)>; diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.cpp b/src/plugins/cmakeprojectmanager/tealeafreader.cpp deleted file mode 100644 index 8b03b33f60..0000000000 --- a/src/plugins/cmakeprojectmanager/tealeafreader.cpp +++ /dev/null @@ -1,528 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** 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 -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "tealeafreader.h" - -#include "builddirmanager.h" -#include "cmakebuildconfiguration.h" -#include "cmakecbpparser.h" -#include "cmakekitinformation.h" -#include "cmakeprocess.h" -#include "cmakeprojectconstants.h" -#include "cmakeprojectnodes.h" - -#include <coreplugin/documentmanager.h> -#include <coreplugin/editormanager/editormanager.h> -#include <coreplugin/idocument.h> -#include <projectexplorer/headerpath.h> -#include <projectexplorer/kitinformation.h> -#include <projectexplorer/projectexplorerconstants.h> -#include <projectexplorer/target.h> -#include <projectexplorer/toolchain.h> -#include <projectexplorer/toolchainmanager.h> - -#include <utils/algorithm.h> -#include <utils/qtcassert.h> -#include <utils/qtcprocess.h> - -#include <QDateTime> -#include <QFileInfo> - -using namespace Core; -using namespace ProjectExplorer; -using namespace Utils; - -namespace CMakeProjectManager { -namespace Internal { - -// -------------------------------------------------------------------- -// TeaLeafReader: -// -------------------------------------------------------------------- - -TeaLeafReader::TeaLeafReader() -{ - connect(EditorManager::instance(), &EditorManager::aboutToSave, - this, [this](const IDocument *document) { - if (m_cmakeFiles.contains(document->filePath()) - || !m_parameters.cmakeTool() - || !m_parameters.cmakeTool()->isAutoRun()) - emit dirty(); - }); - - // Remove \' (quote) for function-style macrosses: - // -D'MACRO()'=xxx - // -D'MACRO()=xxx' - // -D'MACRO()' - // otherwise, compiler will fails - m_macroFixupRe1.setPattern("^-D(\\s*)'([0-9a-zA-Z_\\(\\)]+)'="); - m_macroFixupRe2.setPattern("^-D(\\s*)'([0-9a-zA-Z_\\(\\)]+)=(.+)'$"); - m_macroFixupRe3.setPattern("^-D(\\s*)'([0-9a-zA-Z_\\(\\)]+)'$"); -} - -TeaLeafReader::~TeaLeafReader() -{ - stop(); - resetData(); -} - -void TeaLeafReader::setParameters(const BuildDirParameters &p) -{ - m_parameters = p; - emit isReadyNow(); -} - -bool TeaLeafReader::isCompatible(const BuildDirParameters &p) -{ - return p.cmakeTool() && p.cmakeTool()->readerType() == CMakeTool::TeaLeaf; -} - -void TeaLeafReader::resetData() -{ - m_projectName.clear(); - m_buildTargets.clear(); - m_files.clear(); -} - -static QString findCbpFile(const QDir &directory) -{ - // Find the cbp file - // the cbp file is named like the project() command in the CMakeList.txt file - // so this function below could find the wrong cbp file, if the user changes the project() - // 2name - QDateTime t; - QString file; - foreach (const QString &cbpFile , directory.entryList()) { - if (cbpFile.endsWith(QLatin1String(".cbp"))) { - QFileInfo fi(directory.path() + QLatin1Char('/') + cbpFile); - if (t.isNull() || fi.lastModified() > t) { - file = directory.path() + QLatin1Char('/') + cbpFile; - t = fi.lastModified(); - } - } - } - return file; -} - -void TeaLeafReader::parse(bool forceCMakeRun, bool forceConfiguration) -{ - emit configurationStarted(); - - const QString cbpFile = findCbpFile(QDir(m_parameters.workDirectory.toString())); - const QFileInfo cbpFileFi = cbpFile.isEmpty() ? QFileInfo() : QFileInfo(cbpFile); - if (!cbpFileFi.exists() || forceConfiguration) { - // Initial create: - const FilePath path = m_parameters.workDirectory.pathAppended("qtcsettings.cmake"); - startCMake(QStringList({QString("-C"), path.toUserOutput()})); - return; - } - - const bool mustUpdate = forceCMakeRun || m_cmakeFiles.isEmpty() - || anyOf(m_cmakeFiles, [&cbpFileFi](const FilePath &f) { - return f.toFileInfo().lastModified() > cbpFileFi.lastModified(); - }); - if (mustUpdate) { - startCMake(QStringList()); - } else { - extractData(); - emit dataAvailable(); - } -} - -void TeaLeafReader::stop() -{ - m_cmakeProcess.reset(); -} - -bool TeaLeafReader::isParsing() const -{ - return m_cmakeProcess && m_cmakeProcess->state() != QProcess::NotRunning; -} - -QSet<FilePath> TeaLeafReader::projectFilesToWatch() const -{ - return m_cmakeFiles; -} - -QList<CMakeBuildTarget> TeaLeafReader::takeBuildTargets(QString &errorMessage) -{ - Q_UNUSED(errorMessage) - return m_buildTargets; -} - -CMakeConfig TeaLeafReader::takeParsedConfiguration(QString &errorMessage) -{ - const FilePath cacheFile = m_parameters.workDirectory.pathAppended("CMakeCache.txt"); - - if (!cacheFile.exists()) - return { }; - - CMakeConfig result = BuildDirManager::parseCMakeConfiguration(cacheFile, &errorMessage); - - if (!errorMessage.isEmpty()) { - return { }; - } - - const FilePath sourceOfBuildDir - = FilePath::fromUtf8(CMakeConfigItem::valueOf("CMAKE_HOME_DIRECTORY", result)); - const FilePath canonicalSourceOfBuildDir = sourceOfBuildDir.canonicalPath(); - const FilePath canonicalSourceDirectory = m_parameters.sourceDirectory.canonicalPath(); - if (canonicalSourceOfBuildDir != canonicalSourceDirectory) { // Uses case-insensitive compare where appropriate - errorMessage = tr("The build directory is not for %1 but for %2") - .arg(canonicalSourceOfBuildDir.toUserOutput(), - canonicalSourceDirectory.toUserOutput()); - return { }; - } - return result; -} - -std::unique_ptr<CMakeProjectNode> TeaLeafReader::generateProjectTree( - const QList<const FileNode *> &allFiles, QString &errorMessage) -{ - Q_UNUSED(errorMessage) - if (m_files.size() == 0) - return {}; - - auto root = std::make_unique<CMakeProjectNode>(m_parameters.sourceDirectory); - root->setDisplayName(m_projectName); - - QSet<FilePath> allIncludePathSet; - for (const CMakeBuildTarget &bt : m_buildTargets) { - const QList<Utils::FilePath> targetIncludePaths - = Utils::filtered(bt.includeFiles, [this](const Utils::FilePath &fn) { - return fn.isChildOf(m_parameters.sourceDirectory); - }); - allIncludePathSet.unite(Utils::toSet(targetIncludePaths)); - } - const QList<FilePath> allIncludePaths = Utils::toList(allIncludePathSet); - - const QList<const FileNode *> missingHeaders - = Utils::filtered(allFiles, [&allIncludePaths](const FileNode *fn) -> bool { - if (fn->fileType() != FileType::Header) - return false; - - return Utils::contains(allIncludePaths, [fn](const FilePath &inc) { return fn->filePath().isChildOf(inc); }); - }); - - // filter duplicates: - auto alreadySeen = Utils::transform<QSet>(m_files, &FileNode::filePath); - const QList<const FileNode *> unseenMissingHeaders = Utils::filtered(missingHeaders, [&alreadySeen](const FileNode *fn) { - const int count = alreadySeen.count(); - alreadySeen.insert(fn->filePath()); - return (alreadySeen.count() != count); - }); - - root->addNestedNodes(std::move(m_files), m_parameters.sourceDirectory); - - std::vector<std::unique_ptr<FileNode>> fileNodes - = transform<std::vector>(unseenMissingHeaders, [](const FileNode *fn) { - return std::unique_ptr<FileNode>(fn->clone()); - }); - root->addNestedNodes(std::move(fileNodes), m_parameters.sourceDirectory); - - return root; -} - -static void processCMakeIncludes(const CMakeBuildTarget &cbt, const ToolChain *tc, - const QStringList& flags, const FilePath &sysroot, - QSet<FilePath> &tcIncludes, QStringList &includePaths) -{ - if (!tc) - return; - - foreach (const HeaderPath &hp, tc->builtInHeaderPaths(flags, sysroot, - Environment::systemEnvironment())) { - tcIncludes.insert(FilePath::fromString(hp.path)); - } - foreach (const FilePath &i, cbt.includeFiles) { - if (!tcIncludes.contains(i)) - includePaths.append(i.toString()); - } -} - -RawProjectParts TeaLeafReader::createRawProjectParts(QString &errorMessage) -{ - Q_UNUSED(errorMessage) - const ToolChain *tcCxx = ToolChainManager::findToolChain(m_parameters.cxxToolChainId); - const ToolChain *tcC = ToolChainManager::findToolChain(m_parameters.cToolChainId); - const FilePath sysroot = m_parameters.sysRoot; - - RawProjectParts rpps; - QHash<QString, QStringList> targetDataCacheCxx; - QHash<QString, QStringList> targetDataCacheC; - foreach (const CMakeBuildTarget &cbt, m_buildTargets) { - if (cbt.targetType == UtilityType) - continue; - - // CMake shuffles the include paths that it reports via the CodeBlocks generator - // So remove the toolchain include paths, so that at least those end up in the correct - // place. - auto cxxflags = getFlagsFor(cbt, targetDataCacheCxx, ProjectExplorer::Constants::CXX_LANGUAGE_ID); - auto cflags = getFlagsFor(cbt, targetDataCacheC, ProjectExplorer::Constants::C_LANGUAGE_ID); - QSet<FilePath> tcIncludes; - QStringList includePaths; - if (tcCxx || tcC) { - processCMakeIncludes(cbt, tcCxx, cxxflags, sysroot, tcIncludes, includePaths); - processCMakeIncludes(cbt, tcC, cflags, sysroot, tcIncludes, includePaths); - } else { - includePaths = transform(cbt.includeFiles, &FilePath::toString); - } - includePaths += m_parameters.workDirectory.toString(); - RawProjectPart rpp; - rpp.setProjectFileLocation(cbt.sourceDirectory.toString() + "/CMakeLists.txt"); - rpp.setBuildSystemTarget(cbt.title); - rpp.setIncludePaths(includePaths); - - RawProjectPartFlags cProjectFlags; - cProjectFlags.commandLineFlags = cflags; - rpp.setFlagsForC(cProjectFlags); - - RawProjectPartFlags cxxProjectFlags; - cxxProjectFlags.commandLineFlags = cxxflags; - rpp.setFlagsForCxx(cxxProjectFlags); - - rpp.setMacros(cbt.macros); - rpp.setDisplayName(cbt.title); - rpp.setFiles(transform(cbt.files, &FilePath::toString)); - - const bool isExecutable = cbt.targetType == ExecutableType; - rpp.setBuildTargetType(isExecutable ? ProjectExplorer::BuildTargetType::Executable - : ProjectExplorer::BuildTargetType::Library); - rpps.append(rpp); - } - - return rpps; -} - -void TeaLeafReader::extractData() -{ - CMakeTool *cmake = m_parameters.cmakeTool(); - QTC_ASSERT(m_parameters.isValid() && cmake, return); - - const FilePath srcDir = m_parameters.sourceDirectory; - const FilePath bldDir = m_parameters.workDirectory; - const FilePath topCMake = srcDir.pathAppended("CMakeLists.txt"); - - resetData(); - - m_projectName = m_parameters.projectName; - m_files.emplace_back(std::make_unique<FileNode>(topCMake, FileType::Project)); - // Do not insert topCMake into m_cmakeFiles: The project already watches that! - - // Find cbp file - FilePath cbpFile = FilePath::fromString(findCbpFile(bldDir.toString())); - if (cbpFile.isEmpty()) - return; - m_cmakeFiles.insert(cbpFile); - - // Add CMakeCache.txt file: - const FilePath cacheFile = m_parameters.workDirectory.pathAppended("CMakeCache.txt"); - if (cacheFile.exists()) - m_cmakeFiles.insert(cacheFile); - - // setFolderName - CMakeCbpParser cbpparser; - // Parsing - if (!cbpparser.parseCbpFile(cmake->pathMapper(), cbpFile, srcDir)) - return; - - m_projectName = cbpparser.projectName(); - - m_files = cbpparser.takeFileList(); - if (cbpparser.hasCMakeFiles()) { - std::vector<std::unique_ptr<FileNode>> cmakeNodes = cbpparser.takeCmakeFileList(); - for (const std::unique_ptr<FileNode> &node : cmakeNodes) - m_cmakeFiles.insert(node->filePath()); - - std::move(std::begin(cmakeNodes), std::end(cmakeNodes), std::back_inserter(m_files)); - } - - // Make sure the top cmakelists.txt file is always listed: - if (!contains(m_files, [topCMake](const std::unique_ptr<FileNode> &fn) { - return fn->filePath() == topCMake; - })) - m_files.emplace_back(std::make_unique<FileNode>(topCMake, FileType::Project)); - - m_buildTargets = cbpparser.buildTargets(); -} - -void TeaLeafReader::startCMake(const QStringList &configurationArguments) -{ - QTC_ASSERT(!m_cmakeProcess, return); - - m_cmakeProcess = std::make_unique<CMakeProcess>(); - - connect(m_cmakeProcess.get(), &CMakeProcess::finished, - this, &TeaLeafReader::cmakeFinished); - - m_cmakeProcess->run(m_parameters, configurationArguments); -} - -void TeaLeafReader::cmakeFinished(int code, QProcess::ExitStatus status) -{ - Q_UNUSED(code) - Q_UNUSED(status) - - QTC_ASSERT(m_cmakeProcess, return); - m_cmakeProcess.reset(); - - extractData(); // try even if cmake failed... - - emit dataAvailable(); -} - -QStringList TeaLeafReader::getFlagsFor(const CMakeBuildTarget &buildTarget, - QHash<QString, QStringList> &cache, - Id lang) const -{ - // check cache: - auto it = cache.constFind(buildTarget.title); - if (it != cache.constEnd()) - return *it; - - if (extractFlagsFromMake(buildTarget, cache, lang)) - return cache.value(buildTarget.title); - - if (extractFlagsFromNinja(buildTarget, cache, lang)) - return cache.value(buildTarget.title); - - cache.insert(buildTarget.title, QStringList()); - return QStringList(); -} - -bool TeaLeafReader::extractFlagsFromMake(const CMakeBuildTarget &buildTarget, - QHash<QString, QStringList> &cache, - Id lang) const -{ - QString flagsPrefix; - - if (lang == ProjectExplorer::Constants::CXX_LANGUAGE_ID) - flagsPrefix = QLatin1String("CXX_FLAGS ="); - else if (lang == ProjectExplorer::Constants::C_LANGUAGE_ID) - flagsPrefix = QLatin1String("C_FLAGS ="); - else - return false; - - QString makeCommand = buildTarget.makeCommand.toString(); - int startIndex = makeCommand.indexOf('\"'); - int endIndex = makeCommand.indexOf('\"', startIndex + 1); - if (startIndex != -1 && endIndex != -1) { - startIndex += 1; - QString makefile = makeCommand.mid(startIndex, endIndex - startIndex); - int slashIndex = makefile.lastIndexOf('/'); - makefile.truncate(slashIndex); - makefile.append("/CMakeFiles/" + buildTarget.title + ".dir/flags.make"); - // Remove un-needed shell escaping: - makefile = makefile.remove("\\"); - QFile file(makefile); - if (file.exists()) { - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) - return false; - QTextStream stream(&file); - while (!stream.atEnd()) { - QString line = stream.readLine().trimmed(); - if (line.startsWith(flagsPrefix)) { - // Skip past = - auto flags = - Utils::transform(line.mid(flagsPrefix.length()).trimmed().split(' ', QString::SkipEmptyParts), [this](QString flag) -> QString { - // TODO: maybe Gcc-specific - // Remove \' (quote) for function-style macrosses: - // -D'MACRO()'=xxx - // -D'MACRO()=xxx' - // -D'MACRO()' - // otherwise, compiler will fails - return flag - .replace(m_macroFixupRe1, "-D\\1\\2=") - .replace(m_macroFixupRe2, "-D\\1\\2=\\3") - .replace(m_macroFixupRe3, "-D\\1\\2"); - }); - cache.insert(buildTarget.title, flags); - return true; - } - } - } - } - return false; -} - -bool TeaLeafReader::extractFlagsFromNinja(const CMakeBuildTarget &buildTarget, - QHash<QString, QStringList> &cache, - Id lang) const -{ - Q_UNUSED(buildTarget) - if (!cache.isEmpty()) // We fill the cache in one go! - return false; - - QString compilerPrefix; - if (lang == ProjectExplorer::Constants::CXX_LANGUAGE_ID) - compilerPrefix = QLatin1String("CXX_COMPILER"); - else if (lang == ProjectExplorer::Constants::C_LANGUAGE_ID) - compilerPrefix = QLatin1String("C_COMPILER"); - else - return false; - - // Attempt to find build.ninja file and obtain FLAGS (CXX_FLAGS/C_FLAGS) from there if no suitable flags.make were - // found - // Get "all" target's working directory - QByteArray ninjaFile; - QString buildNinjaFile = m_buildTargets.at(0).workingDirectory.toString(); - buildNinjaFile += "/build.ninja"; - QFile buildNinja(buildNinjaFile); - if (buildNinja.exists()) { - if (!buildNinja.open(QIODevice::ReadOnly | QIODevice::Text)) - return false; - ninjaFile = buildNinja.readAll(); - buildNinja.close(); - } - - if (ninjaFile.isEmpty()) - return false; - - QTextStream stream(ninjaFile); - bool compilerFound = false; - const QString targetSignature = "# Object build statements for "; - QString currentTarget; - - while (!stream.atEnd()) { - // 1. Look for a block that refers to the current target - // 2. Look for a build rule which invokes CXX_COMPILER - // 3. Return the FLAGS definition - QString line = stream.readLine().trimmed(); - if (line.startsWith('#')) { - if (line.startsWith(targetSignature)) { - int pos = line.lastIndexOf(' '); - currentTarget = line.mid(pos + 1); - } - } else if (!currentTarget.isEmpty() && line.startsWith("build")) { - compilerFound = line.indexOf(compilerPrefix) != -1; - } else if (compilerFound && line.startsWith("FLAGS =")) { - // Skip past = - cache.insert(currentTarget, line.mid(7).trimmed().split(' ', QString::SkipEmptyParts)); - } - } - return !cache.isEmpty(); -} - -} // namespace Internal -} // namespace CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.h b/src/plugins/cmakeprojectmanager/tealeafreader.h deleted file mode 100644 index ae77afc47c..0000000000 --- a/src/plugins/cmakeprojectmanager/tealeafreader.h +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** 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 -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include <projectexplorer/toolchain.h> - -#include "builddirreader.h" -#include "cmakeprocess.h" - -#include <QRegularExpression> - -namespace Utils { class QtcProcess; } - -namespace CMakeProjectManager { -namespace Internal { - -class TeaLeafReader final : public BuildDirReader -{ - Q_OBJECT - -public: - TeaLeafReader(); - ~TeaLeafReader() final; - - void setParameters(const BuildDirParameters &p) final; - - bool isCompatible(const BuildDirParameters &p) final; - void resetData() final; - void parse(bool forceCMakeRun, bool forceConfiguration) final; - void stop() final; - - bool isParsing() const final; - - QSet<Utils::FilePath> projectFilesToWatch() const final; - QList<CMakeBuildTarget> takeBuildTargets(QString &errorMessage) final; - CMakeConfig takeParsedConfiguration(QString &errorMessage) final; - std::unique_ptr<CMakeProjectNode> generateProjectTree( - const QList<const ProjectExplorer::FileNode *> &allFiles, QString &errorMessage) final; - ProjectExplorer::RawProjectParts createRawProjectParts(QString &errorMessage) final; - -private: - void extractData(); - - void startCMake(const QStringList &configurationArguments); - - void cmakeFinished(int code, QProcess::ExitStatus status); - - QStringList getFlagsFor(const CMakeBuildTarget &buildTarget, QHash<QString, QStringList> &cache, Core::Id lang) const; - bool extractFlagsFromMake(const CMakeBuildTarget &buildTarget, QHash<QString, QStringList> &cache, Core::Id lang) const; - bool extractFlagsFromNinja(const CMakeBuildTarget &buildTarget, QHash<QString, QStringList> &cache, Core::Id lang) const; - - // Process data: - std::unique_ptr<CMakeProcess> m_cmakeProcess; - - QSet<Utils::FilePath> m_cmakeFiles; - QString m_projectName; - QList<CMakeBuildTarget> m_buildTargets; - std::vector<std::unique_ptr<ProjectExplorer::FileNode>> m_files; - - // RegExps for function-like macrosses names fixups - QRegularExpression m_macroFixupRe1; - QRegularExpression m_macroFixupRe2; - QRegularExpression m_macroFixupRe3; - - friend class CMakeFile; -}; - -} // namespace Internal -} // namespace CMakeProjectManager diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp index 6dce6ed9fc..dcffa6ae3e 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp @@ -52,7 +52,6 @@ #include <utils/runextensions.h> #include <QFileDialog> -#include <QTimer> #ifdef Q_OS_WIN #include <Windows.h> @@ -339,20 +338,15 @@ void createTree(std::unique_ptr<ProjectNode> &root, CompilationDatabaseBuildSystem::CompilationDatabaseBuildSystem(Target *target) : BuildSystem(target) , m_cppCodeModelUpdater(std::make_unique<CppTools::CppProjectUpdater>()) - , m_parseDelay(new QTimer(this)) , m_deployFileWatcher(new FileSystemWatcher(this)) { connect(target->project(), &CompilationDatabaseProject::rootProjectDirectoryChanged, this, [this] { m_projectFileHash.clear(); - m_parseDelay->start(); + requestDelayedParse(); }); - connect(m_parseDelay, &QTimer::timeout, this, &CompilationDatabaseBuildSystem::reparseProject); - - m_parseDelay->setSingleShot(true); - m_parseDelay->setInterval(1000); - m_parseDelay->start(); + requestDelayedParse(); connect(project(), &Project::projectFileIsDirty, this, &CompilationDatabaseBuildSystem::reparseProject); diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h index 34eec1d578..bb98f5213e 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h @@ -37,10 +37,6 @@ #include <QFutureWatcher> -QT_BEGIN_NAMESPACE -class QTimer; -QT_END_NAMESPACE - namespace CppTools { class CppProjectUpdater; } namespace ProjectExplorer { class Kit; } namespace Utils { class FileSystemWatcher; } @@ -77,7 +73,6 @@ public: std::unique_ptr<CppTools::CppProjectUpdater> m_cppCodeModelUpdater; MimeBinaryCache m_mimeBinaryCache; QByteArray m_projectFileHash; - QTimer * const m_parseDelay; CompilationDbParser *m_parser = nullptr; Utils::FileSystemWatcher * const m_deployFileWatcher; }; diff --git a/src/plugins/coreplugin/CMakeLists.txt b/src/plugins/coreplugin/CMakeLists.txt index 06194cddf5..0c071e8ef7 100644 --- a/src/plugins/coreplugin/CMakeLists.txt +++ b/src/plugins/coreplugin/CMakeLists.txt @@ -179,9 +179,8 @@ extend_qtc_plugin(Core ) extend_qtc_plugin(Core - CONDITION TARGET Qt5::Script + CONDITION Qt5_VERSION VERSION_GREATER_EQUAL 5.14.0 FEATURE_INFO "Script Locator filter" - DEPENDS Qt5::Script DEFINES WITH_JAVASCRIPTFILTER SOURCES locator/javascriptfilter.cpp locator/javascriptfilter.h diff --git a/src/plugins/coreplugin/actionmanager/actionmanager.cpp b/src/plugins/coreplugin/actionmanager/actionmanager.cpp index 449a0040bc..eff51a816b 100644 --- a/src/plugins/coreplugin/actionmanager/actionmanager.cpp +++ b/src/plugins/coreplugin/actionmanager/actionmanager.cpp @@ -30,6 +30,7 @@ #include <coreplugin/icore.h> #include <coreplugin/id.h> +#include <utils/algorithm.h> #include <utils/fadingindicator.h> #include <utils/qtcassert.h> @@ -46,6 +47,7 @@ namespace { } static const char kKeyboardSettingsKey[] = "KeyboardShortcuts"; +static const char kKeyboardSettingsKeyV2[] = "KeyboardShortcutsV2"; using namespace Core; using namespace Core::Internal; @@ -495,22 +497,50 @@ Action *ActionManagerPrivate::overridableAction(Id id) void ActionManagerPrivate::readUserSettings(Id id, Action *cmd) { + // TODO Settings V2 were introduced in Qt Creator 4.13, remove old settings at some point QSettings *settings = ICore::settings(); - settings->beginGroup(QLatin1String(kKeyboardSettingsKey)); - if (settings->contains(id.toString())) - cmd->setKeySequence(QKeySequence(settings->value(id.toString()).toString())); + // transfer from old settings if not done before + const QString group = settings->childGroups().contains(kKeyboardSettingsKeyV2) + ? QString(kKeyboardSettingsKeyV2) + : QString(kKeyboardSettingsKey); + settings->beginGroup(group); + if (settings->contains(id.toString())) { + const QVariant v = settings->value(id.toString()); + if (QMetaType::Type(v.type()) == QMetaType::QStringList) { + cmd->setKeySequences(Utils::transform<QList>(v.toStringList(), [](const QString &s) { + return QKeySequence::fromString(s); + })); + } else { + cmd->setKeySequences({QKeySequence::fromString(v.toString())}); + } + } settings->endGroup(); } void ActionManagerPrivate::saveSettings(Action *cmd) { - const QString settingsKey = QLatin1String(kKeyboardSettingsKey) + QLatin1Char('/') - + cmd->id().toString(); - QKeySequence key = cmd->keySequence(); - if (key != cmd->defaultKeySequence()) - ICore::settings()->setValue(settingsKey, key.toString()); - else + const QString id = cmd->id().toString(); + const QString settingsKey = QLatin1String(kKeyboardSettingsKeyV2) + '/' + id; + const QString compatSettingsKey = QLatin1String(kKeyboardSettingsKey) + '/' + id; + const QList<QKeySequence> keys = cmd->keySequences(); + const QList<QKeySequence> defaultKeys = cmd->defaultKeySequences(); + if (keys != defaultKeys) { + if (keys.isEmpty()) { + ICore::settings()->setValue(settingsKey, QString()); + ICore::settings()->setValue(compatSettingsKey, QString()); + } else if (keys.size() == 1) { + ICore::settings()->setValue(settingsKey, keys.first().toString()); + ICore::settings()->setValue(compatSettingsKey, keys.first().toString()); + } else { + ICore::settings()->setValue(settingsKey, + Utils::transform<QStringList>(keys, + [](const QKeySequence &k) { + return k.toString(); + })); + } + } else { ICore::settings()->remove(settingsKey); + } } void ActionManagerPrivate::saveSettings() diff --git a/src/plugins/coreplugin/actionmanager/command.cpp b/src/plugins/coreplugin/actionmanager/command.cpp index cd801c1ec2..7109c15bd9 100644 --- a/src/plugins/coreplugin/actionmanager/command.cpp +++ b/src/plugins/coreplugin/actionmanager/command.cpp @@ -253,13 +253,20 @@ Id Action::id() const void Action::setDefaultKeySequence(const QKeySequence &key) { if (!m_isKeyInitialized) - setKeySequence(key); - m_defaultKey = key; + setKeySequences({key}); + m_defaultKeys = {key}; } -QKeySequence Action::defaultKeySequence() const +void Action::setDefaultKeySequences(const QList<QKeySequence> &keys) { - return m_defaultKey; + if (!m_isKeyInitialized) + setKeySequences(keys); + m_defaultKeys = keys; +} + +QList<QKeySequence> Action::defaultKeySequences() const +{ + return m_defaultKeys; } QAction *Action::action() const @@ -277,13 +284,18 @@ Context Action::context() const return m_context; } -void Action::setKeySequence(const QKeySequence &key) +void Action::setKeySequences(const QList<QKeySequence> &keys) { m_isKeyInitialized = true; - m_action->setShortcut(key); + m_action->setShortcuts(keys); emit keySequenceChanged(); } +QList<QKeySequence> Action::keySequences() const +{ + return m_action->shortcuts(); +} + QKeySequence Action::keySequence() const { return m_action->shortcut(); diff --git a/src/plugins/coreplugin/actionmanager/command.h b/src/plugins/coreplugin/actionmanager/command.h index 355507de12..d17ef0d266 100644 --- a/src/plugins/coreplugin/actionmanager/command.h +++ b/src/plugins/coreplugin/actionmanager/command.h @@ -58,7 +58,9 @@ public: Q_DECLARE_FLAGS(CommandAttributes, CommandAttribute) virtual void setDefaultKeySequence(const QKeySequence &key) = 0; - virtual QKeySequence defaultKeySequence() const = 0; + virtual void setDefaultKeySequences(const QList<QKeySequence> &keys) = 0; + virtual QList<QKeySequence> defaultKeySequences() const = 0; + virtual QList<QKeySequence> keySequences() const = 0; virtual QKeySequence keySequence() const = 0; // explicitly set the description (used e.g. in shortcut settings) // default is to use the action text for actions, or the whatsThis for shortcuts, @@ -78,7 +80,7 @@ public: virtual bool isActive() const = 0; - virtual void setKeySequence(const QKeySequence &key) = 0; + virtual void setKeySequences(const QList<QKeySequence> &keys) = 0; virtual QString stringWithAppendedShortcut(const QString &str) const = 0; void augmentActionWithShortcutToolTip(QAction *action) const; static QToolButton *toolButtonWithAppendedShortcut(QAction *action, Command *cmd); diff --git a/src/plugins/coreplugin/actionmanager/command_p.h b/src/plugins/coreplugin/actionmanager/command_p.h index 9811c88fb6..de722d41cf 100644 --- a/src/plugins/coreplugin/actionmanager/command_p.h +++ b/src/plugins/coreplugin/actionmanager/command_p.h @@ -52,9 +52,11 @@ public: Id id() const override; void setDefaultKeySequence(const QKeySequence &key) override; - QKeySequence defaultKeySequence() const override; + void setDefaultKeySequences(const QList<QKeySequence> &key) override; + QList<QKeySequence> defaultKeySequences() const override; - void setKeySequence(const QKeySequence &key) override; + void setKeySequences(const QList<QKeySequence> &keys) override; + QList<QKeySequence> keySequences() const override; QKeySequence keySequence() const override; void setDescription(const QString &text) override; @@ -92,7 +94,7 @@ private: Context m_context; CommandAttributes m_attributes; Id m_id; - QKeySequence m_defaultKey; + QList<QKeySequence> m_defaultKeys; QString m_defaultText; QString m_touchBarText; QIcon m_touchBarIcon; diff --git a/src/plugins/coreplugin/actionmanager/commandsfile.cpp b/src/plugins/coreplugin/actionmanager/commandsfile.cpp index faeed00e07..8b03fee9e5 100644 --- a/src/plugins/coreplugin/actionmanager/commandsfile.cpp +++ b/src/plugins/coreplugin/actionmanager/commandsfile.cpp @@ -83,9 +83,9 @@ CommandsFile::CommandsFile(const QString &filename) /*! \internal */ -QMap<QString, QKeySequence> CommandsFile::importCommands() const +QMap<QString, QList<QKeySequence>> CommandsFile::importCommands() const { - QMap<QString, QKeySequence> result; + QMap<QString, QList<QKeySequence>> result; QFile file(m_filename); if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) @@ -101,19 +101,17 @@ QMap<QString, QKeySequence> CommandsFile::importCommands() const case QXmlStreamReader::StartElement: { const QStringRef name = r.name(); if (name == ctx.shortCutElement) { - if (!currentId.isEmpty()) // shortcut element without key element == empty shortcut - result.insert(currentId, QKeySequence()); currentId = r.attributes().value(ctx.idAttribute).toString(); + if (!result.contains(currentId)) + result.insert(currentId, {}); } else if (name == ctx.keyElement) { - QTC_ASSERT(!currentId.isEmpty(), return result); + QTC_ASSERT(!currentId.isEmpty(), continue); const QXmlStreamAttributes attributes = r.attributes(); if (attributes.hasAttribute(ctx.valueAttribute)) { const QString keyString = attributes.value(ctx.valueAttribute).toString(); - result.insert(currentId, QKeySequence(keyString)); - } else { - result.insert(currentId, QKeySequence()); + QList<QKeySequence> keys = result.value(currentId); + result.insert(currentId, keys << QKeySequence(keyString)); } - currentId.clear(); } // if key element } // case QXmlStreamReader::StartElement default: @@ -144,14 +142,16 @@ bool CommandsFile::exportCommands(const QList<ShortcutItem *> &items) w.writeStartElement(ctx.mappingElement); foreach (const ShortcutItem *item, items) { const Id id = item->m_cmd->id(); - if (item->m_key.isEmpty()) { + if (item->m_keys.isEmpty() || item->m_keys.first().isEmpty()) { w.writeEmptyElement(ctx.shortCutElement); w.writeAttribute(ctx.idAttribute, id.toString()); } else { w.writeStartElement(ctx.shortCutElement); w.writeAttribute(ctx.idAttribute, id.toString()); - w.writeEmptyElement(ctx.keyElement); - w.writeAttribute(ctx.valueAttribute, item->m_key.toString()); + for (const QKeySequence &k : item->m_keys) { + w.writeEmptyElement(ctx.keyElement); + w.writeAttribute(ctx.valueAttribute, k.toString()); + } w.writeEndElement(); // Shortcut } } diff --git a/src/plugins/coreplugin/actionmanager/commandsfile.h b/src/plugins/coreplugin/actionmanager/commandsfile.h index 891856383f..cd4bceeeeb 100644 --- a/src/plugins/coreplugin/actionmanager/commandsfile.h +++ b/src/plugins/coreplugin/actionmanager/commandsfile.h @@ -43,7 +43,7 @@ class CommandsFile : public QObject public: CommandsFile(const QString &filename); - QMap<QString, QKeySequence> importCommands() const; + QMap<QString, QList<QKeySequence> > importCommands() const; bool exportCommands(const QList<ShortcutItem *> &items); private: diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h index fd81737957..d34886632f 100644 --- a/src/plugins/coreplugin/coreconstants.h +++ b/src/plugins/coreplugin/coreconstants.h @@ -49,12 +49,13 @@ const char M_FILE[] = "QtCreator.Menu.File"; const char M_FILE_RECENTFILES[] = "QtCreator.Menu.File.RecentFiles"; const char M_EDIT[] = "QtCreator.Menu.Edit"; const char M_EDIT_ADVANCED[] = "QtCreator.Menu.Edit.Advanced"; +const char M_VIEW[] = "QtCreator.Menu.View"; +const char M_VIEW_MODESTYLES[] = "QtCreator.Menu.View.ModeStyles"; +const char M_VIEW_VIEWS[] = "QtCreator.Menu.View.Views"; +const char M_VIEW_PANES[] = "QtCreator.Menu.View.Panes"; const char M_TOOLS[] = "QtCreator.Menu.Tools"; const char M_TOOLS_EXTERNAL[] = "QtCreator.Menu.Tools.External"; const char M_WINDOW[] = "QtCreator.Menu.Window"; -const char M_WINDOW_PANES[] = "QtCreator.Menu.Window.Panes"; -const char M_WINDOW_MODESTYLES[] = "QtCreator.Menu.Window.ModeStyles"; -const char M_WINDOW_VIEWS[] = "QtCreator.Menu.Window.Views"; const char M_HELP[] = "QtCreator.Menu.Help"; // Contexts @@ -174,12 +175,15 @@ const char G_EDIT_BLOCKS[] = "QtCreator.Group.Edit.Blocks"; const char G_EDIT_FONT[] = "QtCreator.Group.Edit.Font"; const char G_EDIT_EDITOR[] = "QtCreator.Group.Edit.Editor"; +// View menu groups +const char G_VIEW_VIEWS[] = "QtCreator.Group.View.Views"; +const char G_VIEW_PANES[] = "QtCreator.Group.View.Panes"; + +// Tools menu groups const char G_TOOLS_OPTIONS[] = "QtCreator.Group.Tools.Options"; // Window menu groups const char G_WINDOW_SIZE[] = "QtCreator.Group.Window.Size"; -const char G_WINDOW_PANES[] = "QtCreator.Group.Window.Panes"; -const char G_WINDOW_VIEWS[] = "QtCreator.Group.Window.Views"; const char G_WINDOW_SPLIT[] = "QtCreator.Group.Window.Split"; const char G_WINDOW_NAVIGATE[] = "QtCreator.Group.Window.Navigate"; const char G_WINDOW_LIST[] = "QtCreator.Group.Window.List"; diff --git a/src/plugins/coreplugin/coreplugin.qbs b/src/plugins/coreplugin/coreplugin.qbs index 8afe2f0aa8..dc54a0a4df 100644 --- a/src/plugins/coreplugin/coreplugin.qbs +++ b/src/plugins/coreplugin/coreplugin.qbs @@ -1,5 +1,6 @@ import qbs 1.0 import qbs.FileInfo +import qbs.Utilities Project { name: "Core" @@ -17,15 +18,13 @@ Project { condition: qbs.targetOS.contains("windows") } - Depends { name: "Qt.script"; required: false } - Depends { name: "Utils" } Depends { name: "Aggregation" } Depends { name: "app_version_header" } Properties { - condition: Qt.script.present + condition: Utilities.versionCompare(Qt.qml.version, "5.14.0") >= 0 cpp.defines: base.concat("WITH_JAVASCRIPTFILTER") } @@ -379,7 +378,7 @@ Project { Group { name: "Locator Javascript Filter" - condition: Qt.script.present + condition: Utilities.versionCompare(Qt.qml.version, "5.14.0") >= 0 prefix: "locator/" files: [ "javascriptfilter.cpp", diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp index f75c215bf1..bf83d112d6 100644 --- a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp +++ b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp @@ -33,6 +33,7 @@ #include <coreplugin/actionmanager/command_p.h> #include <coreplugin/actionmanager/commandsfile.h> +#include <utils/algorithm.h> #include <utils/fancylineedit.h> #include <utils/hostosinfo.h> #include <utils/qtcassert.h> @@ -50,6 +51,8 @@ Q_DECLARE_METATYPE(Core::Internal::ShortcutItem*) +const char kSeparator[] = " | "; + static int translateModifiers(Qt::KeyboardModifiers state, const QString &text) { @@ -82,9 +85,23 @@ static QString keySequenceToEditString(const QKeySequence &sequence) return text; } +static QString keySequencesToEditString(const QList<QKeySequence> &sequence) +{ + return Utils::transform(sequence, keySequenceToEditString).join(kSeparator); +} + +static QString keySequencesToNativeString(const QList<QKeySequence> &sequence) +{ + return Utils::transform(sequence, + [](const QKeySequence &k) { + return k.toString(QKeySequence::NativeText); + }) + .join(kSeparator); +} + static QKeySequence keySequenceFromEditString(const QString &editString) { - QString text = editString; + QString text = editString.trimmed(); if (Utils::HostOsInfo::isMacHost()) { // adapt the modifier names text.replace(QLatin1String("Opt"), QLatin1String("Alt"), Qt::CaseInsensitive); @@ -94,6 +111,21 @@ static QKeySequence keySequenceFromEditString(const QString &editString) return QKeySequence::fromString(text, QKeySequence::PortableText); } +struct ParsedKey +{ + QString text; + QKeySequence key; +}; + +static QList<ParsedKey> keySequencesFromEditString(const QString &editString) +{ + if (editString.trimmed().isEmpty()) + return {}; + return Utils::transform(editString.split(kSeparator), [](const QString &str) { + return ParsedKey{str, keySequenceFromEditString(str)}; + }); +} + static bool keySequenceIsValid(const QKeySequence &sequence) { if (sequence.isEmpty()) @@ -242,7 +274,7 @@ private: void resetToDefault(); bool validateShortcutEdit() const; bool markCollisions(ShortcutItem *); - void setKeySequence(const QKeySequence &key); + void setKeySequences(const QList<QKeySequence> &keys); void showConflicts(); void clear(); @@ -292,8 +324,10 @@ ShortcutSettingsWidget::ShortcutSettingsWidget() "enter \"Ctrl+Shift+Escape,A\".") + QLatin1String("</body></html>")); auto shortcutButton = new ShortcutButton(m_shortcutBox); - connect(shortcutButton, &ShortcutButton::keySequenceChanged, - this, &ShortcutSettingsWidget::setKeySequence); + connect(shortcutButton, + &ShortcutButton::keySequenceChanged, + this, + [this](const QKeySequence &k) { setKeySequences({k}); }); auto resetButton = new QPushButton(tr("Reset"), m_shortcutBox); resetButton->setToolTip(tr("Reset to default.")); connect(resetButton, &QPushButton::clicked, @@ -343,7 +377,7 @@ QWidget *ShortcutSettings::widget() void ShortcutSettingsWidget::apply() { foreach (ShortcutItem *item, m_scitems) - item->m_cmd->setKeySequence(item->m_key); + item->m_cmd->setKeySequences(item->m_keys); } void ShortcutSettings::apply() @@ -372,12 +406,32 @@ void ShortcutSettingsWidget::handleCurrentCommandChanged(QTreeWidgetItem *curren m_warningLabel->clear(); m_shortcutBox->setEnabled(false); } else { - setKeySequence(scitem->m_key); + setKeySequences(scitem->m_keys); markCollisions(scitem); m_shortcutBox->setEnabled(true); } } +static bool checkValidity(const QList<ParsedKey> &keys, QString *warningMessage) +{ + QTC_ASSERT(warningMessage, return true); + for (const ParsedKey &k : keys) { + if (!keySequenceIsValid(k.key)) { + *warningMessage = ShortcutSettingsWidget::tr("Invalid key sequence \"%1\".").arg(k.text); + return false; + } + } + for (const ParsedKey &k : keys) { + if (textKeySequence(k.key)) { + *warningMessage = ShortcutSettingsWidget::tr( + "Key sequence \"%1\" will not work in editor.") + .arg(k.text); + break; + } + } + return true; +} + bool ShortcutSettingsWidget::validateShortcutEdit() const { m_warningLabel->clear(); @@ -385,43 +439,57 @@ bool ShortcutSettingsWidget::validateShortcutEdit() const ShortcutItem *item = shortcutItem(current); if (!item) return true; - bool valid = false; const QString text = m_shortcutEdit->text().trimmed(); - const QKeySequence currentKey = keySequenceFromEditString(text); + const QList<ParsedKey> currentKeys = keySequencesFromEditString(text); + QString warningMessage; + bool isValid = checkValidity(currentKeys, &warningMessage); - if (keySequenceIsValid(currentKey) || text.isEmpty()) { - item->m_key = currentKey; + if (isValid) { + item->m_keys = Utils::transform(currentKeys, &ParsedKey::key); auto that = const_cast<ShortcutSettingsWidget *>(this); - if (item->m_cmd->defaultKeySequence() != item->m_key) + if (item->m_keys != item->m_cmd->defaultKeySequences()) that->setModified(current, true); else that->setModified(current, false); - current->setText(2, item->m_key.toString(QKeySequence::NativeText)); - valid = !that->markCollisions(item); - if (!valid) { + current->setText(2, keySequencesToNativeString(item->m_keys)); + isValid = !that->markCollisions(item); + if (!isValid) { m_warningLabel->setText( tr("Key sequence has potential conflicts. <a href=\"#conflicts\">Show.</a>")); - } else if (textKeySequence(currentKey)) { - m_warningLabel->setText(tr("Key sequence will not work in editor.")); } - } else { - m_warningLabel->setText(m_warningLabel->text() + tr("Invalid key sequence.")); } - return valid; + if (!warningMessage.isEmpty()) { + if (m_warningLabel->text().isEmpty()) + m_warningLabel->setText(warningMessage); + else + m_warningLabel->setText(m_warningLabel->text() + " " + warningMessage); + } + return isValid; } bool ShortcutSettingsWidget::filterColumn(const QString &filterString, QTreeWidgetItem *item, int column) const { - QString text; - ShortcutItem *scitem = shortcutItem(item); + const ShortcutItem *scitem = shortcutItem(item); if (column == item->columnCount() - 1) { // shortcut // filter on the shortcut edit text if (!scitem) return true; - text = keySequenceToEditString(scitem->m_key); - } else if (column == 0 && scitem) { // command id + const QStringList filters = Utils::transform(filterString.split(kSeparator), + [](const QString &s) { return s.trimmed(); }); + for (const QKeySequence &k : scitem->m_keys) { + const QString &keyString = keySequenceToEditString(k); + const bool found = Utils::anyOf(filters, [keyString](const QString &f) { + return keyString.contains(f, Qt::CaseInsensitive); + }); + if (found) + return false; + } + return true; + } + QString text; + if (column == 0 && scitem) { // command id text = scitem->m_cmd->id().toString(); } else { text = item->text(column); @@ -429,9 +497,9 @@ bool ShortcutSettingsWidget::filterColumn(const QString &filterString, QTreeWidg return !text.contains(filterString, Qt::CaseInsensitive); } -void ShortcutSettingsWidget::setKeySequence(const QKeySequence &key) +void ShortcutSettingsWidget::setKeySequences(const QList<QKeySequence> &keys) { - m_shortcutEdit->setText(keySequenceToEditString(key)); + m_shortcutEdit->setText(keySequencesToEditString(keys)); } void ShortcutSettingsWidget::showConflicts() @@ -439,7 +507,7 @@ void ShortcutSettingsWidget::showConflicts() QTreeWidgetItem *current = commandList()->currentItem(); ShortcutItem *scitem = shortcutItem(current); if (scitem) - setFilterText(keySequenceToEditString(scitem->m_key)); + setFilterText(keySequencesToEditString(scitem->m_keys)); } void ShortcutSettingsWidget::resetToDefault() @@ -447,7 +515,7 @@ void ShortcutSettingsWidget::resetToDefault() QTreeWidgetItem *current = commandList()->currentItem(); ShortcutItem *scitem = shortcutItem(current); if (scitem) { - setKeySequence(scitem->m_cmd->defaultKeySequence()); + setKeySequences(scitem->m_cmd->defaultKeySequences()); foreach (ShortcutItem *item, m_scitems) markCollisions(item); } @@ -461,17 +529,16 @@ void ShortcutSettingsWidget::importAction() if (!fileName.isEmpty()) { CommandsFile cf(fileName); - QMap<QString, QKeySequence> mapping = cf.importCommands(); - - foreach (ShortcutItem *item, m_scitems) { + QMap<QString, QList<QKeySequence>> mapping = cf.importCommands(); + for (ShortcutItem *item : qAsConst(m_scitems)) { QString sid = item->m_cmd->id().toString(); if (mapping.contains(sid)) { - item->m_key = mapping.value(sid); - item->m_item->setText(2, item->m_key.toString(QKeySequence::NativeText)); + item->m_keys = mapping.value(sid); + item->m_item->setText(2, keySequencesToNativeString(item->m_keys)); if (item->m_item == commandList()->currentItem()) emit currentCommandChanged(item->m_item); - if (item->m_cmd->defaultKeySequence() != item->m_key) + if (item->m_keys != item->m_cmd->defaultKeySequences()) setModified(item->m_item, true); else setModified(item->m_item, false); @@ -486,8 +553,8 @@ void ShortcutSettingsWidget::importAction() void ShortcutSettingsWidget::defaultAction() { foreach (ShortcutItem *item, m_scitems) { - item->m_key = item->m_cmd->defaultKeySequence(); - item->m_item->setText(2, item->m_key.toString(QKeySequence::NativeText)); + item->m_keys = item->m_cmd->defaultKeySequences(); + item->m_item->setText(2, keySequencesToNativeString(item->m_keys)); setModified(item->m_item, false); if (item->m_item == commandList()->currentItem()) emit currentCommandChanged(item->m_item); @@ -551,11 +618,11 @@ void ShortcutSettingsWidget::initialize() } sections[section]->addChild(item); - s->m_key = c->keySequence(); + s->m_keys = c->keySequences(); item->setText(0, subId); item->setText(1, c->description()); - item->setText(2, s->m_key.toString(QKeySequence::NativeText)); - if (s->m_cmd->defaultKeySequence() != s->m_key) + item->setText(2, keySequencesToNativeString(s->m_keys)); + if (s->m_keys != s->m_cmd->defaultKeySequences()) setModified(item, true); item->setData(0, Qt::UserRole, QVariant::fromValue(s)); @@ -568,35 +635,42 @@ void ShortcutSettingsWidget::initialize() bool ShortcutSettingsWidget::markCollisions(ShortcutItem *item) { bool hasCollision = false; - if (!item->m_key.isEmpty()) { + if (!item->m_keys.isEmpty()) { Id globalId(Constants::C_GLOBAL); const Context itemContext = item->m_cmd->context(); const bool itemHasGlobalContext = itemContext.contains(globalId); - foreach (ShortcutItem *currentItem, m_scitems) { - if (currentItem->m_key.isEmpty() || item == currentItem - || item->m_key != currentItem->m_key) + for (ShortcutItem *currentItem : qAsConst(m_scitems)) { + if (item == currentItem) + continue; + const bool containsSameShortcut = Utils::anyOf(currentItem->m_keys, + [item](const QKeySequence &k) { + return item->m_keys.contains(k); + }); + if (!containsSameShortcut) continue; + // check if contexts might conflict const Context currentContext = currentItem->m_cmd->context(); bool currentIsConflicting = (itemHasGlobalContext && !currentContext.isEmpty()); if (!currentIsConflicting) { - foreach (const Id &id, currentContext) { - if ((id == globalId && !itemContext.isEmpty()) - || itemContext.contains(id)) { + for (const Id &id : currentContext) { + if ((id == globalId && !itemContext.isEmpty()) || itemContext.contains(id)) { currentIsConflicting = true; break; } } } if (currentIsConflicting) { - currentItem->m_item->setForeground( - 2, Utils::creatorTheme()->color(Utils::Theme::TextColorError)); + currentItem->m_item->setForeground(2, + Utils::creatorTheme()->color( + Utils::Theme::TextColorError)); hasCollision = true; } } } - item->m_item->setForeground(2, hasCollision - ? Utils::creatorTheme()->color(Utils::Theme::TextColorError) - : commandList()->palette().windowText()); + item->m_item->setForeground(2, + hasCollision + ? Utils::creatorTheme()->color(Utils::Theme::TextColorError) + : commandList()->palette().windowText()); return hasCollision; } diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.h b/src/plugins/coreplugin/dialogs/shortcutsettings.h index a49d45a615..14d56ae8f0 100644 --- a/src/plugins/coreplugin/dialogs/shortcutsettings.h +++ b/src/plugins/coreplugin/dialogs/shortcutsettings.h @@ -51,7 +51,7 @@ class ShortcutSettingsWidget; struct ShortcutItem { Command *m_cmd; - QKeySequence m_key; + QList<QKeySequence> m_keys; QTreeWidgetItem *m_item; }; diff --git a/src/plugins/coreplugin/locator/javascriptfilter.cpp b/src/plugins/coreplugin/locator/javascriptfilter.cpp index ab6727b8a2..b1f7f7719f 100644 --- a/src/plugins/coreplugin/locator/javascriptfilter.cpp +++ b/src/plugins/coreplugin/locator/javascriptfilter.cpp @@ -27,7 +27,7 @@ #include <QClipboard> #include <QGuiApplication> -#include <QScriptEngine> +#include <QJSEngine> namespace Core { namespace Internal { @@ -48,8 +48,8 @@ JavaScriptFilter::JavaScriptFilter() m_abortTimer.setInterval(1000); connect(&m_abortTimer, &QTimer::timeout, this, [this] { m_aborted = true; - if (m_engine && m_engine->isEvaluating()) - m_engine->abortEvaluation(); + if (m_engine) + m_engine->setInterrupted(true); }); } @@ -63,6 +63,7 @@ void JavaScriptFilter::prepareSearch(const QString &entry) if (!m_engine) setupEngine(); + m_engine->setInterrupted(false); m_aborted = false; m_abortTimer.start(); } @@ -118,7 +119,7 @@ void JavaScriptFilter::refresh(QFutureInterface<void> &future) void JavaScriptFilter::setupEngine() { - m_engine.reset(new QScriptEngine); + m_engine.reset(new QJSEngine); m_engine->evaluate( "function abs(x) { return Math.abs(x); }\n" "function acos(x) { return Math.acos(x); }\n" diff --git a/src/plugins/coreplugin/locator/javascriptfilter.h b/src/plugins/coreplugin/locator/javascriptfilter.h index a11b9c0f21..28ef447604 100644 --- a/src/plugins/coreplugin/locator/javascriptfilter.h +++ b/src/plugins/coreplugin/locator/javascriptfilter.h @@ -32,7 +32,7 @@ #include <memory> QT_BEGIN_NAMESPACE -class QScriptEngine; +class QJSEngine; QT_END_NAMESPACE namespace Core { @@ -55,7 +55,7 @@ public: private: void setupEngine(); - mutable std::unique_ptr<QScriptEngine> m_engine; + mutable std::unique_ptr<QJSEngine> m_engine; QTimer m_abortTimer; bool m_aborted = false; }; diff --git a/src/plugins/coreplugin/locator/locator.pri b/src/plugins/coreplugin/locator/locator.pri index 2223836c19..ae5cf6e440 100644 --- a/src/plugins/coreplugin/locator/locator.pri +++ b/src/plugins/coreplugin/locator/locator.pri @@ -38,9 +38,7 @@ SOURCES += \ FORMS += \ $$PWD/urllocatorfilter.ui -qtHaveModule(script) { - QT *= script - +minQtVersion(5, 14, 0) { DEFINES += WITH_JAVASCRIPTFILTER HEADERS += \ diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp index ea2e8db147..a9a51d8b65 100644 --- a/src/plugins/coreplugin/mainwindow.cpp +++ b/src/plugins/coreplugin/mainwindow.cpp @@ -424,6 +424,12 @@ void MainWindow::registerDefaultContainers() medit->appendGroup(Constants::G_EDIT_FIND); medit->appendGroup(Constants::G_EDIT_OTHER); + ActionContainer *mview = ActionManager::createMenu(Constants::M_VIEW); + menubar->addMenu(mview, Constants::G_VIEW); + mview->menu()->setTitle(tr("&View")); + mview->appendGroup(Constants::G_VIEW_VIEWS); + mview->appendGroup(Constants::G_VIEW_PANES); + // Tools Menu ActionContainer *ac = ActionManager::createMenu(Constants::M_TOOLS); menubar->addMenu(ac, Constants::G_TOOLS); @@ -434,8 +440,6 @@ void MainWindow::registerDefaultContainers() menubar->addMenu(mwindow, Constants::G_WINDOW); mwindow->menu()->setTitle(tr("&Window")); mwindow->appendGroup(Constants::G_WINDOW_SIZE); - mwindow->appendGroup(Constants::G_WINDOW_VIEWS); - mwindow->appendGroup(Constants::G_WINDOW_PANES); mwindow->appendGroup(Constants::G_WINDOW_SPLIT); mwindow->appendGroup(Constants::G_WINDOW_NAVIGATE); mwindow->appendGroup(Constants::G_WINDOW_LIST); @@ -465,6 +469,7 @@ void MainWindow::registerDefaultActions() { ActionContainer *mfile = ActionManager::actionContainer(Constants::M_FILE); ActionContainer *medit = ActionManager::actionContainer(Constants::M_EDIT); + ActionContainer *mview = ActionManager::actionContainer(Constants::M_VIEW); ActionContainer *mtools = ActionManager::actionContainer(Constants::M_TOOLS); ActionContainer *mwindow = ActionManager::actionContainer(Constants::M_WINDOW); ActionContainer *mhelp = ActionManager::actionContainer(Constants::M_HELP); @@ -640,7 +645,10 @@ void MainWindow::registerDefaultActions() : Utils::Icons::ZOOMOUT_TOOLBAR.icon(); tmpaction = new QAction(icon, tr("Zoom Out"), this); cmd = ActionManager::registerAction(tmpaction, Constants::ZOOM_OUT); - cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+-"))); + if (useMacShortcuts) + cmd->setDefaultKeySequences({QKeySequence(tr("Ctrl+-")), QKeySequence(tr("Ctrl+Shift+-"))}); + else + cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+-"))); tmpaction->setEnabled(false); // Zoom Reset Action @@ -714,7 +722,7 @@ void MainWindow::registerDefaultActions() ProxyAction *toggleLeftSideBarProxyAction = ProxyAction::proxyActionWithIcon(cmd->action(), Utils::Icons::TOGGLE_LEFT_SIDEBAR_TOOLBAR.icon()); m_toggleLeftSideBarButton->setDefaultAction(toggleLeftSideBarProxyAction); - mwindow->addAction(cmd, Constants::G_WINDOW_VIEWS); + mview->addAction(cmd, Constants::G_VIEW_VIEWS); m_toggleLeftSideBarAction->setEnabled(false); // Show Right Sidebar Action @@ -730,14 +738,14 @@ void MainWindow::registerDefaultActions() ProxyAction *toggleRightSideBarProxyAction = ProxyAction::proxyActionWithIcon(cmd->action(), Utils::Icons::TOGGLE_RIGHT_SIDEBAR_TOOLBAR.icon()); m_toggleRightSideBarButton->setDefaultAction(toggleRightSideBarProxyAction); - mwindow->addAction(cmd, Constants::G_WINDOW_VIEWS); + mview->addAction(cmd, Constants::G_VIEW_VIEWS); m_toggleRightSideBarButton->setEnabled(false); registerModeSelectorStyleActions(); // Window->Views - ActionContainer *mviews = ActionManager::createMenu(Constants::M_WINDOW_VIEWS); - mwindow->addMenu(mviews, Constants::G_WINDOW_VIEWS); + ActionContainer *mviews = ActionManager::createMenu(Constants::M_VIEW_VIEWS); + mview->addMenu(mviews, Constants::G_VIEW_VIEWS); mviews->menu()->setTitle(tr("&Views")); // "Help" separators @@ -781,7 +789,7 @@ void MainWindow::registerDefaultActions() void MainWindow::registerModeSelectorStyleActions() { - ActionContainer *mwindow = ActionManager::actionContainer(Constants::M_WINDOW); + ActionContainer *mview = ActionManager::actionContainer(Constants::M_VIEW); // Cycle Mode Selector Styles m_cycleModeSelectorStyleAction = new QAction(tr("Cycle Mode Selector Styles"), this); @@ -792,8 +800,8 @@ void MainWindow::registerModeSelectorStyleActions() }); // Mode Selector Styles - ActionContainer *mmodeLayouts = ActionManager::createMenu(Constants::M_WINDOW_MODESTYLES); - mwindow->addMenu(mmodeLayouts, Constants::G_WINDOW_VIEWS); + ActionContainer *mmodeLayouts = ActionManager::createMenu(Constants::M_VIEW_MODESTYLES); + mview->addMenu(mmodeLayouts, Constants::G_VIEW_VIEWS); QMenu *styleMenu = mmodeLayouts->menu(); styleMenu->setTitle(tr("Mode Selector Style")); auto *stylesGroup = new QActionGroup(styleMenu); diff --git a/src/plugins/coreplugin/messageoutputwindow.cpp b/src/plugins/coreplugin/messageoutputwindow.cpp index 1ea565705b..384b34c113 100644 --- a/src/plugins/coreplugin/messageoutputwindow.cpp +++ b/src/plugins/coreplugin/messageoutputwindow.cpp @@ -111,7 +111,7 @@ void MessageOutputWindow::visibilityChanged(bool /*b*/) void MessageOutputWindow::append(const QString &text) { - m_widget->appendText(text); + m_widget->appendMessage(text, Utils::DebugFormat); } int MessageOutputWindow::priorityInStatusBar() const diff --git a/src/plugins/coreplugin/outputpanemanager.cpp b/src/plugins/coreplugin/outputpanemanager.cpp index 0d33610eb5..fccdd67e47 100644 --- a/src/plugins/coreplugin/outputpanemanager.cpp +++ b/src/plugins/coreplugin/outputpanemanager.cpp @@ -391,11 +391,11 @@ OutputPaneManager::OutputPaneManager(QWidget *parent) : StatusBarManager::addStatusBarWidget(m_buttonsWidget, StatusBarManager::Second); - ActionContainer *mwindow = ActionManager::actionContainer(Constants::M_WINDOW); + ActionContainer *mview = ActionManager::actionContainer(Constants::M_VIEW); // Window->Output Panes - ActionContainer *mpanes = ActionManager::createMenu(Constants::M_WINDOW_PANES); - mwindow->addMenu(mpanes, Constants::G_WINDOW_PANES); + ActionContainer *mpanes = ActionManager::createMenu(Constants::M_VIEW_PANES); + mview->addMenu(mpanes, Constants::G_VIEW_PANES); mpanes->menu()->setTitle(tr("Output &Panes")); mpanes->appendGroup("Coreplugin.OutputPane.ActionsGroup"); mpanes->appendGroup("Coreplugin.OutputPane.PanesGroup"); diff --git a/src/plugins/coreplugin/outputwindow.cpp b/src/plugins/coreplugin/outputwindow.cpp index 149c7189fd..fc61bcc750 100644 --- a/src/plugins/coreplugin/outputwindow.cpp +++ b/src/plugins/coreplugin/outputwindow.cpp @@ -30,7 +30,6 @@ #include "icore.h" #include <utils/outputformatter.h> -#include <utils/synchronousprocess.h> #include <QAction> #include <QCursor> @@ -63,9 +62,8 @@ public: IContext *outputWindowContext = nullptr; QPointer<Utils::OutputFormatter> formatter; QString settingsKey; + OutputFormatter defaultFormatter; - bool enforceNewline = false; - bool prependCarriageReturn = false; bool scrollToBottom = true; bool linksActive = true; bool zoomEnabled = false; @@ -93,6 +91,7 @@ OutputWindow::OutputWindow(Context context, const QString &settingsKey, QWidget setFrameShape(QFrame::NoFrame); setMouseTracking(true); setUndoRedoEnabled(false); + setFormatter(&d->defaultFormatter); d->settingsKey = settingsKey; @@ -169,8 +168,7 @@ void OutputWindow::mouseReleaseEvent(QMouseEvent *e) { if (d->linksActive && d->mouseButtonPressed == Qt::LeftButton) { const QString href = anchorAt(e->pos()); - if (d->formatter) - d->formatter->handleLink(href); + d->formatter->handleLink(href); } // Mouse was released, activate links again @@ -214,16 +212,13 @@ void OutputWindow::keyPressEvent(QKeyEvent *ev) verticalScrollBar()->triggerAction(QAbstractSlider::SliderToMaximum); } -OutputFormatter *OutputWindow::formatter() const -{ - return d->formatter; -} - void OutputWindow::setFormatter(OutputFormatter *formatter) { d->formatter = formatter; if (d->formatter) d->formatter->setPlainTextEdit(this); + else + d->formatter = &d->defaultFormatter; } void OutputWindow::showEvent(QShowEvent *e) @@ -364,23 +359,6 @@ void OutputWindow::filterNewContent() scrollToBottom(); } -QString OutputWindow::doNewlineEnforcement(const QString &out) -{ - d->scrollToBottom = true; - QString s = out; - if (d->enforceNewline) { - s.prepend('\n'); - d->enforceNewline = false; - } - - if (s.endsWith('\n')) { - d->enforceNewline = true; // make appendOutputInline put in a newline next time - s.chop(1); - } - - return s; -} - void OutputWindow::setMaxCharCount(int count) { d->maxCharCount = count; @@ -395,16 +373,6 @@ int OutputWindow::maxCharCount() const void OutputWindow::appendMessage(const QString &output, OutputFormat format) { QString out = output; - if (d->prependCarriageReturn) { - d->prependCarriageReturn = false; - out.prepend('\r'); - } - out = SynchronousProcess::normalizeNewlines(out); - if (out.endsWith('\r')) { - d->prependCarriageReturn = true; - out.chop(1); - } - if (out.size() > d->maxCharCount) { // Current line alone exceeds limit, we need to cut it. out.truncate(d->maxCharCount); @@ -427,48 +395,8 @@ void OutputWindow::appendMessage(const QString &output, OutputFormat format) } const bool atBottom = isScrollbarAtBottom() || m_scrollTimer.isActive(); - - if (format == ErrorMessageFormat || format == NormalMessageFormat) { - if (d->formatter) - d->formatter->appendMessage(doNewlineEnforcement(out), format); - } else { - - bool sameLine = format == StdOutFormatSameLine - || format == StdErrFormatSameLine; - - if (sameLine) { - d->scrollToBottom = true; - - bool enforceNewline = d->enforceNewline; - d->enforceNewline = false; - - if (enforceNewline) { - out.prepend('\n'); - } else { - const int newline = out.indexOf('\n'); - moveCursor(QTextCursor::End); - if (newline != -1) { - if (d->formatter) - d->formatter->appendMessage(out.left(newline), format);// doesn't enforce new paragraph like appendPlainText - out = out.mid(newline); - } - } - - if (out.isEmpty()) { - d->enforceNewline = true; - } else { - if (out.endsWith('\n')) { - d->enforceNewline = true; - out.chop(1); - } - if (d->formatter) - d->formatter->appendMessage(out, format); - } - } else { - if (d->formatter) - d->formatter->appendMessage(doNewlineEnforcement(out), format); - } - } + d->scrollToBottom = true; + d->formatter->appendMessage(out, format); if (atBottom) { if (m_lastMessage.elapsed() < 5) { @@ -483,31 +411,6 @@ void OutputWindow::appendMessage(const QString &output, OutputFormat format) enableUndoRedo(); } -// TODO rename -void OutputWindow::appendText(const QString &textIn, const QTextCharFormat &format) -{ - const QString text = SynchronousProcess::normalizeNewlines(textIn); - if (d->maxCharCount > 0 && document()->characterCount() >= d->maxCharCount) - return; - const bool atBottom = isScrollbarAtBottom(); - if (!d->cursor.atEnd()) - d->cursor.movePosition(QTextCursor::End); - d->cursor.beginEditBlock(); - d->cursor.insertText(doNewlineEnforcement(text), format); - - if (d->maxCharCount > 0 && document()->characterCount() >= d->maxCharCount) { - QTextCharFormat tmp; - tmp.setFontWeight(QFont::Bold); - d->cursor.insertText(doNewlineEnforcement(tr("Additional output omitted. You can increase " - "the limit in the \"Build & Run\" settings.") - + '\n'), tmp); - } - - d->cursor.endEditBlock(); - if (atBottom) - scrollToBottom(); -} - bool OutputWindow::isScrollbarAtBottom() const { return verticalScrollBar()->value() == verticalScrollBar()->maximum(); @@ -542,11 +445,7 @@ QMimeData *OutputWindow::createMimeDataFromSelection() const void OutputWindow::clear() { - d->enforceNewline = false; - d->prependCarriageReturn = false; - QPlainTextEdit::clear(); - if (d->formatter) - d->formatter->clear(); + d->formatter->clear(); } void OutputWindow::scrollToBottom() diff --git a/src/plugins/coreplugin/outputwindow.h b/src/plugins/coreplugin/outputwindow.h index 509ae6dfab..a90e9ced66 100644 --- a/src/plugins/coreplugin/outputwindow.h +++ b/src/plugins/coreplugin/outputwindow.h @@ -56,12 +56,9 @@ public: OutputWindow(Context context, const QString &settingsKey, QWidget *parent = nullptr); ~OutputWindow() override; - Utils::OutputFormatter *formatter() const; void setFormatter(Utils::OutputFormatter *formatter); void appendMessage(const QString &out, Utils::OutputFormat format); - /// appends a \p text using \p format without using formater - void appendText(const QString &text, const QTextCharFormat &format = QTextCharFormat()); void grayOutOldContent(); void clear(); @@ -106,7 +103,6 @@ private: QTimer m_scrollTimer; QElapsedTimer m_lastMessage; void enableUndoRedo(); - QString doNewlineEnforcement(const QString &out); void filterNewContent(); Internal::OutputWindowPrivate *d = nullptr; diff --git a/src/plugins/cppcheck/cppcheckplugin.cpp b/src/plugins/cppcheck/cppcheckplugin.cpp index 0bcbc952da..4bbab6a4de 100644 --- a/src/plugins/cppcheck/cppcheckplugin.cpp +++ b/src/plugins/cppcheck/cppcheckplugin.cpp @@ -147,7 +147,7 @@ void CppcheckPluginPrivate::updateManualRunAction() const Target *target = SessionManager::startupTarget(); const Core::Id cxx = ProjectExplorer::Constants::CXX_LANGUAGE_ID; const bool canRun = target && project->projectLanguages().contains(cxx) - && ToolChainKitAspect::toolChain(target->kit(), cxx); + && ToolChainKitAspect::cxxToolChain(target->kit()); manualRunAction->setEnabled(canRun); } diff --git a/src/plugins/cppeditor/CMakeLists.txt b/src/plugins/cppeditor/CMakeLists.txt index d2072fa5ba..d2a55ca8cf 100644 --- a/src/plugins/cppeditor/CMakeLists.txt +++ b/src/plugins/cppeditor/CMakeLists.txt @@ -43,5 +43,4 @@ extend_qtc_plugin(CppEditor followsymbol_switchmethoddecldef_test.cpp EXPLICIT_MOC cppdoxygen_test.h - cppquickfix_test.h ) diff --git a/src/plugins/cpptools/cpptoolsjsextension.cpp b/src/plugins/cpptools/cpptoolsjsextension.cpp index 4c283fc644..03a0d3df99 100644 --- a/src/plugins/cpptools/cpptoolsjsextension.cpp +++ b/src/plugins/cpptools/cpptoolsjsextension.cpp @@ -29,10 +29,15 @@ #include <coreplugin/icore.h> +#include <projectexplorer/project.h> +#include <projectexplorer/projectnodes.h> +#include <projectexplorer/session.h> + #include <utils/codegeneration.h> #include <utils/fileutils.h> #include <QFileInfo> +#include <QStringList> #include <QTextStream> namespace CppTools { @@ -113,5 +118,69 @@ QString CppToolsJsExtension::closeNamespaces(const QString &klass) const return result; } +QString CppToolsJsExtension::includeStatement( + const QString &fullyQualifiedClassName, + const QString &suffix, + const QString &specialClasses, + const QString &pathOfIncludingFile + ) +{ + if (fullyQualifiedClassName.isEmpty()) + return {}; + const QString className = parts(fullyQualifiedClassName).last(); + if (className.isEmpty() || specialClasses.contains(className)) + return {}; + if (className.startsWith('Q') && className.length() > 2 && className.at(1).isUpper()) + return "#include <" + className + ">\n"; + const auto withUnderScores = [&className] { + QString baseName = className; + baseName[0] = baseName[0].toLower(); + for (int i = 1; i < baseName.length(); ++i) { + if (baseName[i].isUpper()) { + baseName.insert(i, '_'); + baseName[i + 1] = baseName[i + 1].toLower(); + ++i; + } + } + return baseName; + }; + QStringList candidates{className + '.' + suffix}; + bool hasUpperCase = false; + bool hasLowerCase = false; + for (int i = 0; i < className.length() && (!hasUpperCase || !hasLowerCase); ++i) { + if (className.at(i).isUpper()) + hasUpperCase = true; + if (className.at(i).isLower()) + hasLowerCase = true; + } + if (hasUpperCase) + candidates << className.toLower() + '.' + suffix; + if (hasUpperCase && hasLowerCase) + candidates << withUnderScores() + '.' + suffix; + candidates.removeDuplicates(); + using namespace ProjectExplorer; + const auto nodeMatchesFileName = [&candidates](Node *n) { + if (const FileNode * const fileNode = n->asFileNode()) { + if (fileNode->fileType() == FileType::Header + && candidates.contains(fileNode->filePath().fileName())) { + return true; + } + } + return false; + }; + for (const Project * const p : SessionManager::projects()) { + const Node *theNode = p->rootProjectNode()->findNode(nodeMatchesFileName); + if (theNode) { + const bool sameDir = pathOfIncludingFile == theNode->filePath().toFileInfo().path(); + return QString("#include ") + .append(sameDir ? '"' : '<') + .append(theNode->filePath().fileName()) + .append(sameDir ? '"' : '>') + .append('\n'); + } + } + return {}; +} + } // namespace Internal } // namespace CppTools diff --git a/src/plugins/cpptools/cpptoolsjsextension.h b/src/plugins/cpptools/cpptoolsjsextension.h index b528191033..065e0ca8d5 100644 --- a/src/plugins/cpptools/cpptoolsjsextension.h +++ b/src/plugins/cpptools/cpptoolsjsextension.h @@ -55,6 +55,14 @@ public: Q_INVOKABLE QString classToHeaderGuard(const QString &klass, const QString &extension) const; Q_INVOKABLE QString openNamespaces(const QString &klass) const; Q_INVOKABLE QString closeNamespaces(const QString &klass) const; + + // Find header file for class. + Q_INVOKABLE QString includeStatement( + const QString &fullyQualifiedClassName, + const QString &suffix, + const QString &specialClasses, + const QString &pathOfIncludingFile + ); }; } // namespace Internal diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index ae840e772c..930f63bf4f 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -1509,7 +1509,7 @@ bool BreakHandler::setData(const QModelIndex &idx, const QVariant &value, int ro return contextMenuEvent(ev); if (auto kev = ev.as<QKeyEvent>(QEvent::KeyPress)) { - if (kev->key() == Qt::Key_Delete) { + if (kev->key() == Qt::Key_Delete || kev->key() == Qt::Key_Backspace) { QModelIndexList si = ev.currentOrSelectedRows(); const Breakpoints bps = findBreakpointsByIndex(si); for (Breakpoint bp : bps) { @@ -2547,7 +2547,7 @@ bool BreakpointManager::setData(const QModelIndex &idx, const QVariant &value, i return contextMenuEvent(ev); if (auto kev = ev.as<QKeyEvent>(QEvent::KeyPress)) { - if (kev->key() == Qt::Key_Delete) { + if (kev->key() == Qt::Key_Delete || kev->key() == Qt::Key_Backspace) { QModelIndexList si = ev.currentOrSelectedRows(); const GlobalBreakpoints gbps = findBreakpointsByIndex(si); for (GlobalBreakpoint gbp : gbps) diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index a1c2aad6ab..4f3984d4c4 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -1756,11 +1756,11 @@ void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) c case AppOutput: case AppStuff: d->m_logWindow->showOutput(channel, msg); - emit appendMessageRequested(msg, StdOutFormatSameLine, false); + emit appendMessageRequested(msg, StdOutFormat, false); break; case AppError: d->m_logWindow->showOutput(channel, msg); - emit appendMessageRequested(msg, StdErrFormatSameLine, false); + emit appendMessageRequested(msg, StdErrFormat, false); break; default: d->m_logWindow->showOutput(channel, msg); diff --git a/src/plugins/debugger/debuggermainwindow.cpp b/src/plugins/debugger/debuggermainwindow.cpp index bdba4afb86..e4d88ca38a 100644 --- a/src/plugins/debugger/debuggermainwindow.cpp +++ b/src/plugins/debugger/debuggermainwindow.cpp @@ -253,7 +253,7 @@ DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *parent) q->addDockWidget(Qt::BottomDockWidgetArea, m_toolBarDock); connect(viewButton, &QAbstractButton::clicked, this, [this, viewButton] { - ActionContainer *viewsMenu = ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS); + ActionContainer *viewsMenu = ActionManager::actionContainer(Core::Constants::M_VIEW_VIEWS); viewsMenu->menu()->exec(viewButton->mapToGlobal(QPoint())); }); @@ -279,7 +279,7 @@ DebuggerMainWindow::DebuggerMainWindow() Context debugcontext(Debugger::Constants::C_DEBUGMODE); - ActionContainer *viewsMenu = ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS); + ActionContainer *viewsMenu = ActionManager::actionContainer(Core::Constants::M_VIEW_VIEWS); Command *cmd = ActionManager::registerAction(showCentralWidgetAction(), "Debugger.Views.ShowCentralWidget", debugcontext); cmd->setAttribute(Command::CA_Hide); @@ -312,7 +312,7 @@ DebuggerMainWindow::~DebuggerMainWindow() void DebuggerMainWindow::contextMenuEvent(QContextMenuEvent *ev) { - ActionContainer *viewsMenu = ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS); + ActionContainer *viewsMenu = ActionManager::actionContainer(Core::Constants::M_VIEW_VIEWS); viewsMenu->menu()->exec(ev->globalPos()); } @@ -893,7 +893,7 @@ void Perspective::addWindow(QWidget *widget, Command *cmd = ActionManager::registerAction(op.toggleViewAction, op.commandId, d->context()); cmd->setAttribute(Command::CA_Hide); - ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS)->addAction(cmd); + ActionManager::actionContainer(Core::Constants::M_VIEW_VIEWS)->addAction(cmd); } d->m_dockOperations.append(op); diff --git a/src/plugins/debugger/debuggerrunconfigurationaspect.cpp b/src/plugins/debugger/debuggerrunconfigurationaspect.cpp index 06cec3a92d..9317594fd9 100644 --- a/src/plugins/debugger/debuggerrunconfigurationaspect.cpp +++ b/src/plugins/debugger/debuggerrunconfigurationaspect.cpp @@ -27,17 +27,18 @@ #include "debuggerconstants.h" +#include <coreplugin/helpmanager.h> #include <coreplugin/icontext.h> #include <coreplugin/icore.h> -#include <coreplugin/helpmanager.h> +#include <projectexplorer/buildconfiguration.h> +#include <projectexplorer/buildstep.h> +#include <projectexplorer/buildsteplist.h> #include <projectexplorer/kitinformation.h> #include <projectexplorer/project.h> #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/runconfiguration.h> #include <projectexplorer/target.h> -#include <projectexplorer/buildconfiguration.h> -#include <projectexplorer/buildstep.h> -#include <projectexplorer/buildsteplist.h> +#include <qtsupport/qtbuildaspects.h> #include <QCheckBox> #include <QDebug> @@ -242,12 +243,9 @@ bool DebuggerRunConfigurationAspect::useQmlDebugger() const // // Try to find a build configuration to check whether qml debugging is enabled there - // (Using the Qt metatype system to avoid a hard build system dependency) - // if (BuildConfiguration *bc = m_target->activeBuildConfiguration()) { - const QVariant linkProperty = bc->property("linkQmlDebuggingLibrary"); - if (linkProperty.isValid() && linkProperty.canConvert(QVariant::Bool)) - return linkProperty.toBool(); + const auto aspect = bc->aspect<QtSupport::QmlDebuggingAspect>(); + return aspect && aspect->setting() == TriState::Enabled; } return !languages.contains(ProjectExplorer::Constants::CXX_LANGUAGE_ID); diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index c6cf2ec248..fadb50acbc 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -128,14 +128,14 @@ public: { const QByteArray ba = m_proc.readAllStandardOutput(); const QString msg = QString::fromLocal8Bit(ba, ba.length()); - m_runTool->appendMessage(msg, StdOutFormatSameLine); + m_runTool->appendMessage(msg, StdOutFormat); } void handleStandardError() { const QByteArray ba = m_proc.readAllStandardError(); const QString msg = QString::fromLocal8Bit(ba, ba.length()); - m_runTool->appendMessage(msg, StdErrFormatSameLine); + m_runTool->appendMessage(msg, StdErrFormat); } void handleFinished() @@ -1025,10 +1025,10 @@ void DebuggerRunTool::showMessage(const QString &msg, int channel, int timeout) m_engine->showMessage(msg, channel, timeout); switch (channel) { case AppOutput: - appendMessage(msg, StdOutFormatSameLine); + appendMessage(msg, StdOutFormat); break; case AppError: - appendMessage(msg, StdErrFormatSameLine); + appendMessage(msg, StdErrFormat); break; case AppStuff: appendMessage(msg, DebugFormat); diff --git a/src/plugins/debugger/enginemanager.cpp b/src/plugins/debugger/enginemanager.cpp index 8c2bbca146..1770758b11 100644 --- a/src/plugins/debugger/enginemanager.cpp +++ b/src/plugins/debugger/enginemanager.cpp @@ -310,7 +310,7 @@ bool EngineItem::setData(int row, const QVariant &value, int role) } if (auto kev = ev.as<QKeyEvent>(QEvent::KeyPress)) { - if (kev->key() == Qt::Key_Delete && m_engine) { + if ((kev->key() == Qt::Key_Delete || kev->key() == Qt::Key_Backspace) && m_engine) { m_engine->quitDebugger(); } else if (kev->key() == Qt::Key_Return || kev->key() == Qt::Key_Enter) { d->activateEngineByIndex(row); diff --git a/src/plugins/debugger/uvsc/uvscclient.cpp b/src/plugins/debugger/uvsc/uvscclient.cpp index 57de522689..b0feca3c77 100644 --- a/src/plugins/debugger/uvsc/uvscclient.cpp +++ b/src/plugins/debugger/uvsc/uvscclient.cpp @@ -691,6 +691,41 @@ bool UvscClient::inspectWatcher(const QStringList &expandedWatcherINames, return true; } +bool UvscClient::fetchMemory(quint64 address, QByteArray &data) +{ + if (data.isEmpty()) + data.resize(sizeof(quint8)); + + QByteArray amem = UvscUtils::encodeAmem(address, data); + const auto amemPtr = reinterpret_cast<AMEM *>(amem.data()); + const UVSC_STATUS st = ::UVSC_DBG_MEM_READ(m_descriptor, amemPtr, amem.size()); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + + data = QByteArray(reinterpret_cast<char *>(&amemPtr->bytes), + amemPtr->bytesCount); + return true; +} + +bool UvscClient::changeMemory(quint64 address, const QByteArray &data) +{ + if (data.isEmpty()) { + setError(RuntimeError); + return false; + } + + QByteArray amem = UvscUtils::encodeAmem(address, data); + const auto amemPtr = reinterpret_cast<AMEM *>(amem.data()); + const UVSC_STATUS st = ::UVSC_DBG_MEM_WRITE(m_descriptor, amemPtr, amem.size()); + if (st != UVSC_STATUS_SUCCESS) { + setError(RuntimeError); + return false; + } + return true; +} + bool UvscClient::disassemblyAddress(quint64 address, QByteArray &result) { if (!checkConnection()) diff --git a/src/plugins/debugger/uvsc/uvscclient.h b/src/plugins/debugger/uvsc/uvscclient.h index a602622a2b..a1fed71309 100644 --- a/src/plugins/debugger/uvsc/uvscclient.h +++ b/src/plugins/debugger/uvsc/uvscclient.h @@ -87,6 +87,9 @@ public: bool fetchWatchers(const QStringList &expandedWatcherINames, const std::vector<std::pair<QString, QString>> &rootWatchers, GdbMi &data); + bool fetchMemory(quint64 address, QByteArray &data); + bool changeMemory(quint64 address, const QByteArray &data); + bool disassemblyAddress(quint64 address, QByteArray &result); bool setRegisterValue(int index, const QString &value); diff --git a/src/plugins/debugger/uvsc/uvscengine.cpp b/src/plugins/debugger/uvsc/uvscengine.cpp index ba28a449af..351c527986 100644 --- a/src/plugins/debugger/uvsc/uvscengine.cpp +++ b/src/plugins/debugger/uvsc/uvscengine.cpp @@ -32,6 +32,7 @@ #include <debugger/disassemblerlines.h> #include <debugger/memoryagent.h> #include <debugger/moduleshandler.h> +#include <debugger/peripheralregisterhandler.h> #include <debugger/registerhandler.h> #include <debugger/stackhandler.h> #include <debugger/threadshandler.h> @@ -162,6 +163,9 @@ void UvscEngine::setupEngine() if (!configureProject(rp)) return; + + // Reload peripheral register description. + peripheralRegisterHandler()->updateRegisterGroups(); } void UvscEngine::runEngine() @@ -231,6 +235,14 @@ void UvscEngine::setRegisterValue(const QString &name, const QString &value) reloadRegisters(); } +void UvscEngine::setPeripheralRegisterValue(quint64 address, quint64 value) +{ + const QByteArray data = UvscUtils::encodeU32(value); + if (!m_client->changeMemory(address, data)) + return; + reloadPeripheralRegisters(); +} + void UvscEngine::executeStepOver(bool byInstruction) { notifyInferiorRunRequested(); @@ -332,6 +344,7 @@ void UvscEngine::activateFrame(int index) gotoCurrentLocation(); updateLocals(); reloadRegisters(); + reloadPeripheralRegisters(); } bool UvscEngine::stateAcceptsBreakpointChanges() const @@ -469,6 +482,17 @@ void UvscEngine::reloadRegisters() handleReloadRegisters(); } +void UvscEngine::reloadPeripheralRegisters() +{ + if (!isPeripheralRegistersWindowVisible()) + return; + + const QList<quint64> addresses = peripheralRegisterHandler()->activeRegisters(); + if (addresses.isEmpty()) + return; // Nothing to update. + handleReloadPeripheralRegisters(addresses); +} + void UvscEngine::reloadFullStack() { resetLocation(); @@ -496,6 +520,7 @@ void UvscEngine::updateAll() handleThreadInfo(); reloadRegisters(); + reloadPeripheralRegisters(); updateLocals(); } @@ -653,6 +678,7 @@ void UvscEngine::handleReloadStack(bool isFull) if (!m_client->fetchStackFrames(taskId, m_address, data)) { m_address = 0; reloadRegisters(); + reloadPeripheralRegisters(); return; } @@ -678,6 +704,19 @@ void UvscEngine::handleReloadRegisters() } } +void UvscEngine::handleReloadPeripheralRegisters(const QList<quint64> &addresses) +{ + for (const quint64 address : addresses) { + QByteArray data = UvscUtils::encodeU32(0); + if (!m_client->fetchMemory(address, data)) { + showMessage(tr("UVSC: Fetching peripheral register failed"), LogMisc); + } else { + const quint32 value = UvscUtils::decodeU32(data); + peripheralRegisterHandler()->updateRegister(address, value); + } + } +} + void UvscEngine::handleUpdateLocals(bool partial) { m_inUpdateLocals = false; diff --git a/src/plugins/debugger/uvsc/uvscengine.h b/src/plugins/debugger/uvsc/uvscengine.h index 97f843f44c..ace70fd5c5 100644 --- a/src/plugins/debugger/uvsc/uvscengine.h +++ b/src/plugins/debugger/uvsc/uvscengine.h @@ -49,6 +49,7 @@ public: bool hasCapability(unsigned cap) const final; void setRegisterValue(const QString &name, const QString &value) final; + void setPeripheralRegisterValue(quint64 address, quint64 value) final; void executeStepOver(bool byInstruction) final; void executeStepIn(bool byInstruction) final; @@ -72,6 +73,8 @@ public: void fetchDisassembler(DisassemblerAgent *agent) final; void reloadRegisters() final; + void reloadPeripheralRegisters() final; + void reloadFullStack() final; private slots: @@ -84,6 +87,7 @@ private slots: void handleThreadInfo(); void handleReloadStack(bool isFull); void handleReloadRegisters(); + void handleReloadPeripheralRegisters(const QList<quint64> &addresses); void handleUpdateLocals(bool partial); void handleInsertBreakpoint(const QString &exp, const Breakpoint &bp); void handleRemoveBreakpoint(const Breakpoint &bp); diff --git a/src/plugins/debugger/uvsc/uvscutils.cpp b/src/plugins/debugger/uvsc/uvscutils.cpp index e3b7e8799a..d7fb4d22ef 100644 --- a/src/plugins/debugger/uvsc/uvscutils.cpp +++ b/src/plugins/debugger/uvsc/uvscutils.cpp @@ -110,6 +110,16 @@ QByteArray encodeAmem(quint64 address, quint32 bytesCount) return buffer; } +QByteArray encodeAmem(quint64 address, const QByteArray &data) +{ + QByteArray buffer(sizeof(AMEM) - 1, 0); + buffer.append(data); + const auto amem = reinterpret_cast<AMEM *>(buffer.data()); + amem->address = address; + amem->bytesCount = data.size(); + return buffer; +} + TVAL encodeVoidTval() { TVAL tval = {}; @@ -238,6 +248,24 @@ QString adjustHexValue(QString hex, const QString &type) return {}; } +QByteArray encodeU32(quint32 value) +{ + QByteArray data; + QDataStream out(&data, QIODevice::WriteOnly); + out.setByteOrder(QDataStream::LittleEndian); + out << value; + return data; +} + +quint32 decodeU32(const QByteArray &data) +{ + QDataStream in(data); + in.setByteOrder(QDataStream::LittleEndian); + quint32 value = 0; + in >> value; + return value; +} + QString buildLocalId(const VARINFO &varinfo) { return QString::number(varinfo.id); diff --git a/src/plugins/debugger/uvsc/uvscutils.h b/src/plugins/debugger/uvsc/uvscutils.h index 6295912839..b51ac017a5 100644 --- a/src/plugins/debugger/uvsc/uvscutils.h +++ b/src/plugins/debugger/uvsc/uvscutils.h @@ -56,6 +56,7 @@ QString decodeAscii(const qint8 *ascii); QByteArray encodeProjectData(const QStringList &someNames); QByteArray encodeBreakPoint(BKTYPE type, const QString &exp, const QString &cmd = QString()); QByteArray encodeAmem(quint64 address, quint32 bytesCount); +QByteArray encodeAmem(quint64 address, const QByteArray &data); TVAL encodeVoidTval(); TVAL encodeIntTval(int value); TVAL encodeU64Tval(quint64 value); @@ -65,6 +66,9 @@ VSET encodeU64Vset(quint64 index, const QString &value); bool isKnownRegister(int type); QString adjustHexValue(QString hex, const QString &type); +QByteArray encodeU32(quint32 value); +quint32 decodeU32(const QByteArray &data); + QString buildLocalId(const VARINFO &varinfo); QString buildLocalEditable(const VARINFO &varinfo); QString buildLocalNumchild(const VARINFO &varinfo); diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 066f9be23b..9aac88f9e3 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -1108,7 +1108,8 @@ bool WatchModel::setData(const QModelIndex &idx, const QVariant &value, int role } if (auto kev = ev.as<QKeyEvent>(QEvent::KeyPress)) { - if (item && kev->key() == Qt::Key_Delete && item->isWatcher()) { + if (item && (kev->key() == Qt::Key_Delete || kev->key() == Qt::Key_Backspace) + && item->isWatcher()) { foreach (const QModelIndex &idx, ev.selectedRows()) removeWatchItem(itemForIndex(idx)); return true; diff --git a/src/plugins/designer/formeditorw.cpp b/src/plugins/designer/formeditorw.cpp index d7df1c8e85..ad5cb8c97b 100644 --- a/src/plugins/designer/formeditorw.cpp +++ b/src/plugins/designer/formeditorw.cpp @@ -313,7 +313,7 @@ void FormEditorData::addDockViewAction(ActionContainer *viewMenu, void FormEditorData::setupViewActions() { // Populate "View" menu of form editor menu - ActionContainer *viewMenu = ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS); + ActionContainer *viewMenu = ActionManager::actionContainer(Core::Constants::M_VIEW_VIEWS); QTC_ASSERT(viewMenu, return); addDockViewAction(viewMenu, WidgetBoxSubWindow, m_contexts, diff --git a/src/plugins/genericprojectmanager/genericmakestep.cpp b/src/plugins/genericprojectmanager/genericmakestep.cpp index e66a938ab3..f987ac6586 100644 --- a/src/plugins/genericprojectmanager/genericmakestep.cpp +++ b/src/plugins/genericprojectmanager/genericmakestep.cpp @@ -34,6 +34,12 @@ using namespace ProjectExplorer; namespace GenericProjectManager { namespace Internal { +class GenericMakeStep : public ProjectExplorer::MakeStep +{ +public: + explicit GenericMakeStep(BuildStepList *parent, Core::Id id); +}; + GenericMakeStep::GenericMakeStep(BuildStepList *parent, Core::Id id) : MakeStep(parent, id) { diff --git a/src/plugins/genericprojectmanager/genericmakestep.h b/src/plugins/genericprojectmanager/genericmakestep.h index 5e83216f49..85d312646d 100644 --- a/src/plugins/genericprojectmanager/genericmakestep.h +++ b/src/plugins/genericprojectmanager/genericmakestep.h @@ -27,20 +27,10 @@ #include <projectexplorer/makestep.h> -QT_FORWARD_DECLARE_CLASS(QListWidgetItem); - namespace GenericProjectManager { namespace Internal { -class GenericMakeStep : public ProjectExplorer::MakeStep -{ - Q_OBJECT - -public: - explicit GenericMakeStep(ProjectExplorer::BuildStepList *parent, Core::Id id); -}; - -class GenericMakeStepFactory : public ProjectExplorer::BuildStepFactory +class GenericMakeStepFactory final : public ProjectExplorer::BuildStepFactory { public: GenericMakeStepFactory(); diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp index e5f735f711..3289564e25 100644 --- a/src/plugins/genericprojectmanager/genericproject.cpp +++ b/src/plugins/genericprojectmanager/genericproject.cpp @@ -173,8 +173,6 @@ private: CppTools::CppProjectUpdaterInterface *m_cppCodeModelUpdater = nullptr; Utils::FileSystemWatcher m_deployFileWatcher; - - ParseGuard m_guard; }; @@ -263,7 +261,6 @@ GenericBuildSystem::~GenericBuildSystem() void GenericBuildSystem::triggerParsing() { - m_guard = guardParsingRun(); refresh(Everything); } diff --git a/src/plugins/help/docsettingspage.cpp b/src/plugins/help/docsettingspage.cpp index 86cf3b6515..66fba5f211 100644 --- a/src/plugins/help/docsettingspage.cpp +++ b/src/plugins/help/docsettingspage.cpp @@ -291,6 +291,7 @@ bool DocSettingsPageWidget::eventFilter(QObject *object, QEvent *event) if (event->type() == QEvent::KeyPress) { auto ke = static_cast<const QKeyEvent*>(event); switch (ke->key()) { + case Qt::Key_Backspace: case Qt::Key_Delete: removeDocumentation(currentSelection()); break; diff --git a/src/plugins/ios/iosbuildstep.cpp b/src/plugins/ios/iosbuildstep.cpp index c881e62267..fbf500b099 100644 --- a/src/plugins/ios/iosbuildstep.cpp +++ b/src/plugins/ios/iosbuildstep.cpp @@ -38,6 +38,7 @@ #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/toolchain.h> #include <projectexplorer/gcctoolchain.h> +#include <projectexplorer/abstractprocessstep.h> #include <qtsupport/qtkitinformation.h> #include <qtsupport/qtparser.h> @@ -61,18 +62,41 @@ namespace Ios { namespace Internal { const char IOS_BUILD_STEP_ID[] = "Ios.IosBuildStep"; -const char IOS_BUILD_STEP_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("Ios::Internal::IosBuildStep", - "xcodebuild"); - const char BUILD_USE_DEFAULT_ARGS_KEY[] = "Ios.IosBuildStep.XcodeArgumentsUseDefault"; const char BUILD_ARGUMENTS_KEY[] = "Ios.IosBuildStep.XcodeArguments"; const char CLEAN_KEY[] = "Ios.IosBuildStep.Clean"; +class IosBuildStep final : public AbstractProcessStep +{ + Q_DECLARE_TR_FUNCTIONS(Ios::Internal::IosBuildStep) + +public: + IosBuildStep(BuildStepList *parent, Core::Id id); + + BuildStepConfigWidget *createConfigWidget() final; + void setBaseArguments(const QStringList &args); + void setExtraArguments(const QStringList &extraArgs); + QStringList baseArguments() const; + QStringList allArguments() const; + QStringList defaultArguments() const; + Utils::FilePath buildCommand() const; + + bool init() final; + void doRun() final; + bool fromMap(const QVariantMap &map) final; + QVariantMap toMap() const final; + + QStringList m_baseBuildArguments; + QStringList m_extraArguments; + bool m_useDefaultArguments = true; + bool m_clean = false; +}; + // // IosBuildStepConfigWidget // -class IosBuildStepConfigWidget : public ProjectExplorer::BuildStepConfigWidget +class IosBuildStepConfigWidget final : public BuildStepConfigWidget { public: IosBuildStepConfigWidget(IosBuildStep *buildStep) @@ -145,12 +169,10 @@ private: void updateDetails() { - BuildConfiguration *bc = m_buildStep->buildConfiguration(); - ProcessParameters param; - param.setMacroExpander(bc->macroExpander()); - param.setWorkingDirectory(bc->buildDirectory()); - param.setEnvironment(bc->environment()); + param.setMacroExpander(m_buildStep->macroExpander()); + param.setWorkingDirectory(m_buildStep->buildDirectory()); + param.setEnvironment(m_buildStep->buildEnvironment()); param.setCommandLine({m_buildStep->buildCommand(), m_buildStep->allArguments()}); setSummaryText(param.summary(displayName())); @@ -166,8 +188,8 @@ private: IosBuildStep::IosBuildStep(BuildStepList *parent, Id id) : AbstractProcessStep(parent, id) { - setDefaultDisplayName(QCoreApplication::translate("GenericProjectManager::Internal::IosBuildStep", - IOS_BUILD_STEP_DISPLAY_NAME)); + setDefaultDisplayName(tr("xcodebuild")); + if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_CLEAN) { m_clean = true; setExtraArguments(QStringList("clean")); @@ -177,10 +199,8 @@ IosBuildStep::IosBuildStep(BuildStepList *parent, Id id) bool IosBuildStep::init() { BuildConfiguration *bc = buildConfiguration(); - if (!bc) - emit addTask(Task::buildConfigurationMissingTask()); - ToolChain *tc = ToolChainKitAspect::toolChain(target()->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID); + ToolChain *tc = ToolChainKitAspect::cxxToolChain(target()->kit()); if (!tc) emit addTask(Task::compilerMissingTask()); @@ -240,7 +260,7 @@ QStringList IosBuildStep::defaultArguments() const { QStringList res; Kit *kit = target()->kit(); - ToolChain *tc = ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID); + ToolChain *tc = ToolChainKitAspect::cxxToolChain(kit); switch (buildConfiguration()->buildType()) { case BuildConfiguration::Debug : res << "-configuration" << "Debug"; @@ -252,8 +272,7 @@ QStringList IosBuildStep::defaultArguments() const case BuildConfiguration::Unknown : break; default: - qCWarning(iosLog) << "IosBuildStep had an unknown buildType " - << buildConfiguration()->buildType(); + qCWarning(iosLog) << "IosBuildStep had an unknown buildType " << buildType(); } if (tc->typeId() == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID || tc->typeId() == ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID) { @@ -262,7 +281,7 @@ QStringList IosBuildStep::defaultArguments() const } if (!SysRootKitAspect::sysRoot(kit).isEmpty()) res << "-sdk" << SysRootKitAspect::sysRoot(kit).toString(); - res << "SYMROOT=" + buildConfiguration()->buildDirectory().toString(); + res << "SYMROOT=" + buildDirectory().toString(); return res; } @@ -310,8 +329,7 @@ IosBuildStepFactory::IosBuildStepFactory() Constants::IOS_SIMULATOR_TYPE}); setSupportedStepLists({ProjectExplorer::Constants::BUILDSTEPS_CLEAN, ProjectExplorer::Constants::BUILDSTEPS_BUILD}); - setDisplayName(QCoreApplication::translate("GenericProjectManager::Internal::IosBuildStep", - IOS_BUILD_STEP_DISPLAY_NAME)); + setDisplayName(IosBuildStep::tr("xcodebuild")); } } // namespace Internal diff --git a/src/plugins/ios/iosbuildstep.h b/src/plugins/ios/iosbuildstep.h index 3f6145202c..3a27b20960 100644 --- a/src/plugins/ios/iosbuildstep.h +++ b/src/plugins/ios/iosbuildstep.h @@ -25,49 +25,12 @@ #pragma once -#include <projectexplorer/abstractprocessstep.h> - -QT_BEGIN_NAMESPACE -class QListWidgetItem; -QT_END_NAMESPACE +#include <projectexplorer/buildstep.h> namespace Ios { namespace Internal { -class IosBuildStepConfigWidget; -class IosBuildStepFactory; - -class IosBuildStep : public ProjectExplorer::AbstractProcessStep -{ - Q_OBJECT - - friend class IosBuildStepConfigWidget; - friend class IosBuildStepFactory; - -public: - IosBuildStep(ProjectExplorer::BuildStepList *parent, Core::Id id); - - ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override; - void setBaseArguments(const QStringList &args); - void setExtraArguments(const QStringList &extraArgs); - QStringList baseArguments() const; - QStringList allArguments() const; - QStringList defaultArguments() const; - Utils::FilePath buildCommand() const; - -private: - bool init() override; - void doRun() override; - bool fromMap(const QVariantMap &map) override; - QVariantMap toMap() const override; - - QStringList m_baseBuildArguments; - QStringList m_extraArguments; - bool m_useDefaultArguments = true; - bool m_clean = false; -}; - -class IosBuildStepFactory : public ProjectExplorer::BuildStepFactory +class IosBuildStepFactory final : public ProjectExplorer::BuildStepFactory { public: IosBuildStepFactory(); diff --git a/src/plugins/ios/iosconfigurations.cpp b/src/plugins/ios/iosconfigurations.cpp index 158805c53d..b90787ff63 100644 --- a/src/plugins/ios/iosconfigurations.cpp +++ b/src/plugins/ios/iosconfigurations.cpp @@ -288,8 +288,8 @@ void IosConfigurations::updateAutomaticKitList() // we do not compare the sdk (thus automatically upgrading it in place if a // new Xcode is used). Change? return DeviceTypeKitAspect::deviceTypeId(kit) == pDeviceType - && ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID) == platformToolchains.second - && ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::C_LANGUAGE_ID) == platformToolchains.first + && ToolChainKitAspect::cxxToolChain(kit) == platformToolchains.second + && ToolChainKitAspect::cToolChain(kit) == platformToolchains.first && QtKitAspect::qtVersion(kit) == qtVersion; }); QTC_ASSERT(!resultingKits.contains(kit), continue); diff --git a/src/plugins/ios/iosconfigurations.h b/src/plugins/ios/iosconfigurations.h index cddf0a5806..d041ac3f21 100644 --- a/src/plugins/ios/iosconfigurations.h +++ b/src/plugins/ios/iosconfigurations.h @@ -95,8 +95,6 @@ using DevelopmentTeams = QList<DevelopmentTeamPtr>; class IosToolChainFactory : public ProjectExplorer::ToolChainFactory { - Q_OBJECT - public: IosToolChainFactory(); diff --git a/src/plugins/ios/iosdeploystep.cpp b/src/plugins/ios/iosdeploystep.cpp index 329fab7bfd..7bd5a87944 100644 --- a/src/plugins/ios/iosdeploystep.cpp +++ b/src/plugins/ios/iosdeploystep.cpp @@ -24,13 +24,15 @@ ****************************************************************************/ #include "iosdeploystep.h" + #include "iosbuildstep.h" +#include "iosconfigurations.h" #include "iosconstants.h" +#include "iosdevice.h" #include "iosrunconfiguration.h" +#include "iossimulator.h" #include "iostoolhandler.h" -#include <coreplugin/messagemanager.h> - #include <projectexplorer/buildconfiguration.h> #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/target.h> @@ -39,22 +41,64 @@ #include <projectexplorer/kitinformation.h> #include <projectexplorer/devicesupport/devicemanager.h> -#include <qtsupport/qtkitinformation.h> - #include <utils/temporaryfile.h> #include <QDir> #include <QFile> #include <QSettings> -#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(State, state, m_state) - using namespace ProjectExplorer; using namespace Utils; namespace Ios { namespace Internal { +class IosDeployStep final : public BuildStep +{ + Q_DECLARE_TR_FUNCTIONS(Ios::Internal::IosDeployStep) + +public: + enum TransferStatus { + NoTransfer, + TransferInProgress, + TransferOk, + TransferFailed + }; + + IosDeployStep(BuildStepList *bc, Core::Id id); + +private: + void cleanup(); + + void doRun() final; + void doCancel() final; + + void handleIsTransferringApp(IosToolHandler *handler, const QString &bundlePath, + const QString &deviceId, int progress, int maxProgress, + const QString &info); + void handleDidTransferApp(IosToolHandler *handler, const QString &bundlePath, const QString &deviceId, + IosToolHandler::OpStatus status); + void handleFinished(IosToolHandler *handler); + void handleErrorMsg(IosToolHandler *handler, const QString &msg); + void updateDisplayNames(); + + bool init() final; + BuildStepConfigWidget *createConfigWidget() final; + IDevice::ConstPtr device() const; + IosDevice::ConstPtr iosdevice() const; + IosSimulator::ConstPtr iossimulator() const; + + QString deviceId() const; + void checkProvisioningProfile(); + + TransferStatus m_transferStatus = NoTransfer; + IosToolHandler *m_toolHandler = nullptr; + IDevice::ConstPtr m_device; + FilePath m_bundlePath; + IosDeviceType m_deviceType; + bool m_expectFail = false; +}; + IosDeployStep::IosDeployStep(BuildStepList *parent, Core::Id id) : BuildStep(parent, id) { @@ -66,15 +110,9 @@ IosDeployStep::IosDeployStep(BuildStepList *parent, Core::Id id) this, &IosDeployStep::updateDisplayNames); } -Core::Id IosDeployStep::stepId() -{ - return "Qt4ProjectManager.IosDeployStep"; -} - void IosDeployStep::updateDisplayNames() { - IDevice::ConstPtr dev = - DeviceKitAspect::device(target()->kit()); + IDevice::ConstPtr dev = DeviceKitAspect::device(target()->kit()); const QString devName = dev.isNull() ? IosDevice::name() : dev->displayName(); setDefaultDisplayName(tr("Deploy to %1").arg(devName)); setDisplayName(tr("Deploy to %1").arg(devName)); @@ -95,7 +133,7 @@ bool IosDeployStep::init() m_deviceType = runConfig->deviceType(); } else { emit addOutput(tr("Error: no device available, deploy failed."), - BuildStep::OutputFormat::ErrorMessage); + OutputFormat::ErrorMessage); return false; } return true; @@ -104,7 +142,7 @@ bool IosDeployStep::init() void IosDeployStep::doRun() { QTC_CHECK(m_transferStatus == NoTransfer); - if (device().isNull()) { + if (m_device.isNull()) { TaskHub::addTask( DeploymentTask(Task::Error, tr("Deployment failed. No iOS device found."))); emit finished(!iossimulator().isNull()); @@ -190,7 +228,7 @@ void IosDeployStep::handleErrorMsg(IosToolHandler *handler, const QString &msg) if (msg.contains(QLatin1String("AMDeviceInstallApplication returned -402653103"))) TaskHub::addTask(DeploymentTask(Task::Warning, tr("The Info.plist might be incorrect."))); - emit addOutput(msg, BuildStep::OutputFormat::ErrorMessage); + emit addOutput(msg, OutputFormat::ErrorMessage); } BuildStepConfigWidget *IosDeployStep::createConfigWidget() @@ -236,7 +274,7 @@ void IosDeployStep::checkProvisioningProfile() return; end += 8; - Utils::TemporaryFile f("iosdeploy"); + TemporaryFile f("iosdeploy"); if (!f.open()) return; f.write(provisionData.mid(start, end - start)); @@ -245,9 +283,9 @@ void IosDeployStep::checkProvisioningProfile() if (!provisionPlist.contains(QLatin1String("ProvisionedDevices"))) return; - QStringList deviceIds = provisionPlist.value(QLatin1String("ProvisionedDevices")).toStringList(); - QString targetId = device->uniqueDeviceID(); - foreach (const QString &deviceId, deviceIds) { + const QStringList deviceIds = provisionPlist.value("ProvisionedDevices").toStringList(); + const QString targetId = device->uniqueDeviceID(); + for (const QString &deviceId : deviceIds) { if (deviceId == targetId) return; } @@ -263,11 +301,6 @@ void IosDeployStep::checkProvisioningProfile() emit addTask(task); } -IDevice::ConstPtr IosDeployStep::device() const -{ - return m_device; -} - IosDevice::ConstPtr IosDeployStep::iosdevice() const { return m_device.dynamicCast<const IosDevice>(); @@ -278,5 +311,21 @@ IosSimulator::ConstPtr IosDeployStep::iossimulator() const return m_device.dynamicCast<const IosSimulator>(); } +// IosDeployStepFactory + +IosDeployStepFactory::IosDeployStepFactory() +{ + registerStep<IosDeployStep>(stepId()); + setDisplayName(IosDeployStep::tr("Deploy to iOS device or emulator")); + setSupportedStepList(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY); + setSupportedDeviceTypes({Constants::IOS_DEVICE_TYPE, Constants::IOS_SIMULATOR_TYPE}); + setRepeatable(false); +} + +Core::Id IosDeployStepFactory::stepId() +{ + return "Qt4ProjectManager.IosDeployStep"; +} + } // namespace Internal } // namespace Ios diff --git a/src/plugins/ios/iosdeploystep.h b/src/plugins/ios/iosdeploystep.h index 909aae4f4d..bdd23a74f7 100644 --- a/src/plugins/ios/iosdeploystep.h +++ b/src/plugins/ios/iosdeploystep.h @@ -25,64 +25,17 @@ #pragma once -#include "iosconfigurations.h" -#include "iosdevice.h" -#include "iossimulator.h" - #include <projectexplorer/buildstep.h> -#include <projectexplorer/devicesupport/idevice.h> - -#include <QProcess> namespace Ios { -class IosToolHandler; namespace Internal { -class IosDeployStep : public ProjectExplorer::BuildStep +class IosDeployStepFactory final : public ProjectExplorer::BuildStepFactory { - Q_OBJECT public: - enum TransferStatus { - NoTransfer, - TransferInProgress, - TransferOk, - TransferFailed - }; + IosDeployStepFactory(); - friend class IosDeployStepFactory; - IosDeployStep(ProjectExplorer::BuildStepList *bc, Core::Id id); static Core::Id stepId(); - - void cleanup(); -private: - void doRun() override; - void doCancel() override; - - void handleIsTransferringApp(Ios::IosToolHandler *handler, const QString &bundlePath, - const QString &deviceId, int progress, int maxProgress, - const QString &info); - void handleDidTransferApp(Ios::IosToolHandler *handler, const QString &bundlePath, const QString &deviceId, - Ios::IosToolHandler::OpStatus status); - void handleFinished(Ios::IosToolHandler *handler); - void handleErrorMsg(Ios::IosToolHandler *handler, const QString &msg); - void updateDisplayNames(); - - bool init() override; - ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override; - ProjectExplorer::IDevice::ConstPtr device() const; - IosDevice::ConstPtr iosdevice() const; - IosSimulator::ConstPtr iossimulator() const; - - QString deviceId() const; - void checkProvisioningProfile(); - - TransferStatus m_transferStatus = NoTransfer; - IosToolHandler *m_toolHandler = nullptr; - ProjectExplorer::IDevice::ConstPtr m_device; - Utils::FilePath m_bundlePath; - IosDeviceType m_deviceType; - static const Core::Id Id; - bool m_expectFail = false; }; } // namespace Internal diff --git a/src/plugins/ios/iosdsymbuildstep.cpp b/src/plugins/ios/iosdsymbuildstep.cpp index a597f9b0d6..0221624201 100644 --- a/src/plugins/ios/iosdsymbuildstep.cpp +++ b/src/plugins/ios/iosdsymbuildstep.cpp @@ -67,12 +67,10 @@ IosDsymBuildStep::IosDsymBuildStep(BuildStepList *parent, Id id) : bool IosDsymBuildStep::init() { - BuildConfiguration *bc = buildConfiguration(); - ProcessParameters *pp = processParameters(); - pp->setMacroExpander(bc->macroExpander()); - pp->setWorkingDirectory(bc->buildDirectory()); - Utils::Environment env = bc->environment(); + pp->setMacroExpander(macroExpander()); + pp->setWorkingDirectory(buildDirectory()); + Utils::Environment env = buildEnvironment(); Utils::Environment::setupEnglishOutput(&env); pp->setEnvironment(env); pp->setCommandLine({command(), arguments()}); @@ -255,12 +253,10 @@ IosDsymBuildStepConfigWidget::~IosDsymBuildStepConfigWidget() void IosDsymBuildStepConfigWidget::updateDetails() { - BuildConfiguration *bc = m_buildStep->buildConfiguration(); - ProcessParameters param; - param.setMacroExpander(bc->macroExpander()); - param.setWorkingDirectory(bc->buildDirectory()); - param.setEnvironment(bc->environment()); + param.setMacroExpander(m_buildStep->macroExpander()); + param.setWorkingDirectory(m_buildStep->buildDirectory()); + param.setEnvironment(m_buildStep->buildEnvironment()); param.setCommandLine({m_buildStep->command(), m_buildStep->arguments()}); setSummaryText(param.summary(displayName())); diff --git a/src/plugins/ios/iosplugin.cpp b/src/plugins/ios/iosplugin.cpp index 50540c331f..a112364735 100644 --- a/src/plugins/ios/iosplugin.cpp +++ b/src/plugins/ios/iosplugin.cpp @@ -53,19 +53,6 @@ namespace Internal { Q_LOGGING_CATEGORY(iosLog, "qtc.ios.common", QtWarningMsg) -class IosDeployStepFactory : public BuildStepFactory -{ -public: - IosDeployStepFactory() - { - registerStep<IosDeployStep>(IosDeployStep::stepId()); - setDisplayName(IosDeployStep::tr("Deploy to iOS device or emulator")); - setSupportedStepList(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY); - setSupportedDeviceTypes({Constants::IOS_DEVICE_TYPE, Constants::IOS_SIMULATOR_TYPE}); - setRepeatable(false); - } -}; - class IosDeployConfigurationFactory : public DeployConfigurationFactory { public: @@ -76,7 +63,7 @@ public: addSupportedTargetDeviceType(Constants::IOS_DEVICE_TYPE); addSupportedTargetDeviceType(Constants::IOS_SIMULATOR_TYPE); setDefaultDisplayName(QCoreApplication::translate("Ios::Internal", "Deploy on iOS")); - addInitialStep(IosDeployStep::stepId()); + addInitialStep(IosDeployStepFactory::stepId()); } }; diff --git a/src/plugins/modeleditor/CMakeLists.txt b/src/plugins/modeleditor/CMakeLists.txt index 69ff243b5c..0e19bdb24f 100644 --- a/src/plugins/modeleditor/CMakeLists.txt +++ b/src/plugins/modeleditor/CMakeLists.txt @@ -32,5 +32,4 @@ add_qtc_plugin(ModelEditor EXPLICIT_MOC actionhandler.h modeleditor.h - modeleditorfactory.h ) diff --git a/src/plugins/nim/project/nimblebuildstep.cpp b/src/plugins/nim/project/nimblebuildstep.cpp index 43fb20da23..97014cc17a 100644 --- a/src/plugins/nim/project/nimblebuildstep.cpp +++ b/src/plugins/nim/project/nimblebuildstep.cpp @@ -111,8 +111,8 @@ bool NimbleBuildStep::init() setOutputParser(parser); ProcessParameters* params = processParameters(); - params->setEnvironment(buildConfiguration()->environment()); - params->setMacroExpander(buildConfiguration()->macroExpander()); + params->setEnvironment(buildEnvironment()); + params->setMacroExpander(macroExpander()); params->setWorkingDirectory(project()->projectDirectory()); params->setCommandLine({QStandardPaths::findExecutable("nimble"), {"build", m_arguments}}); return AbstractProcessStep::init(); @@ -156,13 +156,12 @@ QVariantMap NimbleBuildStep::toMap() const QString NimbleBuildStep::defaultArguments() const { - QTC_ASSERT(buildConfiguration(), return {}; ); - switch (buildConfiguration()->buildType()) { - case ProjectExplorer::BuildConfiguration::Debug: + switch (buildType()) { + case BuildConfiguration::Debug: return {"--debugger:native"}; - case ProjectExplorer::BuildConfiguration::Unknown: - case ProjectExplorer::BuildConfiguration::Profile: - case ProjectExplorer::BuildConfiguration::Release: + case BuildConfiguration::Unknown: + case BuildConfiguration::Profile: + case BuildConfiguration::Release: default: return {}; } diff --git a/src/plugins/nim/project/nimblebuildsystem.cpp b/src/plugins/nim/project/nimblebuildsystem.cpp index 537000e357..ecfec5d3b0 100644 --- a/src/plugins/nim/project/nimblebuildsystem.cpp +++ b/src/plugins/nim/project/nimblebuildsystem.cpp @@ -134,7 +134,12 @@ NimbleBuildSystem::NimbleBuildSystem(Target *target) void NimbleBuildSystem::triggerParsing() { - m_guard = guardParsingRun(); + // Only allow one parsing run at the same time: + auto guard = guardParsingRun(); + if (!guard.guardsProject()) + return; + m_guard = std::move(guard); + m_projectScanner.startScan(); } diff --git a/src/plugins/nim/project/nimbletaskstep.cpp b/src/plugins/nim/project/nimbletaskstep.cpp index 61cfb8f66e..f5f95160d3 100644 --- a/src/plugins/nim/project/nimbletaskstep.cpp +++ b/src/plugins/nim/project/nimbletaskstep.cpp @@ -31,6 +31,8 @@ #include <projectexplorer/buildstep.h> #include <projectexplorer/buildconfiguration.h> #include <projectexplorer/processparameters.h> +#include <projectexplorer/projectexplorerconstants.h> + #include <utils/fileutils.h> #include <QStandardPaths> @@ -47,7 +49,7 @@ NimbleTaskStep::NimbleTaskStep(BuildStepList *parentList, Core::Id id) bool NimbleTaskStep::init() { - processParameters()->setEnvironment(buildConfiguration()->environment()); + processParameters()->setEnvironment(buildEnvironment()); processParameters()->setWorkingDirectory(project()->projectDirectory()); return validate() && AbstractProcessStep::init(); } diff --git a/src/plugins/nim/project/nimbletaskstep.h b/src/plugins/nim/project/nimbletaskstep.h index f8e7d375d4..15e67885cd 100644 --- a/src/plugins/nim/project/nimbletaskstep.h +++ b/src/plugins/nim/project/nimbletaskstep.h @@ -25,7 +25,7 @@ #pragma once -#include <projectexplorer/processstep.h> +#include <projectexplorer/abstractprocessstep.h> namespace Nim { diff --git a/src/plugins/nim/project/nimcompilerbuildstep.cpp b/src/plugins/nim/project/nimcompilerbuildstep.cpp index 5159e45946..521c038afd 100644 --- a/src/plugins/nim/project/nimcompilerbuildstep.cpp +++ b/src/plugins/nim/project/nimcompilerbuildstep.cpp @@ -106,7 +106,7 @@ NimCompilerBuildStep::NimCompilerBuildStep(BuildStepList *parentList, Core::Id i this, &NimCompilerBuildStep::updateProcessParameters); connect(this, &NimCompilerBuildStep::outFilePathChanged, bc, &NimBuildConfiguration::outFilePathChanged); - connect(bc->target()->project(), &ProjectExplorer::Project::fileListChanged, + connect(project(), &ProjectExplorer::Project::fileListChanged, this, &NimCompilerBuildStep::updateTargetNimFile); updateProcessParameters(); } @@ -208,17 +208,13 @@ void NimCompilerBuildStep::updateProcessParameters() void NimCompilerBuildStep::updateOutFilePath() { - auto bc = qobject_cast<NimBuildConfiguration *>(buildConfiguration()); - QTC_ASSERT(bc, return); const QString targetName = Utils::HostOsInfo::withExecutableSuffix(m_targetNimFile.toFileInfo().baseName()); - setOutFilePath(bc->buildDirectory().pathAppended(targetName)); + setOutFilePath(buildDirectory().pathAppended(targetName)); } void NimCompilerBuildStep::updateWorkingDirectory() { - auto bc = qobject_cast<NimBuildConfiguration *>(buildConfiguration()); - QTC_ASSERT(bc, return); - processParameters()->setWorkingDirectory(bc->buildDirectory()); + processParameters()->setWorkingDirectory(buildDirectory()); } void NimCompilerBuildStep::updateCommand() @@ -257,9 +253,7 @@ void NimCompilerBuildStep::updateCommand() void NimCompilerBuildStep::updateEnvironment() { - auto bc = qobject_cast<NimBuildConfiguration *>(buildConfiguration()); - QTC_ASSERT(bc, return); - processParameters()->setEnvironment(bc->environment()); + processParameters()->setEnvironment(buildEnvironment()); } void NimCompilerBuildStep::updateTargetNimFile() diff --git a/src/plugins/nim/project/nimcompilercleanstep.cpp b/src/plugins/nim/project/nimcompilercleanstep.cpp index 570df83e58..3fce967a34 100644 --- a/src/plugins/nim/project/nimcompilercleanstep.cpp +++ b/src/plugins/nim/project/nimcompilercleanstep.cpp @@ -40,6 +40,24 @@ using namespace Utils; namespace Nim { +class NimCompilerCleanStep final : public BuildStep +{ + Q_DECLARE_TR_FUNCTIONS(Nim::NimCompilerCleanStep) + +public: + NimCompilerCleanStep(BuildStepList *parentList, Core::Id id); + +private: + bool init() final; + void doRun() final; + void doCancel() final {} // Can be left empty. The run() function hardly does anything. + + bool removeCacheDirectory(); + bool removeOutFilePath(); + + Utils::FilePath m_buildDir; +}; + NimCompilerCleanStep::NimCompilerCleanStep(BuildStepList *parentList, Core::Id id) : BuildStep(parentList, id) { @@ -51,14 +69,14 @@ NimCompilerCleanStep::NimCompilerCleanStep(BuildStepList *parentList, Core::Id i workingDirectory->setDisplayStyle(BaseStringAspect::LineEditDisplay); setSummaryUpdater([this, workingDirectory] { - workingDirectory->setFilePath(buildConfiguration()->buildDirectory()); + workingDirectory->setFilePath(buildDirectory()); return displayName(); }); } bool NimCompilerCleanStep::init() { - FilePath buildDir = buildConfiguration()->buildDirectory(); + FilePath buildDir = buildDirectory(); bool result = buildDir.exists(); if (result) m_buildDir = buildDir; @@ -68,32 +86,27 @@ bool NimCompilerCleanStep::init() void NimCompilerCleanStep::doRun() { if (!m_buildDir.exists()) { - emit addOutput(tr("Build directory \"%1\" does not exist.").arg(m_buildDir.toUserOutput()), BuildStep::OutputFormat::ErrorMessage); + emit addOutput(tr("Build directory \"%1\" does not exist.").arg(m_buildDir.toUserOutput()), OutputFormat::ErrorMessage); emit finished(false); return; } if (!removeCacheDirectory()) { - emit addOutput(tr("Failed to delete the cache directory."), BuildStep::OutputFormat::ErrorMessage); + emit addOutput(tr("Failed to delete the cache directory."), OutputFormat::ErrorMessage); emit finished(false); return; } if (!removeOutFilePath()) { - emit addOutput(tr("Failed to delete the out file."), BuildStep::OutputFormat::ErrorMessage); + emit addOutput(tr("Failed to delete the out file."), OutputFormat::ErrorMessage); emit finished(false); return; } - emit addOutput(tr("Clean step completed successfully."), BuildStep::OutputFormat::NormalMessage); + emit addOutput(tr("Clean step completed successfully."), OutputFormat::NormalMessage); emit finished(true); } -void NimCompilerCleanStep::doCancel() -{ - // Can be left empty. The run() function hardly does anything. -} - bool NimCompilerCleanStep::removeCacheDirectory() { auto bc = qobject_cast<NimBuildConfiguration*>(buildConfiguration()); diff --git a/src/plugins/nim/project/nimcompilercleanstep.h b/src/plugins/nim/project/nimcompilercleanstep.h index 483d627b9e..4086cf7275 100644 --- a/src/plugins/nim/project/nimcompilercleanstep.h +++ b/src/plugins/nim/project/nimcompilercleanstep.h @@ -26,30 +26,10 @@ #pragma once #include <projectexplorer/buildstep.h> -#include <projectexplorer/buildsteplist.h> -#include <utils/fileutils.h> namespace Nim { -class NimCompilerCleanStep : public ProjectExplorer::BuildStep -{ - Q_OBJECT - -public: - NimCompilerCleanStep(ProjectExplorer::BuildStepList *parentList, Core::Id id); - -private: - bool init() override; - void doRun() override; - void doCancel() override; - - bool removeCacheDirectory(); - bool removeOutFilePath(); - - Utils::FilePath m_buildDir; -}; - -class NimCompilerCleanStepFactory : public ProjectExplorer::BuildStepFactory +class NimCompilerCleanStepFactory final : public ProjectExplorer::BuildStepFactory { public: NimCompilerCleanStepFactory(); diff --git a/src/plugins/nim/project/nimtoolchain.cpp b/src/plugins/nim/project/nimtoolchain.cpp index 6a922f9553..031557c889 100644 --- a/src/plugins/nim/project/nimtoolchain.cpp +++ b/src/plugins/nim/project/nimtoolchain.cpp @@ -49,7 +49,7 @@ NimToolChain::NimToolChain(Core::Id typeId) , m_version(std::make_tuple(-1,-1,-1)) { setLanguage(Constants::C_NIMLANGUAGE_ID); - setTypeDisplayName(NimToolChainFactory::tr("Nim")); + setTypeDisplayName(tr("Nim")); } Abi NimToolChain::targetAbi() const diff --git a/src/plugins/nim/project/nimtoolchain.h b/src/plugins/nim/project/nimtoolchain.h index 84b449d11d..a140f1444f 100644 --- a/src/plugins/nim/project/nimtoolchain.h +++ b/src/plugins/nim/project/nimtoolchain.h @@ -32,6 +32,8 @@ namespace Nim { class NimToolChain : public ProjectExplorer::ToolChain { + Q_DECLARE_TR_FUNCTIONS(Nim::NimToolChain) + public: NimToolChain(); explicit NimToolChain(Core::Id typeId); diff --git a/src/plugins/nim/project/nimtoolchainfactory.cpp b/src/plugins/nim/project/nimtoolchainfactory.cpp index 7467ab7789..b79bad1969 100644 --- a/src/plugins/nim/project/nimtoolchainfactory.cpp +++ b/src/plugins/nim/project/nimtoolchainfactory.cpp @@ -42,7 +42,7 @@ namespace Nim { NimToolChainFactory::NimToolChainFactory() { - setDisplayName(tr("Nim")); + setDisplayName(NimToolChain::tr("Nim")); setSupportedToolChainType(Constants::C_NIMTOOLCHAIN_TYPEID); setSupportedLanguages({Constants::C_NIMLANGUAGE_ID}); setToolchainConstructor([] { return new NimToolChain; }); diff --git a/src/plugins/nim/project/nimtoolchainfactory.h b/src/plugins/nim/project/nimtoolchainfactory.h index 0b79653400..1e9e219e97 100644 --- a/src/plugins/nim/project/nimtoolchainfactory.h +++ b/src/plugins/nim/project/nimtoolchainfactory.h @@ -36,8 +36,6 @@ class NimToolChain; class NimToolChainFactory : public ProjectExplorer::ToolChainFactory { - Q_OBJECT - public: NimToolChainFactory(); diff --git a/src/plugins/perfprofiler/perfdatareader.cpp b/src/plugins/perfprofiler/perfdatareader.cpp index 4902c1fd20..48dcaf645f 100644 --- a/src/plugins/perfprofiler/perfdatareader.cpp +++ b/src/plugins/perfprofiler/perfdatareader.cpp @@ -54,6 +54,8 @@ #include <QTextStream> #include <QtEndian> +using namespace ProjectExplorer; + namespace PerfProfiler { namespace Internal { @@ -289,15 +291,14 @@ bool PerfDataReader::acceptsSamples() const return m_recording; } -QStringList PerfDataReader::collectArguments(const QString &executableDirPath, - const ProjectExplorer::Kit *kit) const +QStringList PerfDataReader::collectArguments(const QString &executableDirPath, const Kit *kit) const { QStringList arguments; if (!executableDirPath.isEmpty()) - arguments << QLatin1String("--app") << executableDirPath; + arguments << "--app" << executableDirPath; if (QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(kit)) { - arguments << QLatin1String("--extra") << QString::fromLatin1("%1%5%2%5%3%5%4") + arguments << "--extra" << QString("%1%5%2%5%3%5%4") .arg(QDir::toNativeSeparators(qt->libraryPath().toString())) .arg(QDir::toNativeSeparators(qt->pluginPath().toString())) .arg(QDir::toNativeSeparators(qt->hostBinPath().toString())) @@ -305,20 +306,18 @@ QStringList PerfDataReader::collectArguments(const QString &executableDirPath, .arg(QDir::listSeparator()); } - if (auto toolChain = ProjectExplorer::ToolChainKitAspect::toolChain( - kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID)) { - ProjectExplorer::Abi::Architecture architecture = toolChain->targetAbi().architecture(); - if (architecture == ProjectExplorer::Abi::ArmArchitecture && - toolChain->targetAbi().wordWidth() == 64) { - arguments << QLatin1String("--arch") << QLatin1String("aarch64"); - } else if (architecture != ProjectExplorer::Abi::UnknownArchitecture) { - arguments << QLatin1String("--arch") << ProjectExplorer::Abi::toString(architecture); + if (auto toolChain = ToolChainKitAspect::cxxToolChain(kit)) { + Abi::Architecture architecture = toolChain->targetAbi().architecture(); + if (architecture == Abi::ArmArchitecture && toolChain->targetAbi().wordWidth() == 64) { + arguments << "--arch" << "aarch64"; + } else if (architecture != Abi::UnknownArchitecture) { + arguments << "--arch" << Abi::toString(architecture); } } - QString sysroot = ProjectExplorer::SysRootKitAspect::sysRoot(kit).toString(); + QString sysroot = SysRootKitAspect::sysRoot(kit).toString(); if (!sysroot.isEmpty()) - arguments << QLatin1String("--sysroot") << sysroot; + arguments << "--sysroot" << sysroot; return arguments; } diff --git a/src/plugins/projectexplorer/CMakeLists.txt b/src/plugins/projectexplorer/CMakeLists.txt index a7aa76ae50..24b7dbd655 100644 --- a/src/plugins/projectexplorer/CMakeLists.txt +++ b/src/plugins/projectexplorer/CMakeLists.txt @@ -16,7 +16,6 @@ add_qtc_plugin(ProjectExplorer buildpropertiessettings.h buildpropertiessettingspage.cpp buildpropertiessettingspage.h buildconfiguration.cpp buildconfiguration.h - buildenvironmentwidget.cpp buildenvironmentwidget.h buildinfo.cpp buildinfo.h buildmanager.cpp buildmanager.h buildprogress.cpp buildprogress.h diff --git a/src/plugins/projectexplorer/abstractprocessstep.cpp b/src/plugins/projectexplorer/abstractprocessstep.cpp index 0fc6c7d44f..0cd35c047b 100644 --- a/src/plugins/projectexplorer/abstractprocessstep.cpp +++ b/src/plugins/projectexplorer/abstractprocessstep.cpp @@ -349,10 +349,7 @@ void AbstractProcessStep::processReadyReadStdOutput() if (!d->m_process) return; d->m_process->setReadChannel(QProcess::StandardOutput); - BuildConfiguration *bc = buildConfiguration(); - if (!bc) - bc = target()->activeBuildConfiguration(); - const bool utf8Output = bc && bc->environment().hasKey("VSLANG"); + const bool utf8Output = buildEnvironment().hasKey("VSLANG"); d->readData(&AbstractProcessStep::stdOutput, utf8Output); } diff --git a/src/plugins/projectexplorer/applicationlauncher.cpp b/src/plugins/projectexplorer/applicationlauncher.cpp index e0a725716a..a7ef576661 100644 --- a/src/plugins/projectexplorer/applicationlauncher.cpp +++ b/src/plugins/projectexplorer/applicationlauncher.cpp @@ -305,7 +305,7 @@ void ApplicationLauncherPrivate::readLocalStandardOutput() QByteArray data = m_guiProcess.readAllStandardOutput(); QString msg = m_outputCodec->toUnicode( data.constData(), data.length(), &m_outputCodecState); - emit q->appendMessage(msg, StdOutFormatSameLine, false); + emit q->appendMessage(msg, StdOutFormat, false); } void ApplicationLauncherPrivate::readLocalStandardError() @@ -313,7 +313,7 @@ void ApplicationLauncherPrivate::readLocalStandardError() QByteArray data = m_guiProcess.readAllStandardError(); QString msg = m_outputCodec->toUnicode( data.constData(), data.length(), &m_errorCodecState); - emit q->appendMessage(msg, StdErrFormatSameLine, false); + emit q->appendMessage(msg, StdErrFormat, false); } void ApplicationLauncherPrivate::cannotRetrieveLocalDebugOutput() diff --git a/src/plugins/projectexplorer/appoutputpane.cpp b/src/plugins/projectexplorer/appoutputpane.cpp index 42975294b3..d9261efa5e 100644 --- a/src/plugins/projectexplorer/appoutputpane.cpp +++ b/src/plugins/projectexplorer/appoutputpane.cpp @@ -83,15 +83,6 @@ static QString msgAttachDebuggerTooltip(const QString &handleDescription = QStri AppOutputPane::tr("Attach debugger to %1").arg(handleDescription); } -static void replaceAllChildWidgets(QLayout *layout, const QList<QWidget *> &newChildren) -{ - while (QLayoutItem *child = layout->takeAt(0)) - delete child; - - for (QWidget *widget : newChildren) - layout->addWidget(widget); -} - namespace { const char SETTINGS_KEY[] = "ProjectExplorer/AppOutput/Zoom"; const char C_APP_OUTPUT[] = "ProjectExplorer.ApplicationOutput"; @@ -700,10 +691,6 @@ void AppOutputPane::enableButtons(const RunControl *rc) m_attachButton->setToolTip(msgAttachDebuggerTooltip()); } setZoomButtonsEnabled(true); - - replaceAllChildWidgets(m_formatterWidget->layout(), rc->outputFormatter() ? - rc->outputFormatter()->toolbarWidgets() : - QList<QWidget *>()); } else { m_reRunButton->setEnabled(false); m_reRunButton->setIcon(Utils::Icons::RUN_SMALL_TOOLBAR.icon()); diff --git a/src/plugins/projectexplorer/buildconfiguration.cpp b/src/plugins/projectexplorer/buildconfiguration.cpp index c7269480ce..e57772846f 100644 --- a/src/plugins/projectexplorer/buildconfiguration.cpp +++ b/src/plugins/projectexplorer/buildconfiguration.cpp @@ -26,22 +26,22 @@ #include "buildconfiguration.h" #include "buildaspects.h" -#include "buildenvironmentwidget.h" #include "buildinfo.h" #include "buildsteplist.h" #include "buildstepspage.h" #include "buildsystem.h" -#include "namedwidget.h" +#include "environmentwidget.h" #include "kit.h" #include "kitinformation.h" #include "kitmanager.h" -#include "project.h" -#include "projectexplorer.h" +#include "namedwidget.h" #include "projectexplorerconstants.h" +#include "projectexplorer.h" +#include "project.h" #include "projectmacroexpander.h" #include "projecttree.h" -#include "target.h" #include "session.h" +#include "target.h" #include "toolchain.h" #include <coreplugin/idocument.h> @@ -54,8 +54,10 @@ #include <utils/mimetypes/mimetype.h> #include <utils/qtcassert.h> +#include <QCheckBox> #include <QDebug> #include <QFormLayout> +#include <QVBoxLayout> using namespace Utils; @@ -67,6 +69,45 @@ const char USER_ENVIRONMENT_CHANGES_KEY[] = "ProjectExplorer.BuildConfiguration. namespace ProjectExplorer { namespace Internal { +class BuildEnvironmentWidget : public NamedWidget +{ + Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::BuildEnvironmentWidget) + +public: + explicit BuildEnvironmentWidget(BuildConfiguration *bc) + : NamedWidget(tr("Build Environment")) + { + auto clearBox = new QCheckBox(tr("Clear system environment"), this); + clearBox->setChecked(!bc->useSystemEnvironment()); + + auto envWidget = new EnvironmentWidget(this, EnvironmentWidget::TypeLocal, clearBox); + envWidget->setBaseEnvironment(bc->baseEnvironment()); + envWidget->setBaseEnvironmentText(bc->baseEnvironmentText()); + envWidget->setUserChanges(bc->userEnvironmentChanges()); + + connect(envWidget, &EnvironmentWidget::userChangesChanged, this, [bc, envWidget] { + bc->setUserEnvironmentChanges(envWidget->userChanges()); + }); + + connect(clearBox, &QAbstractButton::toggled, this, [bc, envWidget](bool checked) { + bc->setUseSystemEnvironment(!checked); + envWidget->setBaseEnvironment(bc->baseEnvironment()); + envWidget->setBaseEnvironmentText(bc->baseEnvironmentText()); + }); + + connect(bc, &BuildConfiguration::environmentChanged, this, [bc, envWidget] { + envWidget->setBaseEnvironment(bc->baseEnvironment()); + envWidget->setBaseEnvironmentText(bc->baseEnvironmentText()); + }); + + auto vbox = new QVBoxLayout(this); + vbox->setContentsMargins(0, 0, 0, 0); + vbox->addWidget(clearBox); + vbox->addWidget(envWidget); + } +}; + + class BuildConfigurationPrivate { public: @@ -86,6 +127,7 @@ public: bool m_configWidgetHasFrame = false; QList<Core::Id> m_initialBuildSteps; QList<Core::Id> m_initialCleanSteps; + Utils::MacroExpander m_macroExpander; // FIXME: Remove. BuildConfiguration::BuildType m_initialBuildType = BuildConfiguration::Unknown; @@ -130,7 +172,7 @@ BuildConfiguration::BuildConfiguration(Target *target, Core::Id id) d->m_buildDirectoryAspect->setEnvironment(environment()); d->m_buildDirectoryAspect->setMacroExpanderProvider([this] { return macroExpander(); }); connect(d->m_buildDirectoryAspect, &BaseStringAspect::changed, - this, &BuildConfiguration::buildDirectoryChanged); + this, &BuildConfiguration::emitBuildDirectoryChanged); connect(this, &BuildConfiguration::environmentChanged, this, [this] { d->m_buildDirectoryAspect->setEnvironment(environment()); this->target()->buildEnvironmentChanged(this); @@ -204,6 +246,11 @@ void BuildConfiguration::doInitialize(const BuildInfo &info) d->m_initializer(info); } +MacroExpander *BuildConfiguration::macroExpander() const +{ + return &d->m_macroExpander; +} + void BuildConfiguration::setInitializer(const std::function<void(const BuildInfo &)> &initializer) { d->m_initializer = initializer; @@ -239,7 +286,7 @@ NamedWidget *BuildConfiguration::createConfigWidget() QList<NamedWidget *> BuildConfiguration::createSubConfigWidgets() { - return {new BuildEnvironmentWidget(this)}; + return {new Internal::BuildEnvironmentWidget(this)}; } BuildSystem *BuildConfiguration::buildSystem() const @@ -470,8 +517,7 @@ bool BuildConfiguration::isActive() const void BuildConfiguration::prependCompilerPathToEnvironment(Kit *k, Environment &env) { - const ToolChain *tc - = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID); + const ToolChain *tc = ToolChainKitAspect::cxxToolChain(k); if (!tc) return; diff --git a/src/plugins/projectexplorer/buildconfiguration.h b/src/plugins/projectexplorer/buildconfiguration.h index 04058f4aa7..35730eccc7 100644 --- a/src/plugins/projectexplorer/buildconfiguration.h +++ b/src/plugins/projectexplorer/buildconfiguration.h @@ -32,6 +32,8 @@ #include <utils/environment.h> #include <utils/fileutils.h> +namespace Utils { class MacroExpander; } + namespace ProjectExplorer { namespace Internal { class BuildConfigurationPrivate; } @@ -118,6 +120,8 @@ public: void doInitialize(const BuildInfo &info); + Utils::MacroExpander *macroExpander() const; + signals: void environmentChanged(); void buildDirectoryChanged(); diff --git a/src/plugins/projectexplorer/buildenvironmentwidget.cpp b/src/plugins/projectexplorer/buildenvironmentwidget.cpp deleted file mode 100644 index 68211385e8..0000000000 --- a/src/plugins/projectexplorer/buildenvironmentwidget.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** 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 -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "buildenvironmentwidget.h" - -#include "buildconfiguration.h" -#include "environmentwidget.h" - -#include <projectexplorer/target.h> - -#include <QVBoxLayout> -#include <QCheckBox> - -namespace ProjectExplorer { - -BuildEnvironmentWidget::BuildEnvironmentWidget(BuildConfiguration *bc) - : NamedWidget(tr("Build Environment")), m_buildConfiguration(bc) -{ - auto vbox = new QVBoxLayout(this); - vbox->setContentsMargins(0, 0, 0, 0); - m_clearSystemEnvironmentCheckBox = new QCheckBox(this); - m_clearSystemEnvironmentCheckBox->setText(tr("Clear system environment")); - - m_buildEnvironmentWidget = new EnvironmentWidget(this, EnvironmentWidget::TypeLocal, - m_clearSystemEnvironmentCheckBox); - vbox->addWidget(m_buildEnvironmentWidget); - - connect(m_buildEnvironmentWidget, &EnvironmentWidget::userChangesChanged, - this, &BuildEnvironmentWidget::environmentModelUserChangesChanged); - connect(m_clearSystemEnvironmentCheckBox, &QAbstractButton::toggled, - this, &BuildEnvironmentWidget::clearSystemEnvironmentCheckBoxClicked); - - connect(m_buildConfiguration, &BuildConfiguration::environmentChanged, - this, &BuildEnvironmentWidget::environmentChanged); - - m_clearSystemEnvironmentCheckBox->setChecked(!m_buildConfiguration->useSystemEnvironment()); - m_buildEnvironmentWidget->setBaseEnvironment(m_buildConfiguration->baseEnvironment()); - m_buildEnvironmentWidget->setBaseEnvironmentText(m_buildConfiguration->baseEnvironmentText()); - m_buildEnvironmentWidget->setUserChanges(m_buildConfiguration->userEnvironmentChanges()); -} - -void BuildEnvironmentWidget::environmentModelUserChangesChanged() -{ - m_buildConfiguration->setUserEnvironmentChanges(m_buildEnvironmentWidget->userChanges()); -} - -void BuildEnvironmentWidget::clearSystemEnvironmentCheckBoxClicked(bool checked) -{ - m_buildConfiguration->setUseSystemEnvironment(!checked); - m_buildEnvironmentWidget->setBaseEnvironment(m_buildConfiguration->baseEnvironment()); - m_buildEnvironmentWidget->setBaseEnvironmentText(m_buildConfiguration->baseEnvironmentText()); -} - -void BuildEnvironmentWidget::environmentChanged() -{ - m_buildEnvironmentWidget->setBaseEnvironment(m_buildConfiguration->baseEnvironment()); - m_buildEnvironmentWidget->setBaseEnvironmentText(m_buildConfiguration->baseEnvironmentText()); -} - -} // ProjectExplorer diff --git a/src/plugins/projectexplorer/buildstep.cpp b/src/plugins/projectexplorer/buildstep.cpp index 959e91d23c..275d9fdcfb 100644 --- a/src/plugins/projectexplorer/buildstep.cpp +++ b/src/plugins/projectexplorer/buildstep.cpp @@ -30,6 +30,7 @@ #include "deployconfiguration.h" #include "kitinformation.h" #include "project.h" +#include "projectexplorerconstants.h" #include "target.h" #include <coreplugin/variablechooser.h> @@ -117,6 +118,8 @@ This signal needs to be emitted if the build step runs in the GUI thread. */ +using namespace Utils; + static const char buildStepEnabledKey[] = "ProjectExplorer.BuildStep.Enabled"; namespace ProjectExplorer { @@ -127,10 +130,6 @@ BuildStep::BuildStep(BuildStepList *bsl, Core::Id id) : ProjectConfiguration(bsl, id) { QTC_CHECK(bsl->target() && bsl->target() == this->target()); - Utils::MacroExpander *expander = macroExpander(); - expander->setDisplayName(tr("Build Step")); - expander->setAccumulating(true); - expander->registerSubProvider([this] { return projectConfiguration()->macroExpander(); }); } void BuildStep::run() @@ -186,6 +185,13 @@ BuildConfiguration *BuildStep::buildConfiguration() const auto config = qobject_cast<BuildConfiguration *>(parent()->parent()); if (config) return config; + + // This situation should be avoided, as the step returned below is almost + // always not the right one, but the fallback is best we can do. + // A potential currently still valid path is accessing a build configuration + // from a BuildStep in a DeployConfiguration. Let's hunt those down and + // replace with explicit code there. + QTC_CHECK(false); // step is not part of a build configuration, use active build configuration of step's target return target()->activeBuildConfiguration(); } @@ -195,6 +201,8 @@ DeployConfiguration *BuildStep::deployConfiguration() const auto config = qobject_cast<DeployConfiguration *>(parent()->parent()); if (config) return config; + // See comment in buildConfiguration() + QTC_CHECK(false); // step is not part of a deploy configuration, use active deploy configuration of step's target return target()->activeDeployConfiguration(); } @@ -211,6 +219,41 @@ BuildSystem *BuildStep::buildSystem() const return target()->buildSystem(); } +Environment BuildStep::buildEnvironment() const +{ + if (auto bc = buildConfiguration()) + return bc->environment(); + return Environment::systemEnvironment(); +} + +FilePath BuildStep::buildDirectory() const +{ + if (auto bc = buildConfiguration()) + return bc->buildDirectory(); + return {}; +} + +BuildConfiguration::BuildType BuildStep::buildType() const +{ + if (auto bc = buildConfiguration()) + return bc->buildType(); + return BuildConfiguration::Unknown; +} + +Utils::MacroExpander *BuildStep::macroExpander() const +{ + if (auto bc = buildConfiguration()) + return bc->macroExpander(); + return Utils::globalMacroExpander(); +} + +QString BuildStep::fallbackWorkingDirectory() const +{ + if (auto bc = buildConfiguration()) + return {Constants::DEFAULT_WORKING_DIR}; + return {Constants::DEFAULT_WORKING_DIR_ALTERNATE}; +} + void BuildStep::reportRunResult(QFutureInterface<bool> &fi, bool success) { fi.reportResult(success); diff --git a/src/plugins/projectexplorer/buildstep.h b/src/plugins/projectexplorer/buildstep.h index 2b2cfe64a2..b8dd6b6718 100644 --- a/src/plugins/projectexplorer/buildstep.h +++ b/src/plugins/projectexplorer/buildstep.h @@ -26,6 +26,8 @@ #pragma once #include "projectconfiguration.h" + +#include "buildconfiguration.h" #include "projectexplorer_export.h" #include <utils/optional.h> @@ -38,6 +40,12 @@ #include <functional> #include <memory> +namespace Utils { +class Environment; +class FilePath; +class MacroExpander; +} // Utils + namespace ProjectExplorer { class BuildConfiguration; @@ -77,6 +85,11 @@ public: ProjectConfiguration *projectConfiguration() const; BuildSystem *buildSystem() const; + Utils::Environment buildEnvironment() const; + Utils::FilePath buildDirectory() const; + BuildConfiguration::BuildType buildType() const; + Utils::MacroExpander *macroExpander() const; + QString fallbackWorkingDirectory() const; enum class OutputFormat { Stdout, Stderr, // These are for forwarded output from external tools diff --git a/src/plugins/projectexplorer/buildsystem.cpp b/src/plugins/projectexplorer/buildsystem.cpp index ea299cd522..851a2565bc 100644 --- a/src/plugins/projectexplorer/buildsystem.cpp +++ b/src/plugins/projectexplorer/buildsystem.cpp @@ -142,6 +142,26 @@ void BuildSystem::requestDelayedParse() requestParseHelper(1000); } +void BuildSystem::requestParseWithCustomDelay(int delayInMs) +{ + requestParseHelper(delayInMs); +} + +void BuildSystem::cancelDelayedParseRequest() +{ + d->m_delayedParsingTimer.stop(); +} + +void BuildSystem::setParseDelay(int delayInMs) +{ + d->m_delayedParsingTimer.setInterval(delayInMs); +} + +int BuildSystem::parseDelay() const +{ + return d->m_delayedParsingTimer.interval(); +} + bool BuildSystem::isParsing() const { return d->m_isParsing; diff --git a/src/plugins/projectexplorer/buildsystem.h b/src/plugins/projectexplorer/buildsystem.h index 551f83ac00..c12e75e9c4 100644 --- a/src/plugins/projectexplorer/buildsystem.h +++ b/src/plugins/projectexplorer/buildsystem.h @@ -62,6 +62,10 @@ public: void requestParse(); void requestDelayedParse(); + void requestParseWithCustomDelay(int delayInMs = 1000); + void cancelDelayedParseRequest(); + void setParseDelay(int delayInMs); + int parseDelay() const; bool isParsing() const; bool hasParsingData() const; diff --git a/src/plugins/projectexplorer/customtoolchain.cpp b/src/plugins/projectexplorer/customtoolchain.cpp index 654337ab2c..e24e859862 100644 --- a/src/plugins/projectexplorer/customtoolchain.cpp +++ b/src/plugins/projectexplorer/customtoolchain.cpp @@ -85,7 +85,7 @@ CustomToolChain::CustomToolChain() : ToolChain(Constants::CUSTOM_TOOLCHAIN_TYPEID), m_outputParserId(GccParser::id()) { - setTypeDisplayName(Internal::CustomToolChainFactory::tr("Custom")); + setTypeDisplayName(tr("Custom")); } Abi CustomToolChain::targetAbi() const @@ -405,7 +405,7 @@ namespace Internal { CustomToolChainFactory::CustomToolChainFactory() { - setDisplayName(tr("Custom")); + setDisplayName(CustomToolChain::tr("Custom")); setSupportedToolChainType(Constants::CUSTOM_TOOLCHAIN_TYPEID); setSupportsAllLanguages(true); setToolchainConstructor([] { return new CustomToolChain; }); diff --git a/src/plugins/projectexplorer/customtoolchain.h b/src/plugins/projectexplorer/customtoolchain.h index c84d0bba1a..074a09e0f5 100644 --- a/src/plugins/projectexplorer/customtoolchain.h +++ b/src/plugins/projectexplorer/customtoolchain.h @@ -135,8 +135,6 @@ namespace Internal { class CustomToolChainFactory : public ToolChainFactory { - Q_OBJECT - public: CustomToolChainFactory(); }; diff --git a/src/plugins/projectexplorer/deployconfiguration.cpp b/src/plugins/projectexplorer/deployconfiguration.cpp index f410003646..e5469e9e3b 100644 --- a/src/plugins/projectexplorer/deployconfiguration.cpp +++ b/src/plugins/projectexplorer/deployconfiguration.cpp @@ -47,14 +47,6 @@ DeployConfiguration::DeployConfiguration(Target *target, Core::Id id) m_stepList(this, Constants::BUILDSTEPS_DEPLOY) { QTC_CHECK(target && target == this->target()); - Utils::MacroExpander *expander = macroExpander(); - expander->setDisplayName(tr("Deploy Settings")); - expander->setAccumulating(true); - expander->registerSubProvider([target] { - BuildConfiguration *bc = target->activeBuildConfiguration(); - return bc ? bc->macroExpander() : target->macroExpander(); - }); - //: Default DeployConfiguration display name setDefaultDisplayName(tr("Deploy locally")); } diff --git a/src/plugins/projectexplorer/environmentwidget.cpp b/src/plugins/projectexplorer/environmentwidget.cpp index d89adccb45..517e840a95 100644 --- a/src/plugins/projectexplorer/environmentwidget.cpp +++ b/src/plugins/projectexplorer/environmentwidget.cpp @@ -36,22 +36,101 @@ #include <utils/hostosinfo.h> #include <utils/itemviews.h> #include <utils/namevaluevalidator.h> +#include <utils/qtcassert.h> #include <utils/tooltip/tooltip.h> +#include <QDialogButtonBox> #include <QDir> #include <QFileDialog> #include <QFileInfo> -#include <QString> +#include <QHBoxLayout> +#include <QKeyEvent> +#include <QLineEdit> #include <QPushButton> +#include <QString> +#include <QStyledItemDelegate> #include <QTreeView> +#include <QTreeWidget> +#include <QTreeWidgetItem> #include <QVBoxLayout> -#include <QKeyEvent> -#include <QStyledItemDelegate> -#include <QLineEdit> -#include <QDebug> namespace ProjectExplorer { +class PathListDialog : public QDialog +{ + Q_DECLARE_TR_FUNCTIONS(EnvironmentWidget) +public: + PathListDialog(const QString &varName, const QString &paths, QWidget *parent) : QDialog(parent) + { + const auto mainLayout = new QVBoxLayout(this); + const auto viewLayout = new QHBoxLayout; + const auto buttonsLayout = new QVBoxLayout; + const auto addButton = new QPushButton(tr("Add ...")); + const auto removeButton = new QPushButton(tr("Remove")); + const auto editButton = new QPushButton(tr("Edit...")); + buttonsLayout->addWidget(addButton); + buttonsLayout->addWidget(removeButton); + buttonsLayout->addWidget(editButton); + buttonsLayout->addStretch(1); + const auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok + | QDialogButtonBox::Cancel); + viewLayout->addWidget(&m_view); + viewLayout->addLayout(buttonsLayout); + mainLayout->addLayout(viewLayout); + mainLayout->addWidget(buttonBox); + + m_view.setHeaderLabel(varName); + const QStringList pathList = paths.split(Utils::HostOsInfo::pathListSeparator(), + QString::SkipEmptyParts); + for (const QString &path : pathList) + addPath(path); + + connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + connect(addButton, &QPushButton::clicked, this, [this] { + const QString dir = QDir::toNativeSeparators( + QFileDialog::getExistingDirectory(this, tr("Choose Directory"))); + if (!dir.isEmpty()) + addPath(dir); + }); + connect(removeButton, &QPushButton::clicked, this, [this] { + const QList<QTreeWidgetItem *> selected = m_view.selectedItems(); + QTC_ASSERT(selected.count() == 1, return); + delete selected.first(); + }); + connect(editButton, &QPushButton::clicked, this, [this] { + const QList<QTreeWidgetItem *> selected = m_view.selectedItems(); + QTC_ASSERT(selected.count() == 1, return); + m_view.editItem(selected.first(), 0); + }); + const auto updateButtonStates = [this, removeButton, editButton] { + const bool hasSelection = !m_view.selectedItems().isEmpty(); + removeButton->setEnabled(hasSelection); + editButton->setEnabled(hasSelection); + }; + connect(m_view.selectionModel(), &QItemSelectionModel::selectionChanged, + this, updateButtonStates); + updateButtonStates(); + } + + QString paths() const + { + QStringList pathList; + for (int i = 0; i < m_view.topLevelItemCount(); ++i) + pathList << QDir::fromNativeSeparators(m_view.topLevelItem(i)->text(0)); + return pathList.join(Utils::HostOsInfo::pathListSeparator()); + } + +private: + void addPath(const QString &path) + { + const auto item = new QTreeWidgetItem(&m_view, {QDir::toNativeSeparators(path)}); + item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable); + } + + QTreeWidget m_view; +}; + class EnvironmentDelegate : public QStyledItemDelegate { public: @@ -85,7 +164,7 @@ class EnvironmentWidgetPrivate { public: Utils::EnvironmentModel *m_model; - + EnvironmentWidget::Type m_type = EnvironmentWidget::TypeLocal; QString m_baseEnvironmentText; EnvironmentWidget::OpenTerminalFunc m_openTerminalFunc; Utils::DetailsWidget *m_detailsContainer; @@ -105,6 +184,7 @@ EnvironmentWidget::EnvironmentWidget(QWidget *parent, Type type, QWidget *additi : QWidget(parent), d(std::make_unique<EnvironmentWidgetPrivate>()) { d->m_model = new Utils::EnvironmentModel(); + d->m_type = type; connect(d->m_model, &Utils::EnvironmentModel::userChangesChanged, this, &EnvironmentWidget::userChangesChanged); connect(d->m_model, &QAbstractItemModel::modelReset, @@ -377,7 +457,15 @@ void EnvironmentWidget::updateButtons() void EnvironmentWidget::editEnvironmentButtonClicked() { - d->m_environmentView->edit(d->m_environmentView->currentIndex()); + const QModelIndex current = d->m_environmentView->currentIndex(); + if (current.column() == 1 && d->m_type == TypeLocal && currentEntryIsPathList(current)) { + PathListDialog dlg(d->m_model->indexToVariable(current), + d->m_model->data(current).toString(), this); + if (dlg.exec() == QDialog::Accepted) + d->m_model->setData(current, dlg.paths()); + } else { + d->m_environmentView->edit(current); + } } void EnvironmentWidget::addEnvironmentButtonClicked() diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index eef0e9ad84..4b2d04e6e0 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -265,7 +265,7 @@ static Utils::FilePath gccInstallDir(const FilePath &path, const QStringList &en GccToolChain::GccToolChain(Core::Id typeId) : ToolChain(typeId) { - setTypeDisplayName(GccToolChainFactory::tr("GCC")); + setTypeDisplayName(tr("GCC")); } void GccToolChain::setCompilerCommand(const FilePath &path) @@ -1045,7 +1045,7 @@ static Utils::FilePaths renesasRl78SearchPathsFromRegistry() GccToolChainFactory::GccToolChainFactory() { - setDisplayName(tr("GCC")); + setDisplayName(GccToolChain::tr("GCC")); setSupportedToolChainType(Constants::GCC_TOOLCHAIN_TYPEID); setSupportedLanguages({Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID}); setToolchainConstructor([] { return new GccToolChain(Constants::GCC_TOOLCHAIN_TYPEID); }); @@ -1472,7 +1472,7 @@ ClangToolChain::ClangToolChain() : ClangToolChain::ClangToolChain(Core::Id typeId) : GccToolChain(typeId) { - setTypeDisplayName(ClangToolChainFactory::tr("Clang")); + setTypeDisplayName(tr("Clang")); syncAutodetectedWithParentToolchains(); } @@ -1639,7 +1639,7 @@ IOutputParser *ClangToolChain::outputParser() const ClangToolChainFactory::ClangToolChainFactory() { - setDisplayName(tr("Clang")); + setDisplayName(ClangToolChain::tr("Clang")); setSupportedToolChainType(Constants::CLANG_TOOLCHAIN_TYPEID); setSupportedLanguages({Constants::CXX_LANGUAGE_ID, Constants::C_LANGUAGE_ID}); setToolchainConstructor([] { return new ClangToolChain; }); @@ -1798,7 +1798,7 @@ void ClangToolChainConfigWidget::makeReadOnlyImpl() MingwToolChain::MingwToolChain() : GccToolChain(Constants::MINGW_TOOLCHAIN_TYPEID) { - setTypeDisplayName(MingwToolChainFactory::tr("MinGW")); + setTypeDisplayName(MingwToolChain::tr("MinGW")); } QStringList MingwToolChain::suggestedMkspecList() const @@ -1833,7 +1833,7 @@ FilePath MingwToolChain::makeCommand(const Environment &environment) const MingwToolChainFactory::MingwToolChainFactory() { - setDisplayName(tr("MinGW")); + setDisplayName(MingwToolChain::tr("MinGW")); setSupportedToolChainType(Constants::MINGW_TOOLCHAIN_TYPEID); setSupportedLanguages({Constants::CXX_LANGUAGE_ID, Constants::C_LANGUAGE_ID}); setToolchainConstructor([] { return new MingwToolChain; }); @@ -1873,7 +1873,7 @@ QList<ToolChain *> MingwToolChainFactory::detectForImport(const ToolChainDescrip LinuxIccToolChain::LinuxIccToolChain() : GccToolChain(Constants::LINUXICC_TOOLCHAIN_TYPEID) { - setTypeDisplayName(LinuxIccToolChainFactory::tr("ICC")); + setTypeDisplayName(LinuxIccToolChain::tr("ICC")); } /** @@ -1914,7 +1914,7 @@ QStringList LinuxIccToolChain::suggestedMkspecList() const LinuxIccToolChainFactory::LinuxIccToolChainFactory() { - setDisplayName(tr("ICC")); + setDisplayName(LinuxIccToolChain::tr("ICC")); setSupportedToolChainType(Constants::LINUXICC_TOOLCHAIN_TYPEID); setSupportedLanguages({Constants::CXX_LANGUAGE_ID, Constants::C_LANGUAGE_ID}); setToolchainConstructor([] { return new LinuxIccToolChain; }); diff --git a/src/plugins/projectexplorer/gcctoolchain.h b/src/plugins/projectexplorer/gcctoolchain.h index 8ecf7aa375..a0761aa1fe 100644 --- a/src/plugins/projectexplorer/gcctoolchain.h +++ b/src/plugins/projectexplorer/gcctoolchain.h @@ -66,6 +66,8 @@ inline const QStringList gccPredefinedMacrosOptions(Core::Id languageId) class PROJECTEXPLORER_EXPORT GccToolChain : public ToolChain { + Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::GccToolChain) + public: GccToolChain(Core::Id typeId); @@ -212,6 +214,8 @@ private: class PROJECTEXPLORER_EXPORT ClangToolChain : public GccToolChain { + Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::ClangToolChain) + public: ClangToolChain(); explicit ClangToolChain(Core::Id typeId); @@ -258,6 +262,8 @@ private: class PROJECTEXPLORER_EXPORT MingwToolChain : public GccToolChain { + Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::MingwToolChain) + public: Utils::FilePath makeCommand(const Utils::Environment &environment) const override; @@ -276,6 +282,8 @@ private: class PROJECTEXPLORER_EXPORT LinuxIccToolChain : public GccToolChain { + Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::LinuxIccToolChain) + public: Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const override; IOutputParser *outputParser() const override; diff --git a/src/plugins/projectexplorer/gcctoolchainfactories.h b/src/plugins/projectexplorer/gcctoolchainfactories.h index c714a5ce16..42e6c05c01 100644 --- a/src/plugins/projectexplorer/gcctoolchainfactories.h +++ b/src/plugins/projectexplorer/gcctoolchainfactories.h @@ -49,8 +49,6 @@ namespace Internal { class GccToolChainFactory : public ToolChainFactory { - Q_OBJECT - public: GccToolChainFactory(); @@ -132,8 +130,6 @@ private: class ClangToolChainFactory : public GccToolChainFactory { - Q_OBJECT - public: ClangToolChainFactory(); @@ -147,8 +143,6 @@ public: class MingwToolChainFactory : public GccToolChainFactory { - Q_OBJECT - public: MingwToolChainFactory(); @@ -162,8 +156,6 @@ public: class LinuxIccToolChainFactory : public GccToolChainFactory { - Q_OBJECT - public: LinuxIccToolChainFactory(); diff --git a/src/plugins/projectexplorer/ioutputparser.h b/src/plugins/projectexplorer/ioutputparser.h index 1872461cbb..cd65378fe2 100644 --- a/src/plugins/projectexplorer/ioutputparser.h +++ b/src/plugins/projectexplorer/ioutputparser.h @@ -28,7 +28,7 @@ #include "projectexplorer_export.h" #include "buildstep.h" -#include <QString> +namespace Utils { class FilePath; } namespace ProjectExplorer { class Task; diff --git a/src/plugins/projectexplorer/jsonwizard/jsonfilepage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonfilepage.cpp index 865ee82865..19615f929a 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonfilepage.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonfilepage.cpp @@ -45,6 +45,7 @@ void JsonFilePage::initializePage() setFileName(wiz->stringValue(QLatin1String("InitialFileName"))); if (path().isEmpty()) setPath(wiz->stringValue(QLatin1String("InitialPath"))); + setDefaultSuffix(wiz->stringValue("DefaultSuffix")); } bool JsonFilePage::validatePage() diff --git a/src/plugins/projectexplorer/kitinformation.cpp b/src/plugins/projectexplorer/kitinformation.cpp index 69383652c8..d21ededfd7 100644 --- a/src/plugins/projectexplorer/kitinformation.cpp +++ b/src/plugins/projectexplorer/kitinformation.cpp @@ -511,19 +511,19 @@ KitAspectWidget *ToolChainKitAspect::createConfigWidget(Kit *k) const QString ToolChainKitAspect::displayNamePostfix(const Kit *k) const { - ToolChain *tc = toolChain(k, Constants::CXX_LANGUAGE_ID); + ToolChain *tc = cxxToolChain(k); return tc ? tc->displayName() : QString(); } KitAspect::ItemList ToolChainKitAspect::toUserOutput(const Kit *k) const { - ToolChain *tc = toolChain(k, Constants::CXX_LANGUAGE_ID); + ToolChain *tc = cxxToolChain(k); return {{tr("Compiler"), tc ? tc->displayName() : tr("None")}}; } void ToolChainKitAspect::addToEnvironment(const Kit *k, Utils::Environment &env) const { - ToolChain *tc = toolChain(k, Constants::CXX_LANGUAGE_ID); + ToolChain *tc = cxxToolChain(k); if (tc) tc->addToEnvironment(env); } @@ -534,24 +534,24 @@ void ToolChainKitAspect::addToMacroExpander(Kit *kit, Utils::MacroExpander *expa // Compatibility with Qt Creator < 4.2: expander->registerVariable("Compiler:Name", tr("Compiler"), - [kit]() -> QString { - const ToolChain *tc = toolChain(kit, Constants::CXX_LANGUAGE_ID); + [kit] { + const ToolChain *tc = cxxToolChain(kit); return tc ? tc->displayName() : tr("None"); }); expander->registerVariable("Compiler:Executable", tr("Path to the compiler executable"), - [kit]() -> QString { - const ToolChain *tc = toolChain(kit, Constants::CXX_LANGUAGE_ID); + [kit] { + const ToolChain *tc = cxxToolChain(kit); return tc ? tc->compilerCommand().toString() : QString(); }); expander->registerPrefix("Compiler:Name", tr("Compiler for different languages"), - [kit](const QString &ls) -> QString { + [kit](const QString &ls) { const ToolChain *tc = toolChain(kit, findLanguage(ls)); return tc ? tc->displayName() : tr("None"); }); expander->registerPrefix("Compiler:Executable", tr("Compiler executable for different languages"), - [kit](const QString &ls) -> QString { + [kit](const QString &ls) { const ToolChain *tc = toolChain(kit, findLanguage(ls)); return tc ? tc->compilerCommand().toString() : QString(); }); @@ -594,6 +594,17 @@ ToolChain *ToolChainKitAspect::toolChain(const Kit *k, Core::Id language) return ToolChainManager::findToolChain(toolChainId(k, language)); } +ToolChain *ToolChainKitAspect::cToolChain(const Kit *k) +{ + return ToolChainManager::findToolChain(toolChainId(k, ProjectExplorer::Constants::C_LANGUAGE_ID)); +} + +ToolChain *ToolChainKitAspect::cxxToolChain(const Kit *k) +{ + return ToolChainManager::findToolChain(toolChainId(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID)); +} + + QList<ToolChain *> ToolChainKitAspect::toolChains(const Kit *k) { QTC_ASSERT(k, return QList<ToolChain *>()); diff --git a/src/plugins/projectexplorer/kitinformation.h b/src/plugins/projectexplorer/kitinformation.h index 1df90adb53..e4179f2a61 100644 --- a/src/plugins/projectexplorer/kitinformation.h +++ b/src/plugins/projectexplorer/kitinformation.h @@ -90,6 +90,8 @@ public: static Core::Id id(); static QByteArray toolChainId(const Kit *k, Core::Id language); static ToolChain *toolChain(const Kit *k, Core::Id language); + static ToolChain *cToolChain(const Kit *k); + static ToolChain *cxxToolChain(const Kit *k); static QList<ToolChain *> toolChains(const Kit *k); static void setToolChain(Kit *k, ToolChain *tc); static void setAllToolChainsToMatch(Kit *k, ToolChain *tc); diff --git a/src/plugins/projectexplorer/makestep.cpp b/src/plugins/projectexplorer/makestep.cpp index ed8a048e68..ea327fe303 100644 --- a/src/plugins/projectexplorer/makestep.cpp +++ b/src/plugins/projectexplorer/makestep.cpp @@ -81,23 +81,19 @@ void MakeStep::setAvailableBuildTargets(const QStringList &buildTargets) bool MakeStep::init() { - BuildConfiguration *bc = buildConfiguration(); - if (!bc) - emit addTask(Task::buildConfigurationMissingTask()); - const CommandLine make = effectiveMakeCommand(Execution); if (make.executable().isEmpty()) emit addTask(makeCommandMissingTask()); - if (!bc || make.executable().isEmpty()) { + if (make.executable().isEmpty()) { emitFaultyConfigurationMessage(); return false; } ProcessParameters *pp = processParameters(); - pp->setMacroExpander(bc->macroExpander()); - pp->setWorkingDirectory(bc->buildDirectory()); - pp->setEnvironment(environment(bc)); + pp->setMacroExpander(macroExpander()); + pp->setWorkingDirectory(buildDirectory()); + pp->setEnvironment(buildEnvironment()); pp->setCommandLine(make); pp->resolveAll(); @@ -153,7 +149,7 @@ FilePath MakeStep::defaultMakeCommand() const BuildConfiguration *bc = buildConfiguration(); if (!bc) return {}; - const Utils::Environment env = environment(bc); + const Utils::Environment env = makeEnvironment(); for (const ToolChain *tc : preferredToolChains(target()->kit())) { FilePath make = tc->makeCommand(env); if (!make.isEmpty()) @@ -225,7 +221,7 @@ static Utils::optional<int> argsJobCount(const QString &str) bool MakeStep::makeflagsJobCountMismatch() const { - const Utils::Environment env = environment(buildConfiguration()); + const Environment env = makeEnvironment(); if (!env.hasKey(MAKEFLAGS)) return false; Utils::optional<int> makeFlagsJobCount = argsJobCount(env.expandedValueForKey(MAKEFLAGS)); @@ -234,7 +230,7 @@ bool MakeStep::makeflagsJobCountMismatch() const bool MakeStep::makeflagsContainsJobCount() const { - const Utils::Environment env = environment(buildConfiguration()); + const Environment env = makeEnvironment(); if (!env.hasKey(MAKEFLAGS)) return false; return argsJobCount(env.expandedValueForKey(MAKEFLAGS)).has_value(); @@ -245,9 +241,9 @@ bool MakeStep::userArgsContainsJobCount() const return argsJobCount(m_userArguments).has_value(); } -Utils::Environment MakeStep::environment(BuildConfiguration *bc) const +Environment MakeStep::makeEnvironment() const { - Utils::Environment env = bc ? bc->environment() : Utils::Environment::systemEnvironment(); + Environment env = buildEnvironment(); Utils::Environment::setupEnglishOutput(&env); if (makeCommand().isEmpty()) { // We also prepend "L" to the MAKEFLAGS, so that nmake / jom are less verbose @@ -494,10 +490,10 @@ void MakeStepConfigWidget::updateDetails() m_ui->disableInSubDirsCheckBox->setChecked(!m_makeStep->enabledForSubDirs()); ProcessParameters param; - param.setMacroExpander(bc->macroExpander()); - param.setWorkingDirectory(bc->buildDirectory()); + param.setMacroExpander(m_makeStep->macroExpander()); + param.setWorkingDirectory(m_makeStep->buildDirectory()); param.setCommandLine(make); - param.setEnvironment(m_makeStep->environment(bc)); + param.setEnvironment(m_makeStep->buildEnvironment()); if (param.commandMissing()) setSummaryText(tr("<b>Make:</b> %1 not found in the environment.") diff --git a/src/plugins/projectexplorer/makestep.h b/src/plugins/projectexplorer/makestep.h index 721e99b440..bd02090bec 100644 --- a/src/plugins/projectexplorer/makestep.h +++ b/src/plugins/projectexplorer/makestep.h @@ -87,7 +87,7 @@ public: bool enabledForSubDirs() const { return m_enabledForSubDirs; } void setEnabledForSubDirs(bool enabled) { m_enabledForSubDirs = enabled; } - Utils::Environment environment(BuildConfiguration *bc) const; + Utils::Environment makeEnvironment() const; protected: bool fromMap(const QVariantMap &map) override; diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.cpp b/src/plugins/projectexplorer/miniprojecttargetselector.cpp index 342c877526..0057366a17 100644 --- a/src/plugins/projectexplorer/miniprojecttargetselector.cpp +++ b/src/plugins/projectexplorer/miniprojecttargetselector.cpp @@ -92,76 +92,43 @@ static QIcon createCenteredIcon(const QIcon &icon, const QIcon &overlay) return QIcon(targetPixmap); } -class SelectorView : public TreeView -{ - Q_OBJECT - -public: - SelectorView(QWidget *parent); - - void setMaxCount(int maxCount); - int maxCount(); - - int optimalWidth() const; - void setOptimalWidth(int width); - - int padding(); - -private: - void keyPressEvent(QKeyEvent *event) override; - void keyReleaseEvent(QKeyEvent *event) override; - - int m_maxCount = 0; - int m_optimalWidth = 0; -}; - -// The project-specific classes look annoyingly similar to the generic ones. -// Can we merge them? -class SelectorProjectItem : public TreeItem -{ -public: - SelectorProjectItem() = default; - SelectorProjectItem(Project *project) : m_project(project) {} - Project *project() const { return m_project; } - QString displayName() const - { - const auto hasSameProjectName = [this](TreeItem *ti) { - return ti != this && static_cast<SelectorProjectItem *>(ti)->project()->displayName() - == project()->displayName(); - }; - QString displayName = m_project->displayName(); - if (parent()->findAnyChild(hasSameProjectName)) { - displayName.append(" (").append(project()->projectFilePath().toUserOutput()) - .append(')'); - } - return displayName; - } - -private: - QVariant data(int column, int role) const override - { - return column == 0 && role == Qt::DisplayRole ? displayName() : QString(); - } - - Project *m_project = nullptr; -}; - class GenericItem : public TreeItem { public: GenericItem() = default; GenericItem(QObject *object) : m_object(object) {} QObject *object() const { return m_object; } - QString displayName() const + QString rawDisplayName() const { + if (const auto p = qobject_cast<Project *>(object())) + return p->displayName(); if (const auto t = qobject_cast<Target *>(object())) return t->displayName(); return static_cast<ProjectConfiguration *>(object())->displayName(); + + } + QString displayName() const + { + if (const auto p = qobject_cast<Project *>(object())) { + const auto hasSameProjectName = [this](TreeItem *ti) { + return ti != this + && static_cast<GenericItem *>(ti)->rawDisplayName() == rawDisplayName(); + }; + QString displayName = p->displayName(); + if (parent()->findAnyChild(hasSameProjectName)) { + displayName.append(" (").append(p->projectFilePath().toUserOutput()) + .append(')'); + } + return displayName; + } + return rawDisplayName(); } private: - QString toolTip() const + QVariant toolTip() const { + if (qobject_cast<Project *>(object())) + return {}; if (const auto t = qobject_cast<Target *>(object())) return t->toolTip(); return static_cast<ProjectConfiguration *>(object())->toolTip(); @@ -178,7 +145,8 @@ private: return displayName(); case Qt::ToolTipRole: return toolTip(); - default:break; + default: + break; } return {}; } @@ -186,72 +154,101 @@ private: QObject *m_object = nullptr; }; -static QString rawDisplayName(const SelectorProjectItem *item) +static bool compareItems(const TreeItem *ti1, const TreeItem *ti2) { - return item->project()->displayName(); -} -static QString rawDisplayName(const GenericItem *item) { return item->displayName(); } - -template<typename T> bool compareItems(const TreeItem *ti1, const TreeItem *ti2) -{ - const int result = caseFriendlyCompare(rawDisplayName(static_cast<const T*>(ti1)), - rawDisplayName(static_cast<const T*>(ti2))); + const int result = caseFriendlyCompare(static_cast<const GenericItem *>(ti1)->rawDisplayName(), + static_cast<const GenericItem *>(ti2)->rawDisplayName()); if (result != 0) return result < 0; return ti1 < ti2; } -class ProjectsModel : public TreeModel<SelectorProjectItem, SelectorProjectItem> +class GenericModel : public TreeModel<GenericItem, GenericItem> { Q_OBJECT public: - ProjectsModel(QObject *parent) : TreeModel(parent) + GenericModel(QObject *parent) : TreeModel(parent) { } + + void rebuild(const QList<QObject *> &objects) { - connect(SessionManager::instance(), &SessionManager::projectAdded, - this, [this](Project *project) { - emit projectAdded(addItemForProject(project)); - }); - connect(SessionManager::instance(), &SessionManager::aboutToRemoveProject, - this, [this](const Project *project) { - SelectorProjectItem * const item = itemForProject(project); - if (!item) - return; - destroyItem(item); - emit optimalWidthChanged(); - }); - buildTree(); + clear(); + for (QObject * const e : objects) + addItemForObject(e); + } + + const GenericItem *addItemForObject(QObject *object) + { + const auto item = new GenericItem(object); + rootItem()->insertOrderedChild(item, &compareItems); + if (const auto project = qobject_cast<Project *>(object)) { + connect(project, &Project::displayNameChanged, + this, &GenericModel::displayNameChanged); + } else if (const auto target = qobject_cast<Target *>(object)) { + connect(target, &Target::kitChanged, this, &GenericModel::displayNameChanged); + } else { + const auto pc = qobject_cast<ProjectConfiguration *>(object); + QTC_CHECK(pc); + connect(pc, &ProjectConfiguration::displayNameChanged, + this, &GenericModel::displayNameChanged); + connect(pc, &ProjectConfiguration::toolTipChanged, + this, &GenericModel::updateToolTips); + } + return item; } - SelectorProjectItem *itemForProject(const Project *project) const + GenericItem *itemForObject(const QObject *object) const { - return findItemAtLevel<1>([project](const SelectorProjectItem *item) { - return item->project() == project; + return findItemAtLevel<1>([object](const GenericItem *item) { + return item->object() == object; }); } + void setColumnCount(int columns) { m_columnCount = columns; } + signals: - void projectAdded(const SelectorProjectItem *projectItem); - void requestRestoreCurrentIndex(); - void optimalWidthChanged(); + void displayNameChanged(); private: - const SelectorProjectItem *addItemForProject(Project *project) + void updateToolTips() { - const auto projectItem = new SelectorProjectItem(project); - rootItem()->insertOrderedChild(projectItem, &compareItems<SelectorProjectItem>); - connect(project, &Project::displayNameChanged, this, [this] { - rootItem()->sortChildren(&compareItems<SelectorProjectItem>); - emit optimalWidthChanged(); - emit requestRestoreCurrentIndex(); - }); - return projectItem; + emit dataChanged(index(0, 0), index(rowCount() - 1, 0), {Qt::ToolTipRole}); } +}; + +class SelectorView : public TreeView +{ + Q_OBJECT + +public: + SelectorView(QWidget *parent); + + void setMaxCount(int maxCount); + int maxCount(); + + int optimalWidth() const; + void setOptimalWidth(int width); - void buildTree() + int padding(); + + GenericModel *theModel() const { return static_cast<GenericModel *>(model()); } + +protected: + void resetOptimalWidth() { - for (Project * const project : SessionManager::projects()) - addItemForProject(project); + int width = 0; + QFontMetrics fn(font()); + theModel()->forItemsAtLevel<1>([this, &width, &fn](const GenericItem *item) { + width = qMax(fn.horizontalAdvance(item->displayName()) + padding(), width); + }); + setOptimalWidth(width); } + +private: + void keyPressEvent(QKeyEvent *event) override; + void keyReleaseEvent(QKeyEvent *event) override; + + int m_maxCount = 0; + int m_optimalWidth = 0; }; class ProjectListView : public SelectorView @@ -261,96 +258,54 @@ class ProjectListView : public SelectorView public: explicit ProjectListView(QWidget *parent = nullptr) : SelectorView(parent) { - ProjectsModel * const model = new ProjectsModel(this); - connect(model, &ProjectsModel::projectAdded, this, - [this](const SelectorProjectItem *projectItem) { + const auto model = new GenericModel(this); + model->rebuild(transform<QList<QObject *>>(SessionManager::projects(), + [](Project *p) { return p; })); + connect(SessionManager::instance(), &SessionManager::projectAdded, + this, [this, model](Project *project) { + const GenericItem *projectItem = model->addItemForObject(project); QFontMetrics fn(font()); const int width = fn.horizontalAdvance(projectItem->displayName()) + padding(); if (width > optimalWidth()) setOptimalWidth(width); restoreCurrentIndex(); }); - connect(model, &ProjectsModel::optimalWidthChanged, - this, &ProjectListView::resetOptimalWidth); - connect(model, &ProjectsModel::requestRestoreCurrentIndex, - this, &ProjectListView::restoreCurrentIndex); + connect(SessionManager::instance(), &SessionManager::aboutToRemoveProject, + this, [this, model](const Project *project) { + GenericItem * const item = model->itemForObject(project); + if (!item) + return; + model->destroyItem(item); + resetOptimalWidth(); + }); connect(SessionManager::instance(), &SessionManager::startupProjectChanged, this, [this, model](const Project *project) { - const SelectorProjectItem * const item = model->itemForProject(project); + const GenericItem * const item = model->itemForObject(project); if (item) setCurrentIndex(item->index()); }); + connect(model, &GenericModel::displayNameChanged, this, [this, model] { + model->rootItem()->sortChildren(&compareItems); + resetOptimalWidth(); + restoreCurrentIndex(); + }); setModel(model); connect(selectionModel(), &QItemSelectionModel::currentChanged, this, [model](const QModelIndex &index) { - const SelectorProjectItem * const item = model->itemForIndex(index); - if (item && item->project()) - SessionManager::setStartupProject(item->project()); + const GenericItem * const item = model->itemForIndex(index); + if (item && item->object()) + SessionManager::setStartupProject(qobject_cast<Project *>(item->object())); }); } private: - ProjectsModel *theModel() const { return static_cast<ProjectsModel *>(model()); } - void restoreCurrentIndex() { - const SelectorProjectItem * const itemForStartupProject - = theModel()->itemForProject(SessionManager::startupProject()); + const GenericItem * const itemForStartupProject + = theModel()->itemForObject(SessionManager::startupProject()); if (itemForStartupProject) setCurrentIndex(theModel()->indexForItem(itemForStartupProject)); } - - void resetOptimalWidth() - { - int width = 0; - QFontMetrics fn(font()); - theModel()->forItemsAtLevel<1>([this, &width, &fn](const SelectorProjectItem *item) { - width = qMax(fn.horizontalAdvance(item->displayName()) + padding(), width); - }); - setOptimalWidth(width); - } -}; - -class GenericModel : public TreeModel<GenericItem, GenericItem> -{ - Q_OBJECT -public: - GenericModel(QObject *parent) : TreeModel(parent) { } - - void rebuild(const QList<QObject *> &objects) - { - clear(); - for (QObject * const e : objects) - addItemForObject(e); - } - - const GenericItem *addItemForObject(QObject *object) - { - const auto item = new GenericItem(object); - rootItem()->insertOrderedChild(item, &compareItems<GenericItem>); - if (const auto target = qobject_cast<Target *>(object)) { - connect(target, &Target::kitChanged, this, &GenericModel::displayNameChanged); - } else { - const auto pc = qobject_cast<ProjectConfiguration *>(object); - QTC_CHECK(pc); - connect(pc, &ProjectConfiguration::displayNameChanged, - this, &GenericModel::displayNameChanged); - connect(pc, &ProjectConfiguration::toolTipChanged, - this, &GenericModel::updateToolTips); - } - return item; - } - - void setColumnCount(int columns) { m_columnCount = columns; } - -signals: - void displayNameChanged(); - -private: - void updateToolTips() - { - emit dataChanged(index(0, 0), index(rowCount() - 1, 0), {Qt::ToolTipRole}); - } }; class GenericListWidget : public SelectorView @@ -363,7 +318,7 @@ public: const auto model = new GenericModel(this); connect(model, &GenericModel::displayNameChanged, this, [this, model] { const GenericItem * const activeItem = model->itemForIndex(currentIndex()); - model->rootItem()->sortChildren(&compareItems<GenericItem>); + model->rootItem()->sortChildren(&compareItems); resetOptimalWidth(); if (activeItem) setCurrentIndex(activeItem->index()); @@ -386,7 +341,7 @@ public: void setActiveProjectConfiguration(QObject *active) { - if (const GenericItem * const item = itemForObject(active)) + if (const GenericItem * const item = theModel()->itemForObject(active)) setCurrentIndex(item->index()); } @@ -405,7 +360,7 @@ public: void removeProjectConfiguration(QObject *pc) { const auto activeItem = theModel()->itemForIndex(currentIndex()); - if (GenericItem * const item = itemForObject(pc)) { + if (GenericItem * const item = theModel()->itemForObject(pc)) { theModel()->destroyItem(item); resetOptimalWidth(); if (activeItem && activeItem != item) @@ -413,8 +368,6 @@ public: } } - GenericModel *theModel() const { return static_cast<GenericModel *>(model()); } - private: void mousePressEvent(QMouseEvent *event) override { @@ -442,23 +395,6 @@ private: TreeView::mouseReleaseEvent(event); } - GenericItem *itemForObject(const QObject *object) - { - return theModel()->findItemAtLevel<1>([object](const GenericItem *item) { - return item->object() == object; - }); - } - - void resetOptimalWidth() - { - int width = 0; - QFontMetrics fn(font()); - theModel()->forItemsAtLevel<1>([this, &width, &fn](const GenericItem *item) { - width = qMax(fn.horizontalAdvance(item->displayName()) + padding(), width); - }); - setOptimalWidth(width); - } - QObject *objectAt(const QModelIndex &index) const { return theModel()->itemForIndex(index)->object(); @@ -1054,13 +990,8 @@ void MiniProjectTargetSelector::doLayout(bool keepSize) void MiniProjectTargetSelector::projectAdded(Project *project) { - connect(project, &Project::addedProjectConfiguration, - this, &MiniProjectTargetSelector::handleNewProjectConfiguration); connect(project, &Project::addedTarget, this, &MiniProjectTargetSelector::handleNewTarget); - - connect(project, &Project::removedProjectConfiguration, - this, &MiniProjectTargetSelector::handleRemovalOfProjectConfiguration); connect(project, &Project::removedTarget, this, &MiniProjectTargetSelector::handleRemovalOfTarget); @@ -1076,13 +1007,8 @@ void MiniProjectTargetSelector::projectAdded(Project *project) void MiniProjectTargetSelector::projectRemoved(Project *project) { - disconnect(project, &Project::addedProjectConfiguration, - this, &MiniProjectTargetSelector::handleNewProjectConfiguration); disconnect(project, &Project::addedTarget, this, &MiniProjectTargetSelector::handleNewTarget); - - disconnect(project, &Project::removedProjectConfiguration, - this, &MiniProjectTargetSelector::handleRemovalOfProjectConfiguration); disconnect(project, &Project::removedTarget, this, &MiniProjectTargetSelector::handleRemovalOfTarget); @@ -1105,25 +1031,6 @@ void MiniProjectTargetSelector::handleNewTarget(Target *target) updateRunListVisible(); } -void MiniProjectTargetSelector::handleNewProjectConfiguration(ProjectConfiguration *pc) -{ - if (auto bc = qobject_cast<BuildConfiguration *>(pc)) { - if (addedBuildConfiguration(bc)) - updateBuildListVisible(); - return; - } - if (auto dc = qobject_cast<DeployConfiguration *>(pc)) { - if (addedDeployConfiguration(dc)) - updateDeployListVisible(); - return; - } - if (auto rc = qobject_cast<RunConfiguration *>(pc)) { - if (addedRunConfiguration(rc)) - updateRunListVisible(); - return; - } -} - void MiniProjectTargetSelector::handleRemovalOfTarget(Target *target) { removedTarget(target); @@ -1134,25 +1041,6 @@ void MiniProjectTargetSelector::handleRemovalOfTarget(Target *target) updateRunListVisible(); } -void MiniProjectTargetSelector::handleRemovalOfProjectConfiguration(ProjectConfiguration *pc) -{ - if (auto bc = qobject_cast<BuildConfiguration *>(pc)) { - if (removedBuildConfiguration(bc)) - updateBuildListVisible(); - return; - } - if (auto dc = qobject_cast<DeployConfiguration *>(pc)) { - if (removedDeployConfiguration(dc)) - updateDeployListVisible(); - return; - } - if (auto rc = qobject_cast<RunConfiguration *>(pc)) { - if (removedRunConfiguration(rc)) - updateRunListVisible(); - return; - } -} - void MiniProjectTargetSelector::addedTarget(Target *target) { if (target->project() != m_project) @@ -1161,11 +1049,11 @@ void MiniProjectTargetSelector::addedTarget(Target *target) m_listWidgets[TARGET]->addProjectConfiguration(target); for (BuildConfiguration *bc : target->buildConfigurations()) - addedBuildConfiguration(bc); + addedBuildConfiguration(bc, false); for (DeployConfiguration *dc : target->deployConfigurations()) - addedDeployConfiguration(dc); + addedDeployConfiguration(dc, false); for (RunConfiguration *rc : target->runConfigurations()) - addedRunConfiguration(rc); + addedRunConfiguration(rc, false); } void MiniProjectTargetSelector::removedTarget(Target *target) @@ -1176,64 +1064,71 @@ void MiniProjectTargetSelector::removedTarget(Target *target) m_listWidgets[TARGET]->removeProjectConfiguration(target); for (BuildConfiguration *bc : target->buildConfigurations()) - removedBuildConfiguration(bc); + removedBuildConfiguration(bc, false); for (DeployConfiguration *dc : target->deployConfigurations()) - removedDeployConfiguration(dc); + removedDeployConfiguration(dc, false); for (RunConfiguration *rc : target->runConfigurations()) - removedRunConfiguration(rc); + removedRunConfiguration(rc, false); } -bool MiniProjectTargetSelector::addedBuildConfiguration(BuildConfiguration *bc) +void MiniProjectTargetSelector::addedBuildConfiguration(BuildConfiguration *bc, bool update) { - if (bc->target() != m_project->activeTarget()) - return false; + if (!m_project || bc->target() != m_project->activeTarget()) + return; m_listWidgets[BUILD]->addProjectConfiguration(bc); - return true; + if (update) + updateBuildListVisible(); } -bool MiniProjectTargetSelector::removedBuildConfiguration(BuildConfiguration *bc) +void MiniProjectTargetSelector::removedBuildConfiguration(BuildConfiguration *bc, bool update) { - if (bc->target() != m_project->activeTarget()) - return false; + if (!m_project || bc->target() != m_project->activeTarget()) + return; m_listWidgets[BUILD]->removeProjectConfiguration(bc); - return true; + if (update) + updateBuildListVisible(); } -bool MiniProjectTargetSelector::addedDeployConfiguration(DeployConfiguration *dc) +void MiniProjectTargetSelector::addedDeployConfiguration(DeployConfiguration *dc, bool update) { if (!m_project || dc->target() != m_project->activeTarget()) - return false; + return; m_listWidgets[DEPLOY]->addProjectConfiguration(dc); - return true; + if (update) + updateDeployListVisible(); } -bool MiniProjectTargetSelector::removedDeployConfiguration(DeployConfiguration *dc) +void MiniProjectTargetSelector::removedDeployConfiguration(DeployConfiguration *dc, bool update) { if (!m_project || dc->target() != m_project->activeTarget()) - return false; + return; m_listWidgets[DEPLOY]->removeProjectConfiguration(dc); - return true; + if (update) + updateDeployListVisible(); } -bool MiniProjectTargetSelector::addedRunConfiguration(RunConfiguration *rc) + +void MiniProjectTargetSelector::addedRunConfiguration(RunConfiguration *rc, bool update) { if (!m_project || rc->target() != m_project->activeTarget()) - return false; + return; m_listWidgets[RUN]->addProjectConfiguration(rc); - return true; + if (update) + updateRunListVisible(); } -bool MiniProjectTargetSelector::removedRunConfiguration(RunConfiguration *rc) +void MiniProjectTargetSelector::removedRunConfiguration(RunConfiguration *rc, bool update) { if (!m_project || rc->target() != m_project->activeTarget()) - return false; + return; m_listWidgets[RUN]->removeProjectConfiguration(rc); - return true; + if (update) + updateRunListVisible(); } void MiniProjectTargetSelector::updateProjectListVisible() diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.h b/src/plugins/projectexplorer/miniprojecttargetselector.h index e78d416089..b86845f59a 100644 --- a/src/plugins/projectexplorer/miniprojecttargetselector.h +++ b/src/plugins/projectexplorer/miniprojecttargetselector.h @@ -38,7 +38,6 @@ class Project; class Target; class BuildConfiguration; class DeployConfiguration; -class ProjectConfiguration; class RunConfiguration; namespace Internal { @@ -51,7 +50,8 @@ class MiniProjectTargetSelector : public QWidget Q_OBJECT public: - explicit MiniProjectTargetSelector(QAction *projectAction, QWidget *parent = nullptr); + explicit MiniProjectTargetSelector(QAction *projectAction, QWidget *parent); + void setVisible(bool visible) override; void keyPressEvent(QKeyEvent *ke) override; @@ -62,11 +62,10 @@ public: void nextOrShow(); private: + friend class ProjectExplorer::Target; void projectAdded(ProjectExplorer::Project *project); void projectRemoved(ProjectExplorer::Project *project); - void handleNewProjectConfiguration(ProjectExplorer::ProjectConfiguration *pc); void handleNewTarget(Target *target); - void handleRemovalOfProjectConfiguration(ProjectExplorer::ProjectConfiguration *pc); void handleRemovalOfTarget(Target *pc); void changeStartupProject(ProjectExplorer::Project *project); @@ -81,12 +80,12 @@ private: void switchToProjectsMode(); void addedTarget(Target *target); void removedTarget(Target *target); - bool addedBuildConfiguration(BuildConfiguration* bc); - bool removedBuildConfiguration(BuildConfiguration* bc); - bool addedDeployConfiguration(DeployConfiguration *dc); - bool removedDeployConfiguration(DeployConfiguration *dc); - bool addedRunConfiguration(RunConfiguration *rc); - bool removedRunConfiguration(RunConfiguration *rc); + void addedBuildConfiguration(BuildConfiguration *bc, bool update = true); + void removedBuildConfiguration(BuildConfiguration *bc, bool update = true); + void addedDeployConfiguration(DeployConfiguration *dc, bool update = true); + void removedDeployConfiguration(DeployConfiguration *dc, bool update = true); + void addedRunConfiguration(RunConfiguration *rc, bool update = true); + void removedRunConfiguration(RunConfiguration *rc, bool update = true); void updateProjectListVisible(); void updateTargetListVisible(); diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp index 9748b52f7f..53da86420e 100644 --- a/src/plugins/projectexplorer/msvctoolchain.cpp +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -67,7 +67,6 @@ using namespace Utils; static const char varsBatKeyC[] = KEY_ROOT "VarsBat"; static const char varsBatArgKeyC[] = KEY_ROOT "VarsBatArg"; static const char supportedAbiKeyC[] = KEY_ROOT "SupportedAbi"; -static const char supportedAbisKeyC[] = KEY_ROOT "SupportedAbis"; static const char environModsKeyC[] = KEY_ROOT "environmentModifications"; enum { debug = 0 }; @@ -775,55 +774,6 @@ void MsvcToolChain::updateEnvironmentModifications(Utils::EnvironmentItems modif } } -void MsvcToolChain::detectInstalledAbis() -{ - static QMap<QString, Abis> abiCache; - const QString vcVarsBase - = QDir::fromNativeSeparators(m_vcvarsBat).left(m_vcvarsBat.lastIndexOf('/')); - if (abiCache.contains(vcVarsBase)) { - m_supportedAbis = abiCache.value(vcVarsBase); - } else { - // Clear previously detected m_supportedAbis to repopulate it. - m_supportedAbis.clear(); - const Abi baseAbi = targetAbi(); - for (MsvcPlatform platform : platforms) { - bool toolchainInstalled = false; - QString perhapsVcVarsPath = vcVarsBase + QLatin1Char('/') + QLatin1String(platform.bat); - const Platform p = platform.platform; - if (QFileInfo(perhapsVcVarsPath).isFile()) { - toolchainInstalled = true; - } else { - // MSVC 2015 and below had various versions of vcvars scripts in subfolders. Try these - // as fallbacks. - perhapsVcVarsPath = vcVarsBase + platform.prefix + QLatin1Char('/') - + QLatin1String(platform.bat); - toolchainInstalled = QFileInfo(perhapsVcVarsPath).isFile(); - } - if (hostSupportsPlatform(platform.platform) && toolchainInstalled) { - Abi newAbi(archForPlatform(p), - baseAbi.os(), - baseAbi.osFlavor(), - baseAbi.binaryFormat(), - wordWidthForPlatform(p)); - if (!m_supportedAbis.contains(newAbi)) - m_supportedAbis.append(newAbi); - } - } - - abiCache.insert(vcVarsBase, m_supportedAbis); - } - - // Always add targetAbi in supportedAbis if it is empty. - // targetAbi is the abi with which the toolchain was detected. - // This is necessary for toolchains that don't have vcvars32.bat and the like in their - // vcVarsBase path, like msvc2010. - // Also, don't include that one in abiCache to avoid polluting it with values specific - // to one toolchain as the cache is global for a vcVarsBase path. For this reason, the - // targetAbi needs to be added manually. - if (m_supportedAbis.empty()) - m_supportedAbis.append(targetAbi()); -} - Utils::Environment MsvcToolChain::readEnvironmentSetting(const Utils::Environment &env) const { Utils::Environment resultEnv = env; @@ -862,7 +812,7 @@ MsvcToolChain::MsvcToolChain(Core::Id typeId) : ToolChain(typeId) { setDisplayName("Microsoft Visual C++ Compiler"); - setTypeDisplayName(MsvcToolChainFactory::tr("MSVC")); + setTypeDisplayName(tr("MSVC")); } void MsvcToolChain::inferWarningsForLevel(int warningLevel, WarningFlags &flags) @@ -894,11 +844,6 @@ Abi MsvcToolChain::targetAbi() const return m_abi; } -Abis MsvcToolChain::supportedAbis() const -{ - return m_supportedAbis; -} - void MsvcToolChain::setTargetAbi(const Abi &abi) { m_abi = abi; @@ -978,7 +923,6 @@ QVariantMap MsvcToolChain::toMap() const if (!m_varsBatArg.isEmpty()) data.insert(QLatin1String(varsBatArgKeyC), m_varsBatArg); data.insert(QLatin1String(supportedAbiKeyC), m_abi.toString()); - data.insert(supportedAbisKeyC, Utils::transform<QStringList>(m_supportedAbis, &Abi::toString)); Utils::EnvironmentItem::sort(&m_environmentModifications); data.insert(QLatin1String(environModsKeyC), Utils::EnvironmentItem::toVariantList(m_environmentModifications)); @@ -994,14 +938,6 @@ bool MsvcToolChain::fromMap(const QVariantMap &data) const QString abiString = data.value(QLatin1String(supportedAbiKeyC)).toString(); m_abi = Abi::fromString(abiString); - const QStringList abiList = data.value(supportedAbisKeyC).toStringList(); - m_supportedAbis.clear(); - for (const QString &a : abiList) { - Abi abi = Abi::fromString(a); - if (!abi.isValid()) - continue; - m_supportedAbis.append(abi); - } m_environmentModifications = Utils::EnvironmentItem::itemsFromVariantList( data.value(QLatin1String(environModsKeyC)).toList()); rescanForCompiler(); @@ -1011,11 +947,7 @@ bool MsvcToolChain::fromMap(const QVariantMap &data) m_vcvarsBat, m_varsBatArg)); - // supported Abis were not stored in the map in previous versions of the settings. Re-detect - if (m_supportedAbis.isEmpty()) - detectInstalledAbis(); - - const bool valid = !m_vcvarsBat.isEmpty() && m_abi.isValid() && !m_supportedAbis.isEmpty(); + const bool valid = !m_vcvarsBat.isEmpty() && m_abi.isValid(); if (valid) addToAvailableMsvcToolchains(this); @@ -1250,7 +1182,6 @@ void MsvcToolChain::setupVarsBat(const Abi &abi, const QString &varsBat, const Q m_varsBatArg = varsBatArg; if (!varsBat.isEmpty()) { - detectInstalledAbis(); initEnvModWatcher(Utils::runAsync(envModThreadPool(), &MsvcToolChain::environmentModifications, varsBat, @@ -1410,34 +1341,66 @@ void MsvcToolChainConfigWidget::setFromMsvcToolChain() m_abiWidget->setAbis(tc->supportedAbis(), tc->targetAbi()); } -void MsvcToolChainConfigWidget::handleVcVarsChange(const QString &vcVars) +void MsvcToolChainConfigWidget::updateAbis() { - const QString normalizedVcVars = QDir::fromNativeSeparators(vcVars); + const QString normalizedVcVars = QDir::fromNativeSeparators(m_varsBatPathCombo->currentText()); const auto *currentTc = static_cast<const MsvcToolChain *>(toolChain()); QTC_ASSERT(currentTc, return ); const MsvcToolChain::Platform platform = m_varsBatArchCombo->currentData().value<MsvcToolChain::Platform>(); const Abi::Architecture arch = archForPlatform(platform); const unsigned char wordWidth = wordWidthForPlatform(platform); + // Search the selected vcVars bat file in already detected MSVC compilers. + // For each variant of MSVC found, add its supported ABIs to the ABI widget so the user can + // choose one appropriately. + Abis supportedAbis; + Abi targetAbi; for (const MsvcToolChain *tc : g_availableMsvcToolchains) { if (tc->varsBat() == normalizedVcVars && tc->targetAbi().wordWidth() == wordWidth - && tc->targetAbi().architecture() == arch) { - m_abiWidget->setAbis(tc->supportedAbis(), tc->targetAbi()); - break; + && tc->targetAbi().architecture() == arch && tc->language() == currentTc->language()) { + // We need to filter out duplicates as there might be multiple toolchains with + // same abi (like x86, amd64_x86 for example). + for (const Abi &abi : tc->supportedAbis()) { + if (!supportedAbis.contains(abi)) + supportedAbis.append(abi); + } + targetAbi = tc->targetAbi(); + } + } + + // If we didn't find an exact match, try to find a fallback according to varsBat only. + // This can happen when the toolchain does not support user-selected arch/wordWidth. + if (!targetAbi.isValid()) { + const MsvcToolChain *tc = Utils::findOrDefault(g_availableMsvcToolchains, + [normalizedVcVars](const MsvcToolChain *tc) { + return tc->varsBat() == normalizedVcVars; + }); + if (tc) { + targetAbi = Abi(arch, + tc->targetAbi().os(), + tc->targetAbi().osFlavor(), + tc->targetAbi().binaryFormat(), + wordWidth); } } + + // Always set ABIs, even if none was found, to prevent stale data in the ABI widget. + // In that case, a custom ABI will be selected according to targetAbi. + m_abiWidget->setAbis(supportedAbis, targetAbi); + emit dirty(); } +void MsvcToolChainConfigWidget::handleVcVarsChange(const QString &) +{ + updateAbis(); +} + void MsvcToolChainConfigWidget::handleVcVarsArchChange(const QString &) { - Abi currentAbi = m_abiWidget->currentAbi(); - const MsvcToolChain::Platform platform = m_varsBatArchCombo->currentData().value<MsvcToolChain::Platform>(); - Abi newAbi(archForPlatform(platform), currentAbi.os(), currentAbi.osFlavor(), - currentAbi.binaryFormat(), wordWidthForPlatform(platform)); - if (currentAbi != newAbi) - m_abiWidget->setAbis(m_abiWidget->supportedAbis(), newAbi); - emit dirty(); + // supportedAbi list in the widget only contains matching ABIs to whatever arch was selected. + // We need to reupdate it from scratch with new arch parameters + updateAbis(); } QString MsvcToolChainConfigWidget::vcVarsArguments() const @@ -1784,7 +1747,7 @@ ClangClToolChain::BuiltInHeaderPathsRunner ClangClToolChain::createBuiltInHeader MsvcToolChainFactory::MsvcToolChainFactory() { - setDisplayName(tr("MSVC")); + setDisplayName(MsvcToolChain::tr("MSVC")); setSupportedToolChainType(Constants::MSVC_TOOLCHAIN_TYPEID); setSupportedLanguages({Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID}); setToolchainConstructor([] { return new MsvcToolChain(Constants::MSVC_TOOLCHAIN_TYPEID); }); @@ -1966,7 +1929,7 @@ QList<ToolChain *> MsvcToolChainFactory::autoDetect(const QList<ToolChain *> &al ClangClToolChainFactory::ClangClToolChainFactory() { - setDisplayName(tr("clang-cl")); + setDisplayName(ClangClToolChain::tr("clang-cl")); setSupportedLanguages({Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID}); setSupportedToolChainType(Constants::CLANG_CL_TOOLCHAIN_TYPEID); setToolchainConstructor([] { return new ClangClToolChain; }); diff --git a/src/plugins/projectexplorer/msvctoolchain.h b/src/plugins/projectexplorer/msvctoolchain.h index b224b4b68b..7eba087a19 100644 --- a/src/plugins/projectexplorer/msvctoolchain.h +++ b/src/plugins/projectexplorer/msvctoolchain.h @@ -53,6 +53,8 @@ namespace Internal { class MsvcToolChain : public ToolChain { + Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::Internal::MsvcToolChain) + public: enum Type { WindowsSDK, VS }; enum Platform { x86, amd64, x86_amd64, ia64, x86_ia64, arm, x86_arm, amd64_arm, amd64_x86 }; @@ -61,7 +63,6 @@ public: ~MsvcToolChain() override; Abi targetAbi() const override; - Abis supportedAbis() const override; void setTargetAbi(const Abi &abi); bool isValid() const override; @@ -146,7 +147,6 @@ protected: private: void updateEnvironmentModifications(Utils::EnvironmentItems modifications); void rescanForCompiler(); - void detectInstalledAbis(); mutable Utils::EnvironmentItems m_environmentModifications; mutable QFutureWatcher<GenerateEnvResult> m_envModWatcher; @@ -158,7 +158,6 @@ private: protected: Abi m_abi; - Abis m_supportedAbis; QString m_vcvarsBat; QString m_varsBatArg; // Argument @@ -166,6 +165,8 @@ protected: class PROJECTEXPLORER_EXPORT ClangClToolChain : public MsvcToolChain { + Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::Internal::ClangClToolChain) + public: ClangClToolChain(); @@ -202,8 +203,6 @@ private: class MsvcToolChainFactory : public ToolChainFactory { - Q_OBJECT - public: MsvcToolChainFactory(); @@ -218,8 +217,6 @@ public: class ClangClToolChainFactory : public ToolChainFactory { - Q_OBJECT - public: ClangClToolChainFactory(); @@ -271,6 +268,7 @@ private: void setFromMsvcToolChain(); + void updateAbis(); void handleVcVarsChange(const QString &vcVars); void handleVcVarsArchChange(const QString &arch); diff --git a/src/plugins/projectexplorer/processstep.cpp b/src/plugins/projectexplorer/processstep.cpp index c061eee1c1..02501150b5 100644 --- a/src/plugins/projectexplorer/processstep.cpp +++ b/src/plugins/projectexplorer/processstep.cpp @@ -24,28 +24,42 @@ ****************************************************************************/ #include "processstep.h" + +#include "abstractprocessstep.h" #include "buildconfiguration.h" -#include "buildstep.h" #include "kit.h" #include "processparameters.h" +#include "projectconfigurationaspects.h" #include "projectexplorerconstants.h" +#include "projectexplorer_export.h" #include "target.h" -#include <coreplugin/variablechooser.h> - #include <utils/fileutils.h> -#include <utils/macroexpander.h> - -#include <QFormLayout> using namespace Utils; namespace ProjectExplorer { +namespace Internal { const char PROCESS_COMMAND_KEY[] = "ProjectExplorer.ProcessStep.Command"; const char PROCESS_WORKINGDIRECTORY_KEY[] = "ProjectExplorer.ProcessStep.WorkingDirectory"; const char PROCESS_ARGUMENTS_KEY[] = "ProjectExplorer.ProcessStep.Arguments"; +class ProcessStep final : public AbstractProcessStep +{ + Q_DECLARE_TR_FUNCTIONS(ProjectExplorer::ProcessStep) + +public: + ProcessStep(BuildStepList *bsl, Core::Id id); + + bool init() final; + void setupProcessParameters(ProcessParameters *pp); + + BaseStringAspect *m_command; + BaseStringAspect *m_arguments; + BaseStringAspect *m_workingDirectory; +}; + ProcessStep::ProcessStep(BuildStepList *bsl, Core::Id id) : AbstractProcessStep(bsl, id) { @@ -92,26 +106,18 @@ bool ProcessStep::init() void ProcessStep::setupProcessParameters(ProcessParameters *pp) { - BuildConfiguration *bc = buildConfiguration(); - QString workingDirectory = m_workingDirectory->value(); - if (workingDirectory.isEmpty()) { - if (bc) - workingDirectory = Constants::DEFAULT_WORKING_DIR; - else - workingDirectory = Constants::DEFAULT_WORKING_DIR_ALTERNATE; - } - - pp->setMacroExpander(bc ? bc->macroExpander() : Utils::globalMacroExpander()); - pp->setEnvironment(bc ? bc->environment() : Utils::Environment::systemEnvironment()); - pp->setWorkingDirectory(Utils::FilePath::fromString(workingDirectory)); + if (workingDirectory.isEmpty()) + workingDirectory = fallbackWorkingDirectory(); + + pp->setMacroExpander(macroExpander()); + pp->setEnvironment(buildEnvironment()); + pp->setWorkingDirectory(FilePath::fromString(workingDirectory)); pp->setCommandLine({m_command->filePath(), m_arguments->value(), CommandLine::Raw}); pp->resolveAll(); } -//******* // ProcessStepFactory -//******* ProcessStepFactory::ProcessStepFactory() { @@ -119,4 +125,5 @@ ProcessStepFactory::ProcessStepFactory() setDisplayName(ProcessStep::tr("Custom Process Step", "item in combobox")); } +} // Internal } // ProjectExplorer diff --git a/src/plugins/projectexplorer/processstep.h b/src/plugins/projectexplorer/processstep.h index 95f0f49a22..964f0685db 100644 --- a/src/plugins/projectexplorer/processstep.h +++ b/src/plugins/projectexplorer/processstep.h @@ -25,33 +25,16 @@ #pragma once -#include "abstractprocessstep.h" -#include "projectconfigurationaspects.h" -#include "projectexplorer_export.h" +#include "buildstep.h" namespace ProjectExplorer { +namespace Internal { -class ProcessStepFactory : public BuildStepFactory +class ProcessStepFactory final : public BuildStepFactory { public: ProcessStepFactory(); }; -class PROJECTEXPLORER_EXPORT ProcessStep : public AbstractProcessStep -{ - Q_OBJECT - friend class ProcessStepFactory; - -public: - ProcessStep(BuildStepList *bsl, Core::Id id); - -private: - bool init() override; - void setupProcessParameters(ProcessParameters *pp); - - ProjectExplorer::BaseStringAspect *m_command; - ProjectExplorer::BaseStringAspect *m_arguments; - ProjectExplorer::BaseStringAspect *m_workingDirectory; -}; - +} // namespace Internal } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h index b6b65e6889..4974e64297 100644 --- a/src/plugins/projectexplorer/project.h +++ b/src/plugins/projectexplorer/project.h @@ -51,12 +51,10 @@ namespace ProjectExplorer { class BuildInfo; class BuildSystem; -class BuildConfiguration; class ContainerNode; class EditorConfiguration; class FolderNode; class Node; -class ProjectConfiguration; class ProjectImporter; class ProjectNode; class ProjectPrivate; @@ -183,9 +181,6 @@ signals: // Note: activeTarget can be 0 (if no targets are defined). void activeTargetChanged(ProjectExplorer::Target *target); - void removedProjectConfiguration(ProjectExplorer::ProjectConfiguration *pc); - void addedProjectConfiguration(ProjectExplorer::ProjectConfiguration *pc); - void aboutToRemoveTarget(ProjectExplorer::Target *target); void removedTarget(ProjectExplorer::Target *target); void addedTarget(ProjectExplorer::Target *target); diff --git a/src/plugins/projectexplorer/projectconfiguration.h b/src/plugins/projectexplorer/projectconfiguration.h index 3702655e16..0aa0e9f85e 100644 --- a/src/plugins/projectexplorer/projectconfiguration.h +++ b/src/plugins/projectexplorer/projectconfiguration.h @@ -29,7 +29,6 @@ #include <coreplugin/id.h> #include <utils/displayname.h> -#include <utils/macroexpander.h> #include <QObject> #include <QPointer> @@ -188,9 +187,6 @@ public: // Note: Make sure subclasses call the superclasses' toMap() function! virtual QVariantMap toMap() const; - Utils::MacroExpander *macroExpander() { return &m_macroExpander; } - const Utils::MacroExpander *macroExpander() const { return &m_macroExpander; } - Target *target() const; Project *project() const; @@ -221,7 +217,6 @@ private: const Core::Id m_id; Utils::DisplayName m_displayName; QString m_toolTip; - Utils::MacroExpander m_macroExpander; }; // helper function: diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 66b04ba4ef..440acf9cf0 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -519,6 +519,7 @@ public: QAction *m_openFileAction; QAction *m_projectTreeCollapseAllAction; QAction *m_projectTreeExpandAllAction; + QAction *m_projectTreeExpandNodeAction = nullptr; Utils::ParameterAction *m_closeProjectFilesActionFileMenu; Utils::ParameterAction *m_closeProjectFilesActionContextMenu; QAction *m_searchOnFileSystem; @@ -1361,7 +1362,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er dd->m_removeFileAction = new QAction(this); cmd = ActionManager::registerAction(dd->m_removeFileAction, Constants::REMOVEFILE, projectTreeContext); - cmd->setDefaultKeySequence(QKeySequence::Delete); + cmd->setDefaultKeySequences({QKeySequence::Delete, QKeySequence::Backspace}); mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER); // duplicate file action @@ -1380,7 +1381,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er dd->m_deleteFileAction = new QAction(tr("Delete File..."), this); cmd = ActionManager::registerAction(dd->m_deleteFileAction, Constants::DELETEFILE, projectTreeContext); - cmd->setDefaultKeySequence(QKeySequence::Delete); + cmd->setDefaultKeySequences({QKeySequence::Delete, QKeySequence::Backspace}); mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER); // renamefile action @@ -1412,6 +1413,13 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er // Collapse & Expand. const Id treeGroup = Constants::G_PROJECT_TREE; + + dd->m_projectTreeExpandNodeAction = new QAction(tr("Expand"), this); + connect(dd->m_projectTreeExpandNodeAction, &QAction::triggered, + ProjectTree::instance(), &ProjectTree::expandCurrentNodeRecursively); + Command * const expandNodeCmd = ActionManager::registerAction( + dd->m_projectTreeExpandNodeAction, "ProjectExplorer.ExpandNode", + projectTreeContext); dd->m_projectTreeCollapseAllAction = new QAction(tr("Collapse All"), this); Command * const collapseCmd = ActionManager::registerAction( dd->m_projectTreeCollapseAllAction, Constants::PROJECTTREE_COLLAPSE_ALL, @@ -1423,6 +1431,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er for (Core::ActionContainer * const ac : {mfileContextMenu, msubProjectContextMenu, mfolderContextMenu, mprojectContextMenu, msessionContextMenu}) { ac->addSeparator(treeGroup); + ac->addAction(expandNodeCmd, treeGroup); ac->addAction(collapseCmd, treeGroup); ac->addAction(expandCmd, treeGroup); } @@ -2350,6 +2359,11 @@ QThreadPool *ProjectExplorerPlugin::sharedThreadPool() return &(dd->m_threadPool); } +MiniProjectTargetSelector *ProjectExplorerPlugin::targetSelector() +{ + return dd->m_targetSelector; +} + /*! This function is connected to the ICore::coreOpened signal. If there was no session explicitly loaded, it creates an empty new diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h index 55870aefa1..afc84671cb 100644 --- a/src/plugins/projectexplorer/projectexplorer.h +++ b/src/plugins/projectexplorer/projectexplorer.h @@ -59,6 +59,7 @@ class FileNode; namespace Internal { class AppOutputSettings; +class MiniProjectTargetSelector; class ProjectExplorerSettings; } @@ -166,6 +167,7 @@ public: static QStringList projectFileGlobs(); static QThreadPool *sharedThreadPool(); + static Internal::MiniProjectTargetSelector *targetSelector(); static void showSessionManager(); static void openNewProjectDialog(); diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro index e9357a8e65..4f9b5dd4f7 100644 --- a/src/plugins/projectexplorer/projectexplorer.pro +++ b/src/plugins/projectexplorer/projectexplorer.pro @@ -105,7 +105,6 @@ HEADERS += projectexplorer.h \ projectexplorersettingspage.h \ baseprojectwizarddialog.h \ miniprojecttargetselector.h \ - buildenvironmentwidget.h \ ldparser.h \ lldparser.h \ linuxiccparser.h \ @@ -259,7 +258,6 @@ SOURCES += projectexplorer.cpp \ projectexplorersettingspage.cpp \ baseprojectwizarddialog.cpp \ miniprojecttargetselector.cpp \ - buildenvironmentwidget.cpp \ ldparser.cpp \ lldparser.cpp \ linuxiccparser.cpp \ diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs index a3d53a2262..6398533ca4 100644 --- a/src/plugins/projectexplorer/projectexplorer.qbs +++ b/src/plugins/projectexplorer/projectexplorer.qbs @@ -33,7 +33,6 @@ Project { "baseprojectwizarddialog.cpp", "baseprojectwizarddialog.h", "buildaspects.cpp", "buildaspects.h", "buildconfiguration.cpp", "buildconfiguration.h", - "buildenvironmentwidget.cpp", "buildenvironmentwidget.h", "buildinfo.cpp", "buildinfo.h", "buildmanager.cpp", "buildmanager.h", "buildprogress.cpp", "buildprogress.h", diff --git a/src/plugins/projectexplorer/projecttree.cpp b/src/plugins/projectexplorer/projecttree.cpp index 1ff829a061..fed383008d 100644 --- a/src/plugins/projectexplorer/projecttree.cpp +++ b/src/plugins/projectexplorer/projecttree.cpp @@ -154,7 +154,7 @@ void ProjectTree::update() ProjectTreeWidget *focus = m_focusForContextMenu; static QPointer<ProjectTreeWidget> lastFocusedProjectTreeWidget; if (!focus) { - focus = Utils::findOrDefault(m_projectTreeWidgets, &ProjectTree::hasFocus); + focus = currentWidget(); lastFocusedProjectTreeWidget = focus; } if (!focus) @@ -284,15 +284,21 @@ void ProjectTree::sessionAndTreeChanged() emit treeChanged(); } +void ProjectTree::expandCurrentNodeRecursively() +{ + if (const auto w = currentWidget()) + w->expandCurrentNodeRecursively(); +} + void ProjectTree::collapseAll() { - if (auto w = Utils::findOrDefault(s_instance->m_projectTreeWidgets, &ProjectTree::hasFocus)) + if (const auto w = currentWidget()) w->collapseAll(); } void ProjectTree::expandAll() { - if (auto w = Utils::findOrDefault(s_instance->m_projectTreeWidgets, &ProjectTree::hasFocus)) + if (const auto w = currentWidget()) w->expandAll(); } @@ -344,6 +350,11 @@ bool ProjectTree::hasFocus(ProjectTreeWidget *widget) || s_instance->m_focusForContextMenu == widget); } +ProjectTreeWidget *ProjectTree::currentWidget() const +{ + return findOrDefault(m_projectTreeWidgets, &ProjectTree::hasFocus); +} + void ProjectTree::showContextMenu(ProjectTreeWidget *focus, const QPoint &globalPos, Node *node) { QMenu *contextMenu = nullptr; diff --git a/src/plugins/projectexplorer/projecttree.h b/src/plugins/projectexplorer/projecttree.h index bf1335e5be..bedcb45862 100644 --- a/src/plugins/projectexplorer/projecttree.h +++ b/src/plugins/projectexplorer/projecttree.h @@ -82,6 +82,8 @@ public: static Project *projectForNode(const Node *node); static Node *nodeForFile(const Utils::FilePath &fileName); + void expandCurrentNodeRecursively(); + void collapseAll(); void expandAll(); @@ -117,6 +119,7 @@ private: void updateExternalFileWarning(); static bool hasFocus(Internal::ProjectTreeWidget *widget); + Internal::ProjectTreeWidget *currentWidget() const; void hideContextMenu(); private: diff --git a/src/plugins/projectexplorer/projecttreewidget.cpp b/src/plugins/projectexplorer/projecttreewidget.cpp index ddf1bdf496..cdd24622cd 100644 --- a/src/plugins/projectexplorer/projecttreewidget.cpp +++ b/src/plugins/projectexplorer/projecttreewidget.cpp @@ -432,6 +432,20 @@ void ProjectTreeWidget::setAutoSynchronization(bool sync) syncFromDocumentManager(); } +void ProjectTreeWidget::expandNodeRecursively(const QModelIndex &index) +{ + const int rc = index.model()->rowCount(index); + for (int i = 0; i < rc; ++i) + expandNodeRecursively(index.model()->index(i, index.column(), index)); + if (rc > 0) + m_view->expand(index); +} + +void ProjectTreeWidget::expandCurrentNodeRecursively() +{ + expandNodeRecursively(m_view->currentIndex()); +} + void ProjectTreeWidget::collapseAll() { m_view->collapseAll(); diff --git a/src/plugins/projectexplorer/projecttreewidget.h b/src/plugins/projectexplorer/projecttreewidget.h index e53396c4b9..aa612fdf7e 100644 --- a/src/plugins/projectexplorer/projecttreewidget.h +++ b/src/plugins/projectexplorer/projecttreewidget.h @@ -67,6 +67,7 @@ public: void toggleAutoSynchronization(); void editCurrentItem(); + void expandCurrentNodeRecursively(); void collapseAll(); void expandAll(); @@ -87,6 +88,8 @@ private: void syncFromDocumentManager(); + void expandNodeRecursively(const QModelIndex &index); + QTreeView *m_view = nullptr; FlatModel *m_model = nullptr; QAction *m_filterProjectsAction = nullptr; diff --git a/src/plugins/projectexplorer/rawprojectpart.cpp b/src/plugins/projectexplorer/rawprojectpart.cpp index 7e029c1ced..19eb7ab30f 100644 --- a/src/plugins/projectexplorer/rawprojectpart.cpp +++ b/src/plugins/projectexplorer/rawprojectpart.cpp @@ -155,8 +155,8 @@ KitInfo::KitInfo(Kit *kit) { // Toolchains if (kit) { - cToolChain = ToolChainKitAspect::toolChain(kit, Constants::C_LANGUAGE_ID); - cxxToolChain = ToolChainKitAspect::toolChain(kit, Constants::CXX_LANGUAGE_ID); + cToolChain = ToolChainKitAspect::cToolChain(kit); + cxxToolChain = ToolChainKitAspect::cxxToolChain(kit); } // Sysroot diff --git a/src/plugins/projectexplorer/removetaskhandler.cpp b/src/plugins/projectexplorer/removetaskhandler.cpp index b71b9b0556..b8abc22e11 100644 --- a/src/plugins/projectexplorer/removetaskhandler.cpp +++ b/src/plugins/projectexplorer/removetaskhandler.cpp @@ -42,7 +42,7 @@ QAction *RemoveTaskHandler::createAction(QObject *parent) const { QAction *removeAction = new QAction(tr("Remove", "Name of the action triggering the removetaskhandler"), parent); removeAction->setToolTip(tr("Remove task from the task list.")); - removeAction->setShortcut(QKeySequence(QKeySequence::Delete)); + removeAction->setShortcuts({QKeySequence::Delete, QKeySequence::Backspace}); removeAction->setShortcutContext(Qt::WidgetWithChildrenShortcut); return removeAction; } diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 36c988434d..b1128896f6 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -167,27 +167,26 @@ RunConfiguration::RunConfiguration(Target *target, Core::Id id) QTC_CHECK(target && target == this->target()); connect(target, &Target::parsingFinished, this, &RunConfiguration::update); - Utils::MacroExpander *expander = macroExpander(); - expander->setDisplayName(tr("Run Settings")); - expander->setAccumulating(true); - expander->registerSubProvider([target] { + m_expander.setDisplayName(tr("Run Settings")); + m_expander.setAccumulating(true); + m_expander.registerSubProvider([target] { BuildConfiguration *bc = target->activeBuildConfiguration(); return bc ? bc->macroExpander() : target->macroExpander(); }); - expander->registerPrefix("CurrentRun:Env", tr("Variables in the current run environment"), + m_expander.registerPrefix("CurrentRun:Env", tr("Variables in the current run environment"), [this](const QString &var) { const auto envAspect = aspect<EnvironmentAspect>(); return envAspect ? envAspect->environment().expandedValueForKey(var) : QString(); }); - expander->registerVariable(Constants::VAR_CURRENTRUN_WORKINGDIR, + m_expander.registerVariable(Constants::VAR_CURRENTRUN_WORKINGDIR, tr("The currently active run configuration's working directory"), - [this, expander] { + [this] { const auto wdAspect = aspect<WorkingDirectoryAspect>(); - return wdAspect ? wdAspect->workingDirectory(expander).toString() : QString(); + return wdAspect ? wdAspect->workingDirectory(&m_expander).toString() : QString(); }); - expander->registerVariable(Constants::VAR_CURRENTRUN_NAME, + m_expander.registerVariable(Constants::VAR_CURRENTRUN_NAME, QCoreApplication::translate("ProjectExplorer", "The currently active run configuration's name."), [this] { return displayName(); }, false); @@ -227,7 +226,7 @@ QWidget *RunConfiguration::createConfigurationWidget() } } - Core::VariableChooser::addSupportForChildWidgets(widget, macroExpander()); + Core::VariableChooser::addSupportForChildWidgets(widget, &m_expander); auto detailsWidget = new Utils::DetailsWidget; detailsWidget->setState(DetailsWidget::NoSummary); diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 017384a833..437d3f4ef0 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -33,6 +33,7 @@ #include "task.h" #include <utils/environment.h> +#include <utils/macroexpander.h> #include <utils/port.h> #include <QWidget> @@ -168,6 +169,8 @@ public: void update(); + const Utils::MacroExpander *macroExpander() const { return &m_expander; } + signals: void enabledChanged(); @@ -196,6 +199,7 @@ private: QString m_buildKey; CommandLineGetter m_commandLineGetter; Updater m_updater; + Utils::MacroExpander m_expander; }; class RunConfigurationCreationInfo diff --git a/src/plugins/projectexplorer/runcontrol.cpp b/src/plugins/projectexplorer/runcontrol.cpp index 1bd5d90f9a..37bf2f3c49 100644 --- a/src/plugins/projectexplorer/runcontrol.cpp +++ b/src/plugins/projectexplorer/runcontrol.cpp @@ -322,7 +322,7 @@ public: IDevice::ConstPtr device; Core::Id runMode; Utils::Icon icon; - MacroExpander *macroExpander; + const MacroExpander *macroExpander; QPointer<RunConfiguration> runConfiguration; // Not owned. Avoid use. QString buildKey; QMap<Core::Id, QVariantMap> settingsData; @@ -896,7 +896,7 @@ Kit *RunControl::kit() const return d->kit; } -MacroExpander *RunControl::macroExpander() const +const MacroExpander *RunControl::macroExpander() const { return d->macroExpander; } @@ -1214,12 +1214,12 @@ void SimpleTargetRunner::doStart(const Runnable &runnable, const IDevice::ConstP connect(&m_launcher, &ApplicationLauncher::remoteStderr, this, [this](const QString &output) { - appendMessage(output, Utils::StdErrFormatSameLine, false); + appendMessage(output, Utils::StdErrFormat, false); }); connect(&m_launcher, &ApplicationLauncher::remoteStdout, this, [this](const QString &output) { - appendMessage(output, Utils::StdOutFormatSameLine, false); + appendMessage(output, Utils::StdOutFormat, false); }); connect(&m_launcher, &ApplicationLauncher::finished, diff --git a/src/plugins/projectexplorer/runcontrol.h b/src/plugins/projectexplorer/runcontrol.h index 1ad3e26b27..cda6d6ab55 100644 --- a/src/plugins/projectexplorer/runcontrol.h +++ b/src/plugins/projectexplorer/runcontrol.h @@ -222,7 +222,7 @@ public: Target *target() const; Project *project() const; Kit *kit() const; - Utils::MacroExpander *macroExpander() const; + const Utils::MacroExpander *macroExpander() const; ProjectConfigurationAspect *aspect(Core::Id id) const; template <typename T> T *aspect() const { return runConfiguration() ? runConfiguration()->aspect<T>() : nullptr; diff --git a/src/plugins/projectexplorer/sessionview.cpp b/src/plugins/projectexplorer/sessionview.cpp index ab92ce16b8..49cd8b1486 100644 --- a/src/plugins/projectexplorer/sessionview.cpp +++ b/src/plugins/projectexplorer/sessionview.cpp @@ -152,7 +152,7 @@ void SessionView::showEvent(QShowEvent *event) void SessionView::keyPressEvent(QKeyEvent *event) { - if (event->key() != Qt::Key_Delete) { + if (event->key() != Qt::Key_Delete && event->key() != Qt::Key_Backspace) { TreeView::keyPressEvent(event); return; } diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp index b3f04c646f..96bff5606b 100644 --- a/src/plugins/projectexplorer/target.cpp +++ b/src/plugins/projectexplorer/target.cpp @@ -37,6 +37,7 @@ #include "kit.h" #include "kitinformation.h" #include "kitmanager.h" +#include "miniprojecttargetselector.h" #include "project.h" #include "projectexplorer.h" #include "projectexplorericons.h" @@ -46,8 +47,6 @@ #include <coreplugin/coreconstants.h> -#include <extensionsystem/pluginmanager.h> - #include <utils/algorithm.h> #include <utils/macroexpander.h> #include <utils/qtcassert.h> @@ -150,17 +149,16 @@ Target::Target(Project *project, Kit *k, _constructor_tag) : connect(km, &KitManager::kitUpdated, this, &Target::handleKitUpdates); connect(km, &KitManager::kitRemoved, this, &Target::handleKitRemoval); - Utils::MacroExpander *expander = macroExpander(); - expander->setDisplayName(tr("Target Settings")); - expander->setAccumulating(true); + d->m_macroExpander.setDisplayName(tr("Target Settings")); + d->m_macroExpander.setAccumulating(true); - expander->registerSubProvider([this] { return kit()->macroExpander(); }); + d->m_macroExpander.registerSubProvider([this] { return kit()->macroExpander(); }); - expander->registerVariable("sourceDir", tr("Source directory"), + d->m_macroExpander.registerVariable("sourceDir", tr("Source directory"), [project] { return project->projectDirectory().toUserOutput(); }); // Legacy support. - expander->registerVariable(Constants::VAR_CURRENTPROJECT_NAME, + d->m_macroExpander.registerVariable(Constants::VAR_CURRENTPROJECT_NAME, QCoreApplication::translate("ProjectExplorer", "Name of current project"), [project] { return project->displayName(); }, false); @@ -280,7 +278,7 @@ void Target::addBuildConfiguration(BuildConfiguration *bc) // add it d->m_buildConfigurations.push_back(bc); - project()->addedProjectConfiguration(bc); + ProjectExplorerPlugin::targetSelector()->addedBuildConfiguration(bc); emit addedBuildConfiguration(bc); d->m_buildConfigurationModel.addProjectConfiguration(bc); @@ -307,7 +305,7 @@ bool Target::removeBuildConfiguration(BuildConfiguration *bc) } emit removedBuildConfiguration(bc); - project()->removedProjectConfiguration(bc); + ProjectExplorerPlugin::targetSelector()->removedBuildConfiguration(bc); d->m_buildConfigurationModel.removeProjectConfiguration(bc); delete bc; @@ -349,7 +347,7 @@ void Target::addDeployConfiguration(DeployConfiguration *dc) // add it d->m_deployConfigurations.push_back(dc); - project()->addedProjectConfiguration(dc); + ProjectExplorerPlugin::targetSelector()->addedDeployConfiguration(dc); d->m_deployConfigurationModel.addProjectConfiguration(dc); emit addedDeployConfiguration(dc); @@ -377,7 +375,7 @@ bool Target::removeDeployConfiguration(DeployConfiguration *dc) SetActive::Cascade); } - project()->removedProjectConfiguration(dc); + ProjectExplorerPlugin::targetSelector()->removedDeployConfiguration(dc); d->m_deployConfigurationModel.removeProjectConfiguration(dc); emit removedDeployConfiguration(dc); @@ -428,7 +426,7 @@ void Target::addRunConfiguration(RunConfiguration *rc) d->m_runConfigurations.push_back(rc); - project()->addedProjectConfiguration(rc); + ProjectExplorerPlugin::targetSelector()->addedRunConfiguration(rc); d->m_runConfigurationModel.addProjectConfiguration(rc); emit addedRunConfiguration(rc); @@ -450,7 +448,7 @@ void Target::removeRunConfiguration(RunConfiguration *rc) } emit removedRunConfiguration(rc); - project()->removedProjectConfiguration(rc); + ProjectExplorerPlugin::targetSelector()->removedRunConfiguration(rc); d->m_runConfigurationModel.removeProjectConfiguration(rc); delete rc; diff --git a/src/plugins/projectexplorer/target.h b/src/plugins/projectexplorer/target.h index 1e31c47bda..652b5624a6 100644 --- a/src/plugins/projectexplorer/target.h +++ b/src/plugins/projectexplorer/target.h @@ -32,6 +32,8 @@ QT_FORWARD_DECLARE_CLASS(QIcon) +namespace Utils { class MacroExpander; } + namespace ProjectExplorer { class BuildConfiguration; class BuildTargetInfo; diff --git a/src/plugins/projectexplorer/task.cpp b/src/plugins/projectexplorer/task.cpp index 136d4db09a..aa39a85e3d 100644 --- a/src/plugins/projectexplorer/task.cpp +++ b/src/plugins/projectexplorer/task.cpp @@ -81,14 +81,6 @@ Task Task::compilerMissingTask() .arg(Core::Constants::IDE_DISPLAY_NAME)); } -Task Task::buildConfigurationMissingTask() -{ - return BuildSystemTask(Task::Error, - tr("%1 needs a build configuration set up to build. " - "Configure a build configuration in the project settings.") - .arg(Core::Constants::IDE_DISPLAY_NAME)); -} - void Task::setMark(TextEditor::TextMark *mark) { QTC_ASSERT(mark, return); diff --git a/src/plugins/projectexplorer/task.h b/src/plugins/projectexplorer/task.h index 8d17f086fb..6055dec43e 100644 --- a/src/plugins/projectexplorer/task.h +++ b/src/plugins/projectexplorer/task.h @@ -68,7 +68,6 @@ public: Options options = AddTextMark | FlashWorthy); static Task compilerMissingTask(); - static Task buildConfigurationMissingTask(); bool isNull() const; void clear(); diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h index 519239c1f0..d1a90a2104 100644 --- a/src/plugins/projectexplorer/toolchain.h +++ b/src/plugins/projectexplorer/toolchain.h @@ -193,13 +193,14 @@ private: friend class ToolChainFactory; }; -class PROJECTEXPLORER_EXPORT ToolChainFactory : public QObject +class PROJECTEXPLORER_EXPORT ToolChainFactory { - Q_OBJECT + ToolChainFactory(const ToolChainFactory &) = delete; + ToolChainFactory &operator=(const ToolChainFactory &) = delete; public: ToolChainFactory(); - ~ToolChainFactory() override; + virtual ~ToolChainFactory(); static const QList<ToolChainFactory *> allToolChainFactories(); diff --git a/src/plugins/python/pythonrunconfiguration.cpp b/src/plugins/python/pythonrunconfiguration.cpp index 1783b46930..1846c4b69e 100644 --- a/src/plugins/python/pythonrunconfiguration.cpp +++ b/src/plugins/python/pythonrunconfiguration.cpp @@ -71,15 +71,14 @@ public: } private: - void appendMessage(const QString &text, OutputFormat format) final + void doAppendMessage(const QString &text, OutputFormat format) final { - const bool isTrace = (format == StdErrFormat - || format == StdErrFormatSameLine) + const bool isTrace = format == StdErrFormat && (text.startsWith("Traceback (most recent call last):") || text.startsWith("\nTraceback (most recent call last):")); if (!isTrace) { - OutputFormatter::appendMessage(text, format); + OutputFormatter::doAppendMessage(text, format); return; } @@ -110,7 +109,7 @@ private: task.description += ' '; task.description += line.trimmed(); } - OutputFormatter::appendMessage('\n' + line, format); + OutputFormatter::doAppendMessage('\n' + line, format); } } if (!tasks.isEmpty()) { diff --git a/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp b/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp index 4f373b8ee3..9f0b648dc6 100644 --- a/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp +++ b/src/plugins/qbsprojectmanager/defaultpropertyprovider.cpp @@ -52,6 +52,8 @@ #include <QRegularExpression> #include <QSettings> +using namespace ProjectExplorer; + namespace QbsProjectManager { using namespace Constants; @@ -253,27 +255,24 @@ QVariantMap DefaultPropertyProvider::autoGeneratedProperties(const ProjectExplor { QVariantMap data = defaultData; - const QString sysroot = ProjectExplorer::SysRootKitAspect::sysRoot(k).toUserOutput(); + const QString sysroot = SysRootKitAspect::sysRoot(k).toUserOutput(); if (!sysroot.isEmpty()) data.insert(QLatin1String(QBS_SYSROOT), sysroot); - ProjectExplorer::ToolChain *tcC - = ProjectExplorer::ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::C_LANGUAGE_ID); - ProjectExplorer::ToolChain *tcCxx - = ProjectExplorer::ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID); + ToolChain *tcC = ToolChainKitAspect::cToolChain(k); + ToolChain *tcCxx = ToolChainKitAspect::cxxToolChain(k); if (!tcC && !tcCxx) return data; - ProjectExplorer::ToolChain *mainTc = tcCxx ? tcCxx : tcC; + ToolChain *mainTc = tcCxx ? tcCxx : tcC; - ProjectExplorer::Abi targetAbi = mainTc->targetAbi(); + Abi targetAbi = mainTc->targetAbi(); auto archs = architectures(mainTc); if (!archs.isEmpty()) data.insert(QLatin1String(QBS_ARCHITECTURES), archs); - if (mainTc->targetAbi() != - ProjectExplorer::Abi::abiFromTargetTriplet(mainTc->originalTargetTriple()) - || targetAbi.osFlavor() == ProjectExplorer::Abi::AndroidLinuxFlavor) { + if (mainTc->targetAbi() != Abi::abiFromTargetTriplet(mainTc->originalTargetTriple()) + || targetAbi.osFlavor() == Abi::AndroidLinuxFlavor) { data.insert(QLatin1String(QBS_ARCHITECTURE), architecture(mainTc->targetAbi())); } else if (archs.count() == 1) { data.insert(QLatin1String(QBS_ARCHITECTURE), archs.first()); @@ -281,8 +280,8 @@ QVariantMap DefaultPropertyProvider::autoGeneratedProperties(const ProjectExplor data.insert(QLatin1String(QBS_TARGETPLATFORM), targetPlatform(targetAbi, k)); QStringList toolchain = toolchainList(mainTc); - if (targetAbi.osFlavor() == ProjectExplorer::Abi::AndroidLinuxFlavor) { - const ProjectExplorer::IDevice::ConstPtr dev = ProjectExplorer::DeviceKitAspect::device(k); + if (targetAbi.osFlavor() == Abi::AndroidLinuxFlavor) { + const IDevice::ConstPtr dev = DeviceKitAspect::device(k); if (dev) { const QString sdkDir = k->value(Android::Constants::ANDROID_KIT_SDK).toString(); if (!sdkDir.isEmpty()) diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp index f2aac00591..eb6be29f10 100644 --- a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp +++ b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp @@ -311,11 +311,6 @@ QString QbsBuildConfiguration::equivalentCommandLine(const QbsBuildStepData &ste return commandLine.arguments(); } -bool QbsBuildConfiguration::isQmlDebuggingEnabled() const -{ - return qmlDebuggingSetting() == TriState::Enabled; -} - TriState QbsBuildConfiguration::qmlDebuggingSetting() const { return aspect<QtSupport::QmlDebuggingAspect>()->setting(); diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h index 96b66e2f47..4f9454ea1c 100644 --- a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h +++ b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h @@ -61,11 +61,6 @@ class QbsBuildConfiguration final : public ProjectExplorer::BuildConfiguration { Q_OBJECT - // used in DebuggerRunConfigurationAspect - Q_PROPERTY(bool linkQmlDebuggingLibrary - READ isQmlDebuggingEnabled - NOTIFY qbsConfigurationChanged) - friend class ProjectExplorer::BuildConfigurationFactory; QbsBuildConfiguration(ProjectExplorer::Target *target, Core::Id id); ~QbsBuildConfiguration() final; @@ -90,7 +85,6 @@ public: QString configurationName() const; QString equivalentCommandLine(const QbsBuildStepData &stepData) const; - bool isQmlDebuggingEnabled() const; ProjectExplorer::TriState qmlDebuggingSetting() const; ProjectExplorer::TriState qtQuickCompilerSetting() const; ProjectExplorer::TriState separateDebugInfoSetting() const; diff --git a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp index 9827cf672f..a47c1c972f 100644 --- a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp +++ b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp @@ -234,7 +234,7 @@ QVariantMap QbsBuildStep::qbsConfiguration(VariableHandling variableHandling) co Constants::QBS_CONFIG_QUICK_COMPILER_KEY); if (variableHandling == ExpandVariables) { - const MacroExpander * const expander = buildConfiguration()->macroExpander(); + const MacroExpander * const expander = macroExpander(); for (auto it = config.begin(), end = config.end(); it != end; ++it) { const QString rawString = it.value().toString(); const QString expandedString = expander->expand(rawString); @@ -273,7 +273,7 @@ Utils::FilePath QbsBuildStep::installRoot(VariableHandling variableHandling) con return Utils::FilePath::fromString(root); QString defaultInstallDir = QbsSettings::defaultInstallDirTemplate(); if (variableHandling == VariableHandling::ExpandVariables) - defaultInstallDir = buildConfiguration()->macroExpander()->expand(defaultInstallDir); + defaultInstallDir = macroExpander()->expand(defaultInstallDir); return FilePath::fromString(defaultInstallDir); } @@ -411,7 +411,7 @@ QString QbsBuildStep::buildVariant() const QbsBuildSystem *QbsBuildStep::qbsBuildSystem() const { - return static_cast<QbsBuildSystem *>(buildConfiguration()->buildSystem()); + return static_cast<QbsBuildSystem *>(buildSystem()); } void QbsBuildStep::setBuildVariant(const QString &variant) @@ -644,9 +644,7 @@ QbsBuildStepConfigWidget::QbsBuildStepConfigWidget(QbsBuildStep *step) : auto chooser = new Core::VariableChooser(this); chooser->addSupportedWidget(propertyEdit); chooser->addSupportedWidget(installDirChooser->lineEdit()); - chooser->addMacroExpanderProvider([step] { - return step->buildConfiguration()->macroExpander(); - }); + chooser->addMacroExpanderProvider([step] { return step->macroExpander(); }); propertyEdit->setValidationFunction([this](FancyLineEdit *edit, QString *errorMessage) { return validateProperties(edit, errorMessage); }); @@ -867,7 +865,7 @@ bool QbsBuildStepConfigWidget::validateProperties(Utils::FancyLineEdit *edit, QS } QList<Property> properties; - const MacroExpander * const expander = step()->buildConfiguration()->macroExpander(); + const MacroExpander * const expander = step()->macroExpander(); foreach (const QString &rawArg, argList) { int pos = rawArg.indexOf(':'); if (pos > 0) { diff --git a/src/plugins/qbsprojectmanager/qbsinstallstep.cpp b/src/plugins/qbsprojectmanager/qbsinstallstep.cpp index 371cf4c8d6..f3e3164e1e 100644 --- a/src/plugins/qbsprojectmanager/qbsinstallstep.cpp +++ b/src/plugins/qbsprojectmanager/qbsinstallstep.cpp @@ -109,7 +109,7 @@ QbsInstallStep::~QbsInstallStep() bool QbsInstallStep::init() { - QTC_ASSERT(!buildConfiguration()->buildSystem()->isParsing() && !m_session, return false); + QTC_ASSERT(!buildSystem()->isParsing() && !m_session, return false); return true; } diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index ed9488f7eb..f6c58a2bb1 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -49,8 +49,6 @@ #include <cpptools/cppprojectupdater.h> #include <cpptools/cpptoolsconstants.h> #include <cpptools/generatedcodemodelsupport.h> -#include <extensionsystem/pluginmanager.h> -#include <projectexplorer/buildenvironmentwidget.h> #include <projectexplorer/buildinfo.h> #include <projectexplorer/buildmanager.h> #include <projectexplorer/buildtargetinfo.h> @@ -79,6 +77,7 @@ #include <QJsonArray> #include <QMessageBox> #include <QSet> +#include <QTimer> #include <QVariantMap> #include <algorithm> @@ -209,7 +208,6 @@ QbsBuildSystem::QbsBuildSystem(QbsBuildConfiguration *bc) }); connect(m_session, &QbsSession::fileListUpdated, this, &QbsBuildSystem::delayParsing); - m_parsingDelay.setInterval(1000); // delay parsing by 1s. delayParsing(); connect(bc->project(), &Project::activeTargetChanged, @@ -218,8 +216,6 @@ QbsBuildSystem::QbsBuildSystem(QbsBuildConfiguration *bc) connect(bc->target(), &Target::activeBuildConfigurationChanged, this, &QbsBuildSystem::delayParsing); - connect(&m_parsingDelay, &QTimer::timeout, this, &QbsBuildSystem::triggerParsing); - connect(bc->project(), &Project::projectFileIsDirty, this, &QbsBuildSystem::delayParsing); updateProjectNodes({}); } @@ -593,7 +589,7 @@ void QbsBuildSystem::triggerParsing() void QbsBuildSystem::delayParsing() { if (m_buildConfiguration->isActive()) - m_parsingDelay.start(); + requestDelayedParse(); } void QbsBuildSystem::parseCurrentBuildConfiguration() @@ -631,7 +627,7 @@ void QbsBuildSystem::parseCurrentBuildConfiguration() prepareForParsing(); - m_parsingDelay.stop(); + cancelDelayedParseRequest(); QTC_ASSERT(!m_qbsProjectParser, return); m_qbsProjectParser = new QbsProjectParser(this, m_qbsUpdateFutureInterface); diff --git a/src/plugins/qbsprojectmanager/qbsproject.h b/src/plugins/qbsprojectmanager/qbsproject.h index 250d544e3b..7d4a027adf 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.h +++ b/src/plugins/qbsprojectmanager/qbsproject.h @@ -39,7 +39,6 @@ #include <QFutureWatcher> #include <QHash> #include <QJsonObject> -#include <QTimer> #include <functional> @@ -149,7 +148,6 @@ private: QSet<Core::IDocument *> m_qbsDocuments; QJsonObject m_projectData; // TODO: Perhaps store this in the root project node instead? - QTimer m_parsingDelay; QbsProjectParser *m_qbsProjectParser = nullptr; QFutureInterface<bool> *m_qbsUpdateFutureInterface = nullptr; using TreeCreationWatcher = QFutureWatcher<QbsProjectNode *>; diff --git a/src/plugins/qbsprojectmanager/qbsprojectimporter.cpp b/src/plugins/qbsprojectmanager/qbsprojectimporter.cpp index 8ff3371eef..06f9812169 100644 --- a/src/plugins/qbsprojectmanager/qbsprojectimporter.cpp +++ b/src/plugins/qbsprojectmanager/qbsprojectimporter.cpp @@ -165,10 +165,8 @@ bool QbsProjectImporter::matchKit(void *directoryData, const Kit *k) const && bgData->cxxCompilerPath.isEmpty()) { return true; } - const ToolChain * const cToolchain - = ToolChainKitAspect::toolChain(k, Constants::C_LANGUAGE_ID); - const ToolChain * const cxxToolchain - = ToolChainKitAspect::toolChain(k, Constants::CXX_LANGUAGE_ID); + const ToolChain * const cToolchain = ToolChainKitAspect::cToolChain(k); + const ToolChain * const cxxToolchain = ToolChainKitAspect::cxxToolChain(k); if (!bgData->cCompilerPath.isEmpty()) { if (!cToolchain) return false; diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp b/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp index e9f8e64ea3..d0da8a47e0 100644 --- a/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp +++ b/src/plugins/qbsprojectmanager/qbsprojectmanagerplugin.cpp @@ -542,17 +542,13 @@ void QbsProjectManagerPlugin::runStepsForProducts(QbsProject *project, bc->setChangedFiles(QStringList()); bc->setProducts(products); QList<ProjectExplorer::BuildStepList *> stepLists; - QStringList stepListNames; for (const Core::Id &stepType : stepTypes) { - if (stepType == ProjectExplorer::Constants::BUILDSTEPS_BUILD) { + if (stepType == ProjectExplorer::Constants::BUILDSTEPS_BUILD) stepLists << bc->buildSteps(); - stepListNames << ProjectExplorerPlugin::displayNameForStepId(stepType); - } else if (stepType == ProjectExplorer::Constants::BUILDSTEPS_CLEAN) { + else if (stepType == ProjectExplorer::Constants::BUILDSTEPS_CLEAN) stepLists << bc->cleanSteps(); - stepListNames << ProjectExplorerPlugin::displayNameForStepId(stepType); - } } - BuildManager::buildLists(stepLists, stepListNames); + BuildManager::buildLists(stepLists); bc->setProducts(QStringList()); } diff --git a/src/plugins/qmakeprojectmanager/CMakeLists.txt b/src/plugins/qmakeprojectmanager/CMakeLists.txt index 90d48c0347..f61d50d0c3 100644 --- a/src/plugins/qmakeprojectmanager/CMakeLists.txt +++ b/src/plugins/qmakeprojectmanager/CMakeLists.txt @@ -32,7 +32,6 @@ add_qtc_plugin(QmakeProjectManager qmakeparsernodes.cpp qmakeparsernodes.h qmakeproject.cpp qmakeproject.h qmakeprojectimporter.cpp qmakeprojectimporter.h - qmakeprojectmanager.cpp qmakeprojectmanager.h qmakeprojectmanager.qrc qmakeprojectmanager_global.h qmakeprojectmanagerconstants.h diff --git a/src/plugins/qmakeprojectmanager/customwidgetwizard/classlist.cpp b/src/plugins/qmakeprojectmanager/customwidgetwizard/classlist.cpp index 6c6a3ad7c6..1dcca7754c 100644 --- a/src/plugins/qmakeprojectmanager/customwidgetwizard/classlist.cpp +++ b/src/plugins/qmakeprojectmanager/customwidgetwizard/classlist.cpp @@ -147,6 +147,7 @@ void ClassList::removeCurrentClass() void ClassList::keyPressEvent(QKeyEvent *event) { switch (event->key()) { + case Qt::Key_Backspace: case Qt::Key_Delete: removeCurrentClass(); break; diff --git a/src/plugins/qmakeprojectmanager/profileeditor.cpp b/src/plugins/qmakeprojectmanager/profileeditor.cpp index a00e26d39e..6443af2635 100644 --- a/src/plugins/qmakeprojectmanager/profileeditor.cpp +++ b/src/plugins/qmakeprojectmanager/profileeditor.cpp @@ -30,8 +30,6 @@ #include "profilehoverhandler.h" #include "qmakenodes.h" #include "qmakeproject.h" -#include "qmakeprojectmanager.h" -#include "qmakeprojectmanagerconstants.h" #include "qmakeprojectmanagerconstants.h" #include <coreplugin/fileiconprovider.h> diff --git a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp index b44ae9fba3..632782b11d 100644 --- a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp +++ b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp @@ -424,11 +424,6 @@ TriState QmakeBuildConfiguration::qmlDebugging() const return aspect<QmlDebuggingAspect>()->setting(); } -bool QmakeBuildConfiguration::linkQmlDebuggingLibrary() const -{ - return qmlDebugging() == TriState::Enabled; -} - void QmakeBuildConfiguration::forceQmlDebugging(bool enable) { aspect<QmlDebuggingAspect>()->setSetting(enable ? TriState::Enabled : TriState::Disabled); @@ -829,7 +824,7 @@ QmakeBuildConfiguration::LastKitState::LastKitState(Kit *k) m_sysroot(SysRootKitAspect::sysRoot(k).toString()), m_mkspec(QmakeKitAspect::mkspec(k)) { - ToolChain *tc = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID); + ToolChain *tc = ToolChainKitAspect::cxxToolChain(k); m_toolchain = tc ? tc->id() : QByteArray(); } diff --git a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h index 53d92c3c59..058af3e796 100644 --- a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h +++ b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h @@ -44,9 +44,6 @@ class QMAKEPROJECTMANAGER_EXPORT QmakeBuildConfiguration : public ProjectExplore { Q_OBJECT - // used in DebuggerRunConfigurationAspect - Q_PROPERTY(bool linkQmlDebuggingLibrary READ linkQmlDebuggingLibrary NOTIFY qmlDebuggingChanged) - public: QmakeBuildConfiguration(ProjectExplorer::Target *target, Core::Id id); ~QmakeBuildConfiguration() override; @@ -103,7 +100,6 @@ public: void forceSeparateDebugInfo(bool sepDebugInfo); ProjectExplorer::TriState qmlDebugging() const; - bool linkQmlDebuggingLibrary() const; void forceQmlDebugging(bool enable); ProjectExplorer::TriState useQtQuickCompiler() const; diff --git a/src/plugins/qmakeprojectmanager/qmakekitinformation.cpp b/src/plugins/qmakeprojectmanager/qmakekitinformation.cpp index be619435b4..9333f75330 100644 --- a/src/plugins/qmakeprojectmanager/qmakekitinformation.cpp +++ b/src/plugins/qmakeprojectmanager/qmakekitinformation.cpp @@ -159,8 +159,7 @@ QString QmakeKitAspect::defaultMkspec(const Kit *k) if (!version) // No version, so no qmake return {}; - return version->mkspecFor(ToolChainKitAspect::toolChain(k, - ProjectExplorer::Constants::CXX_LANGUAGE_ID)); + return version->mkspecFor(ToolChainKitAspect::cxxToolChain(k)); } } // namespace Internal diff --git a/src/plugins/qmakeprojectmanager/qmakemakestep.cpp b/src/plugins/qmakeprojectmanager/qmakemakestep.cpp index 83809bc77a..dbf1ed2569 100644 --- a/src/plugins/qmakeprojectmanager/qmakemakestep.cpp +++ b/src/plugins/qmakeprojectmanager/qmakemakestep.cpp @@ -65,8 +65,6 @@ QmakeMakeStep::QmakeMakeStep(BuildStepList *bsl, Core::Id id) bool QmakeMakeStep::init() { const auto bc = static_cast<QmakeBuildConfiguration *>(buildConfiguration()); - if (!bc) - emit addTask(Task::buildConfigurationMissingTask()); const Utils::CommandLine unmodifiedMake = effectiveMakeCommand(Execution); const Utils::FilePath makeExecutable = unmodifiedMake.executable(); @@ -107,7 +105,7 @@ bool QmakeMakeStep::init() // for file builds, since the rules for that are // only in those files. if (subProFile->isDebugAndRelease() && bc->fileNodeBuild()) { - if (bc->buildType() == QmakeBuildConfiguration::Debug) + if (buildType() == QmakeBuildConfiguration::Debug) makefile += ".Debug"; else makefile += ".Release"; @@ -162,13 +160,12 @@ bool QmakeMakeStep::init() makeCmd.addArg(objectFile); } - pp->setEnvironment(environment(bc)); + pp->setEnvironment(makeEnvironment()); pp->setCommandLine(makeCmd); pp->resolveAll(); setOutputParser(new ProjectExplorer::GnuMakeParser()); - ToolChain *tc = ToolChainKitAspect::toolChain(target()->kit(), - ProjectExplorer::Constants::CXX_LANGUAGE_ID); + ToolChain *tc = ToolChainKitAspect::cxxToolChain(target()->kit()); if (tc && tc->targetAbi().os() == Abi::DarwinOS) appendOutputParser(new XcodebuildParser); IOutputParser *parser = target()->kit()->createOutputParser(); @@ -178,7 +175,7 @@ bool QmakeMakeStep::init() appendOutputParser(new QMakeParser); // make may cause qmake to be run, add last to make sure // it has a low priority. - auto rootNode = dynamic_cast<QmakeProFileNode *>(bc->project()->rootProjectNode()); + auto rootNode = dynamic_cast<QmakeProFileNode *>(project()->rootProjectNode()); QTC_ASSERT(rootNode, return false); m_scriptTarget = rootNode->projectType() == ProjectType::ScriptTemplate; m_unalignedBuildDir = !bc->isBuildDirAtSafeLocation(); diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.cpp b/src/plugins/qmakeprojectmanager/qmakenodes.cpp index 25397d92d6..a09fdc6afd 100644 --- a/src/plugins/qmakeprojectmanager/qmakenodes.cpp +++ b/src/plugins/qmakeprojectmanager/qmakenodes.cpp @@ -26,7 +26,7 @@ #include "qmakenodes.h" #include "qmakeproject.h" -#include "qmakeprojectmanager.h" +#include "qmakeprojectmanagerplugin.h" #include <projectexplorer/buildconfiguration.h> #include <projectexplorer/runconfiguration.h> @@ -342,7 +342,7 @@ bool QmakeProFileNode::validParse() const void QmakeProFileNode::build() { - QmakeManager::buildProduct(getProject(), this); + QmakeProjectManagerPlugin::buildProduct(getProject(), this); } QStringList QmakeProFileNode::targetApplications() const diff --git a/src/plugins/qmakeprojectmanager/qmakeparsernodes.h b/src/plugins/qmakeprojectmanager/qmakeparsernodes.h index c1029bde85..b30aafd6af 100644 --- a/src/plugins/qmakeprojectmanager/qmakeparsernodes.h +++ b/src/plugins/qmakeprojectmanager/qmakeparsernodes.h @@ -42,6 +42,8 @@ #include <memory> +namespace ProjectExplorer { class BuildConfiguration; } + namespace Utils { class FilePath; class FileSystemWatcher; @@ -50,7 +52,6 @@ class FileSystemWatcher; namespace QtSupport { class ProFileReader; } namespace QmakeProjectManager { -class QmakeBuildConfiguration; class QmakeBuildSystem; class QmakeProFile; class QmakeProject; diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index 8db751584c..15040d8f94 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -25,7 +25,6 @@ #include "qmakeproject.h" -#include "qmakeprojectmanager.h" #include "qmakeprojectimporter.h" #include "qmakebuildinfo.h" #include "qmakestep.h" @@ -74,6 +73,7 @@ #include <QDir> #include <QFileSystemWatcher> #include <QLoggingCategory> +#include <QTimer> using namespace QmakeProjectManager::Internal; using namespace ProjectExplorer; @@ -188,9 +188,7 @@ QmakeBuildSystem::QmakeBuildSystem(QmakeBuildConfiguration *bc) const QTextCodec *codec = Core::EditorManager::defaultTextCodec(); m_qmakeVfs->setTextCodec(codec); - m_asyncUpdateTimer.setSingleShot(true); - m_asyncUpdateTimer.setInterval(0); - connect(&m_asyncUpdateTimer, &QTimer::timeout, this, &QmakeBuildSystem::asyncUpdate); + setParseDelay(0); m_rootProFile = std::make_unique<QmakeProFile>(this, projectFilePath()); @@ -221,7 +219,7 @@ QmakeBuildSystem::QmakeBuildSystem(QmakeBuildConfiguration *bc) connect(ToolChainManager::instance(), &ToolChainManager::toolChainUpdated, this, [this](ToolChain *tc) { - if (ToolChainKitAspect::toolChain(kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID) == tc) + if (ToolChainKitAspect::cxxToolChain(kit()) == tc) scheduleUpdateAllNowOrLater(); }); @@ -498,13 +496,10 @@ void QmakeBuildSystem::startAsyncTimer(QmakeProFile::AsyncUpdateDelay delay) return; } - const int interval = qMin(m_asyncUpdateTimer.interval(), + const int interval = qMin(parseDelay(), delay == QmakeProFile::ParseLater ? UPDATE_INTERVAL : 0); qCDebug(qmakeBuildSystemLog) << __FUNCTION__ << interval; - - m_asyncUpdateTimer.stop(); - m_asyncUpdateTimer.setInterval(interval); - m_asyncUpdateTimer.start(); + requestParseWithCustomDelay(interval); } void QmakeBuildSystem::incrementPendingEvaluateFutures() @@ -565,7 +560,7 @@ bool QmakeBuildSystem::wasEvaluateCanceled() void QmakeBuildSystem::asyncUpdate() { - m_asyncUpdateTimer.setInterval(UPDATE_INTERVAL); + setParseDelay(UPDATE_INTERVAL); qCDebug(qmakeBuildSystemLog) << __FUNCTION__; if (m_invalidateQmakeVfsContents) { @@ -620,7 +615,7 @@ Tasks QmakeProject::projectIssues(const Kit *k) const result.append(createProjectTask(Task::TaskType::Error, tr("No Qt version set in kit."))); else if (!qtFromKit->isValid()) result.append(createProjectTask(Task::TaskType::Error, tr("Qt version is invalid."))); - if (!ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID)) + if (!ToolChainKitAspect::cxxToolChain(k)) result.append(createProjectTask(Task::TaskType::Error, tr("No C++ compiler set in kit."))); const QtSupport::BaseQtVersion *const qtThatContainsProject = projectIsPartOfQt(this); @@ -1132,7 +1127,7 @@ void QmakeBuildSystem::collectLibraryData(const QmakeProFile *file, DeploymentDa if (targetPath.isEmpty()) return; const Kit * const kit = target()->kit(); - const ToolChain * const toolchain = ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID); + const ToolChain * const toolchain = ToolChainKitAspect::cxxToolChain(kit); if (!toolchain) return; @@ -1280,16 +1275,16 @@ void QmakeBuildSystem::warnOnToolChainMismatch(const QmakeProFile *pro) const if (!bc) return; - testToolChain(ToolChainKitAspect::toolChain(t->kit(), ProjectExplorer::Constants::C_LANGUAGE_ID), + testToolChain(ToolChainKitAspect::cToolChain(t->kit()), getFullPathOf(pro, Variable::QmakeCc, bc)); - testToolChain(ToolChainKitAspect::toolChain(t->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID), + testToolChain(ToolChainKitAspect::cxxToolChain(t->kit()), getFullPathOf(pro, Variable::QmakeCxx, bc)); } QString QmakeBuildSystem::executableFor(const QmakeProFile *file) { const Kit *const kit = target()->kit(); - const ToolChain *const tc = ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID); + const ToolChain *const tc = ToolChainKitAspect::cxxToolChain(kit); if (!tc) return QString(); diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.h b/src/plugins/qmakeprojectmanager/qmakeproject.h index 9cd8902dbb..c25dfcc32d 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.h +++ b/src/plugins/qmakeprojectmanager/qmakeproject.h @@ -26,16 +26,15 @@ #pragma once #include "qmakeprojectmanager_global.h" -#include "qmakeprojectmanager.h" #include "qmakenodes.h" #include "qmakeparsernodes.h" #include <projectexplorer/deploymentdata.h> #include <projectexplorer/project.h> +#include <projectexplorer/toolchain.h> #include <QStringList> #include <QFutureInterface> -#include <QTimer> #include <QFuture> QT_BEGIN_NAMESPACE @@ -48,6 +47,7 @@ namespace ProjectExplorer { class DeploymentData; } namespace QtSupport { class ProFileReader; } namespace QmakeProjectManager { +class QmakeBuildConfiguration; namespace Internal { class CentralizedFolderWatcher; } @@ -188,7 +188,6 @@ public: QString m_qmakeSysroot; - QTimer m_asyncUpdateTimer; QFutureInterface<void> m_asyncUpdateFutureInterface; int m_pendingEvaluateFuturesCount = 0; AsyncUpdateState m_asyncUpdateState = Base; diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp index 71fd912e10..c4ef9ce815 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeprojectimporter.cpp @@ -206,7 +206,7 @@ bool QmakeProjectImporter::matchKit(void *directoryData, const Kit *k) const BaseQtVersion *kitVersion = QtKitAspect::qtVersion(k); QString kitSpec = QmakeKitAspect::mkspec(k); - ToolChain *tc = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID); + ToolChain *tc = ToolChainKitAspect::cxxToolChain(k); if (kitSpec.isEmpty() && kitVersion) kitSpec = kitVersion->mkspecFor(tc); QMakeStepConfig::TargetArchConfig kitTargetArch = QMakeStepConfig::NoArch; diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp deleted file mode 100644 index ba7b44b7d6..0000000000 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** 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 -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "qmakeprojectmanager.h" - -#include "qmakeprojectmanagerconstants.h" -#include "qmakeprojectmanagerplugin.h" -#include "qmakenodes.h" -#include "qmakeproject.h" -#include "profileeditor.h" -#include "qmakestep.h" -#include "qmakebuildconfiguration.h" -#include "addlibrarywizard.h" - -#include <coreplugin/icore.h> -#include <coreplugin/editormanager/editormanager.h> -#include <projectexplorer/projectexplorer.h> -#include <projectexplorer/projecttree.h> -#include <projectexplorer/buildmanager.h> -#include <projectexplorer/session.h> -#include <projectexplorer/target.h> -#include <utils/qtcassert.h> -#include <texteditor/texteditor.h> - -#include <QDir> -#include <QFileInfo> -#include <QVariant> - -using namespace ProjectExplorer; -using namespace TextEditor; - -namespace QmakeProjectManager { - -static QmakeProFileNode *buildableFileProFile(Node *node) -{ - if (node) { - auto subPriFileNode = dynamic_cast<QmakePriFileNode *>(node); - if (!subPriFileNode) - subPriFileNode = dynamic_cast<QmakePriFileNode *>(node->parentProjectNode()); - if (subPriFileNode) - return subPriFileNode->proFileNode(); - } - return nullptr; -} - -FileNode *QmakeManager::contextBuildableFileNode() -{ - Node *node = ProjectTree::currentNode(); - - QmakeProFileNode *subProjectNode = buildableFileProFile(node); - FileNode *fileNode = node ? node->asFileNode() : nullptr; - bool buildFilePossible = subProjectNode && fileNode - && (fileNode->fileType() == ProjectExplorer::FileType::Source); - - return buildFilePossible ? fileNode : nullptr; -} - -void QmakeManager::addLibrary() -{ - if (auto editor = qobject_cast<BaseTextEditor *>(Core::EditorManager::currentEditor())) - addLibraryImpl(editor->document()->filePath().toString(), editor); -} - -void QmakeManager::addLibraryContextMenu() -{ - QString projectPath; - - Node *node = ProjectTree::currentNode(); - if (ContainerNode *cn = node->asContainerNode()) - projectPath = cn->project()->projectFilePath().toString(); - else if (dynamic_cast<QmakeProFileNode *>(node)) - projectPath = node->filePath().toString(); - - addLibraryImpl(projectPath, nullptr); -} - -void QmakeManager::addLibraryImpl(const QString &fileName, BaseTextEditor *editor) -{ - if (fileName.isEmpty()) - return; - - Internal::AddLibraryWizard wizard(fileName, Core::ICore::dialogParent()); - if (wizard.exec() != QDialog::Accepted) - return; - - if (!editor) - editor = qobject_cast<BaseTextEditor *>(Core::EditorManager::openEditor(fileName, - Constants::PROFILE_EDITOR_ID, Core::EditorManager::DoNotMakeVisible)); - if (!editor) - return; - - const int endOfDoc = editor->position(EndOfDocPosition); - editor->setCursorPosition(endOfDoc); - QString snippet = wizard.snippet(); - - // add extra \n in case the last line is not empty - int line, column; - editor->convertPosition(endOfDoc, &line, &column); - const int positionInBlock = column - 1; - if (!editor->textAt(endOfDoc - positionInBlock, positionInBlock).simplified().isEmpty()) - snippet = QLatin1Char('\n') + snippet; - - editor->insert(snippet); -} - -void QmakeManager::runQMake() -{ - runQMakeImpl(SessionManager::startupProject(), nullptr); -} - -void QmakeManager::runQMakeContextMenu() -{ - runQMakeImpl(ProjectTree::currentProject(), ProjectTree::currentNode()); -} - -void QmakeManager::runQMakeImpl(ProjectExplorer::Project *p, ProjectExplorer::Node *node) -{ - if (!ProjectExplorerPlugin::saveModifiedFiles()) - return; - auto *qmakeProject = qobject_cast<QmakeProject *>(p); - QTC_ASSERT(qmakeProject, return); - - if (!qmakeProject->activeTarget() || !qmakeProject->activeTarget()->activeBuildConfiguration()) - return; - - auto *bc = static_cast<QmakeBuildConfiguration *>(qmakeProject->activeTarget()->activeBuildConfiguration()); - QMakeStep *qs = bc->qmakeStep(); - if (!qs) - return; - - //found qmakeStep, now use it - qs->setForced(true); - - if (node && node != qmakeProject->rootProjectNode()) - if (auto *profile = dynamic_cast<QmakeProFileNode *>(node)) - bc->setSubNodeBuild(profile); - - BuildManager::appendStep(qs, tr("QMake")); - bc->setSubNodeBuild(nullptr); -} - -void QmakeManager::buildSubDirContextMenu() -{ - handleSubDirContextMenu(BUILD, false); -} - -void QmakeManager::cleanSubDirContextMenu() -{ - handleSubDirContextMenu(CLEAN, false); -} - -void QmakeManager::rebuildSubDirContextMenu() -{ - handleSubDirContextMenu(REBUILD, false); -} - -void QmakeManager::buildFileContextMenu() -{ - handleSubDirContextMenu(BUILD, true); -} - -void QmakeManager::buildFile() -{ - if (Core::IDocument *currentDocument= Core::EditorManager::currentDocument()) { - const Utils::FilePath file = currentDocument->filePath(); - Node *n = ProjectTree::nodeForFile(file); - FileNode *node = n ? n->asFileNode() : nullptr; - Project *project = SessionManager::projectForFile(file); - - if (project && node) - handleSubDirContextMenu(BUILD, true, project, node->parentProjectNode(), node); - } -} - -void QmakeManager::buildProduct(Project *project, Node *proFileNode) -{ - handleSubDirContextMenu(BUILD, false, project, proFileNode, nullptr); -} - -void QmakeManager::handleSubDirContextMenu(QmakeManager::Action action, bool isFileBuild) -{ - handleSubDirContextMenu(action, - isFileBuild, - ProjectTree::currentProject(), - buildableFileProFile(ProjectTree::currentNode()), - contextBuildableFileNode()); -} - -void QmakeManager::handleSubDirContextMenu(QmakeManager::Action action, bool isFileBuild, - Project *contextProject, Node *contextNode, - FileNode *buildableFile) -{ - QTC_ASSERT(contextProject, return); - Target *target = contextProject->activeTarget(); - if (!target) - return; - - auto *bc = qobject_cast<QmakeBuildConfiguration *>(target->activeBuildConfiguration()); - if (!bc) - return; - - if (!contextNode || !buildableFile) - isFileBuild = false; - - if (auto *prifile = dynamic_cast<QmakePriFileNode *>(contextNode)) { - if (QmakeProFileNode *profile = prifile->proFileNode()) { - if (profile != contextProject->rootProjectNode() || isFileBuild) - bc->setSubNodeBuild(profile->proFileNode()); - } - } - - if (isFileBuild) - bc->setFileNodeBuild(buildableFile); - if (ProjectExplorerPlugin::saveModifiedFiles()) { - const Core::Id buildStep = ProjectExplorer::Constants::BUILDSTEPS_BUILD; - const Core::Id cleanStep = ProjectExplorer::Constants::BUILDSTEPS_CLEAN; - if (action == BUILD) { - BuildManager::buildList(bc->buildSteps()); - } else if (action == CLEAN) { - BuildManager::buildList(bc->cleanSteps()); - } else if (action == REBUILD) { - QStringList names; - names << ProjectExplorerPlugin::displayNameForStepId(cleanStep) - << ProjectExplorerPlugin::displayNameForStepId(buildStep); - - BuildManager::buildLists({bc->cleanSteps(), bc->buildSteps()}, names); - } - } - - bc->setSubNodeBuild(nullptr); - bc->setFileNodeBuild(nullptr); -} - -} // namespace QmakeProjectManager diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.h b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.h deleted file mode 100644 index 722ab07577..0000000000 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.h +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** 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 -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include "qmakeprojectmanager_global.h" - -#include <projectexplorer/projectnodes.h> - -namespace Core { class IEditor; } -namespace TextEditor { class BaseTextEditor; } - -namespace ProjectExplorer { -class Project; -class Node; -class ToolChain; -} - -namespace QmakeProjectManager { - -class QMAKEPROJECTMANAGER_EXPORT QmakeManager : public QObject -{ - Q_OBJECT - -public: - void notifyChanged(const Utils::FilePath &name); - - // Context information used in the slot implementations - static ProjectExplorer::FileNode *contextBuildableFileNode(); - - enum Action { BUILD, REBUILD, CLEAN }; - - void addLibrary(); - void addLibraryContextMenu(); - void runQMake(); - void runQMakeContextMenu(); - void buildSubDirContextMenu(); - void rebuildSubDirContextMenu(); - void cleanSubDirContextMenu(); - void buildFileContextMenu(); - void buildFile(); - - static void buildProduct(ProjectExplorer::Project *project, ProjectExplorer::Node *proFileNode); - -private: - void handleSubDirContextMenu(Action action, bool isFileBuild); - static void handleSubDirContextMenu(QmakeManager::Action action, bool isFileBuild, - ProjectExplorer::Project *contextProject, - ProjectExplorer::Node *contextProFileNode, - ProjectExplorer::FileNode *buildableFile); - void addLibraryImpl(const QString &fileName, TextEditor::BaseTextEditor *editor); - void runQMakeImpl(ProjectExplorer::Project *p, ProjectExplorer::Node *node); -}; - -} // namespace QmakeProjectManager diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro index aa56251ada..90a6a78a8f 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro @@ -10,7 +10,6 @@ HEADERS += \ qmakeparsernodes.h \ qmakeprojectimporter.h \ qmakeprojectmanagerplugin.h \ - qmakeprojectmanager.h \ qmakeproject.h \ qmakesettings.h \ qmakenodes.h \ @@ -39,7 +38,6 @@ SOURCES += \ qmakeparsernodes.cpp \ qmakeprojectimporter.cpp \ qmakeprojectmanagerplugin.cpp \ - qmakeprojectmanager.cpp \ qmakeproject.cpp \ qmakenodes.cpp \ qmakesettings.cpp \ diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs index 24a4fce431..e46f7c90b4 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs @@ -46,7 +46,6 @@ Project { "qmakenodes.cpp", "qmakenodes.h", "qmakenodetreebuilder.cpp", "qmakenodetreebuilder.h", "qmakeproject.cpp", "qmakeproject.h", - "qmakeprojectmanager.cpp", "qmakeprojectmanager.h", "qmakeprojectmanager.qrc", "qmakeprojectmanager_global.h", "qmakeprojectmanagerconstants.h", diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp index 6ca690f6f0..e1899418dd 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp @@ -25,8 +25,8 @@ #include "qmakeprojectmanagerplugin.h" +#include "addlibrarywizard.h" #include "profileeditor.h" -#include "qmakeprojectmanager.h" #include "qmakenodes.h" #include "qmakesettings.h" #include "qmakestep.h" @@ -49,12 +49,15 @@ #include <coreplugin/editormanager/ieditor.h> #include <projectexplorer/buildmanager.h> +#include <projectexplorer/projectnodes.h> #include <projectexplorer/projectmanager.h> #include <projectexplorer/projecttree.h> #include <projectexplorer/runcontrol.h> #include <projectexplorer/session.h> #include <projectexplorer/target.h> +#include <projectexplorer/projectexplorer.h> +#include <texteditor/texteditor.h> #include <texteditor/texteditoractionhandler.h> #include <texteditor/texteditorconstants.h> @@ -67,6 +70,7 @@ using namespace Core; using namespace ProjectExplorer; +using namespace TextEditor; namespace QmakeProjectManager { namespace Internal { @@ -86,7 +90,6 @@ public: void disableBuildFileMenus(); void enableBuildFileMenus(const Utils::FilePath &file); - QmakeManager qmakeProjectManager; Core::Context projectContext; CustomWizardMetaFactory<CustomQmakeProjectWizard> @@ -105,7 +108,7 @@ public: ExternalQtEditor *m_linguistEditor{ExternalQtEditor::createLinguistEditor()}; QmakeProject *m_previousStartupProject = nullptr; - ProjectExplorer::Target *m_previousTarget = nullptr; + Target *m_previousTarget = nullptr; QAction *m_runQMakeAction = nullptr; QAction *m_runQMakeActionContextMenu = nullptr; @@ -122,6 +125,26 @@ public: QAction *m_addLibraryActionContextMenu = nullptr; QmakeKitAspect qmakeKitAspect; + + enum Action { BUILD, REBUILD, CLEAN }; + + void addLibrary(); + void addLibraryContextMenu(); + void runQMake(); + void runQMakeContextMenu(); + void buildSubDirContextMenu(); + void rebuildSubDirContextMenu(); + void cleanSubDirContextMenu(); + void buildFileContextMenu(); + void buildFile(); + + void handleSubDirContextMenu(Action action, bool isFileBuild); + static void handleSubDirContextMenu(Action action, bool isFileBuild, + Project *contextProject, + Node *contextProFileNode, + FileNode *buildableFile); + void addLibraryImpl(const QString &fileName, TextEditor::BaseTextEditor *editor); + void runQMakeImpl(Project *p, ProjectExplorer::Node *node); }; QmakeProjectManagerPlugin::~QmakeProjectManagerPlugin() @@ -170,7 +193,7 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString command->setDescription(d->m_buildSubProjectContextMenu->text()); msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD); connect(d->m_buildSubProjectContextMenu, &QAction::triggered, - &d->qmakeProjectManager, &QmakeManager::buildSubDirContextMenu); + d, &QmakeProjectManagerPluginPrivate::buildSubDirContextMenu); d->m_runQMakeActionContextMenu = new QAction(tr("Run qmake"), this); command = ActionManager::registerAction(d->m_runQMakeActionContextMenu, Constants::RUNQMAKECONTEXTMENU, projectContext); @@ -178,7 +201,7 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString mproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD); msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD); connect(d->m_runQMakeActionContextMenu, &QAction::triggered, - &d->qmakeProjectManager, &QmakeManager::runQMakeContextMenu); + d, &QmakeProjectManagerPluginPrivate::runQMakeContextMenu); command = msubproject->addSeparator(projectContext, ProjectExplorer::Constants::G_PROJECT_BUILD, &d->m_subProjectRebuildSeparator); @@ -190,7 +213,7 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString command->setAttribute(Command::CA_Hide); msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD); connect(d->m_rebuildSubProjectContextMenu, &QAction::triggered, - &d->qmakeProjectManager, &QmakeManager::rebuildSubDirContextMenu); + d, &QmakeProjectManagerPluginPrivate::rebuildSubDirContextMenu); d->m_cleanSubProjectContextMenu = new QAction(tr("Clean"), this); command = ActionManager::registerAction( @@ -198,14 +221,14 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString command->setAttribute(Command::CA_Hide); msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD); connect(d->m_cleanSubProjectContextMenu, &QAction::triggered, - &d->qmakeProjectManager, &QmakeManager::cleanSubDirContextMenu); + d, &QmakeProjectManagerPluginPrivate::cleanSubDirContextMenu); d->m_buildFileContextMenu = new QAction(tr("Build"), this); command = ActionManager::registerAction(d->m_buildFileContextMenu, Constants::BUILDFILECONTEXTMENU, projectContext); command->setAttribute(Command::CA_Hide); mfile->addAction(command, ProjectExplorer::Constants::G_FILE_OTHER); connect(d->m_buildFileContextMenu, &QAction::triggered, - &d->qmakeProjectManager, &QmakeManager::buildFileContextMenu); + d, &QmakeProjectManagerPluginPrivate::buildFileContextMenu); d->m_buildSubProjectAction = new Utils::ParameterAction(tr("Build &Subproject"), tr("Build &Subproject \"%1\""), Utils::ParameterAction::AlwaysEnabled, this); @@ -215,13 +238,14 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString command->setDescription(d->m_buildSubProjectAction->text()); mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_BUILD); connect(d->m_buildSubProjectAction, &QAction::triggered, - &d->qmakeProjectManager, &QmakeManager::buildSubDirContextMenu); + d, &QmakeProjectManagerPluginPrivate::buildSubDirContextMenu); d->m_runQMakeAction = new QAction(tr("Run qmake"), this); const Context globalcontext(Core::Constants::C_GLOBAL); command = ActionManager::registerAction(d->m_runQMakeAction, Constants::RUNQMAKE, globalcontext); mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_BUILD); - connect(d->m_runQMakeAction, &QAction::triggered, &d->qmakeProjectManager, &QmakeManager::runQMake); + connect(d->m_runQMakeAction, &QAction::triggered, + d, &QmakeProjectManagerPluginPrivate::runQMake); d->m_rebuildSubProjectAction = new Utils::ParameterAction(tr("Rebuild Subproject"), tr("Rebuild Subproject \"%1\""), Utils::ParameterAction::AlwaysEnabled, this); @@ -231,7 +255,7 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString command->setDescription(d->m_rebuildSubProjectAction->text()); mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_REBUILD); connect(d->m_rebuildSubProjectAction, &QAction::triggered, - &d->qmakeProjectManager, &QmakeManager::rebuildSubDirContextMenu); + d, &QmakeProjectManagerPluginPrivate::rebuildSubDirContextMenu); d->m_cleanSubProjectAction = new Utils::ParameterAction(tr("Clean Subproject"), tr("Clean Subproject \"%1\""), Utils::ParameterAction::AlwaysEnabled, this); @@ -241,7 +265,7 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString command->setDescription(d->m_cleanSubProjectAction->text()); mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_CLEAN); connect(d->m_cleanSubProjectAction, &QAction::triggered, - &d->qmakeProjectManager, &QmakeManager::cleanSubDirContextMenu); + d, &QmakeProjectManagerPluginPrivate::cleanSubDirContextMenu); d->m_buildFileAction = new Utils::ParameterAction(tr("Build File"), tr("Build File \"%1\""), Utils::ParameterAction::AlwaysEnabled, this); @@ -251,7 +275,8 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString command->setDescription(d->m_buildFileAction->text()); command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+B"))); mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_BUILD); - connect(d->m_buildFileAction, &QAction::triggered, &d->qmakeProjectManager, &QmakeManager::buildFile); + connect(d->m_buildFileAction, &QAction::triggered, + d, &QmakeProjectManagerPluginPrivate::buildFile); connect(BuildManager::instance(), &BuildManager::buildStateChanged, d, &QmakeProjectManagerPluginPrivate::buildStateChanged); @@ -273,14 +298,15 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString d->m_addLibraryAction = new QAction(tr("Add Library..."), this); command = ActionManager::registerAction(d->m_addLibraryAction, Constants::ADDLIBRARY, proFileEditorContext); - connect(d->m_addLibraryAction, &QAction::triggered, &d->qmakeProjectManager, &QmakeManager::addLibrary); + connect(d->m_addLibraryAction, &QAction::triggered, + d, &QmakeProjectManagerPluginPrivate::addLibrary); contextMenu->addAction(command); d->m_addLibraryActionContextMenu = new QAction(tr("Add Library..."), this); command = ActionManager::registerAction(d->m_addLibraryActionContextMenu, Constants::ADDLIBRARY, projectTreeContext); connect(d->m_addLibraryActionContextMenu, &QAction::triggered, - &d->qmakeProjectManager, &QmakeManager::addLibraryContextMenu); + d, &QmakeProjectManagerPluginPrivate::addLibraryContextMenu); mproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_FILES); msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_FILES); @@ -322,6 +348,196 @@ void QmakeProjectManagerPluginPrivate::projectChanged() activeTargetChanged(); } +static QmakeProFileNode *buildableFileProFile(Node *node) +{ + if (node) { + auto subPriFileNode = dynamic_cast<QmakePriFileNode *>(node); + if (!subPriFileNode) + subPriFileNode = dynamic_cast<QmakePriFileNode *>(node->parentProjectNode()); + if (subPriFileNode) + return subPriFileNode->proFileNode(); + } + return nullptr; +} + +void QmakeProjectManagerPluginPrivate::addLibrary() +{ + if (auto editor = qobject_cast<BaseTextEditor *>(Core::EditorManager::currentEditor())) + addLibraryImpl(editor->document()->filePath().toString(), editor); +} + +void QmakeProjectManagerPluginPrivate::addLibraryContextMenu() +{ + QString projectPath; + + Node *node = ProjectTree::currentNode(); + if (ContainerNode *cn = node->asContainerNode()) + projectPath = cn->project()->projectFilePath().toString(); + else if (dynamic_cast<QmakeProFileNode *>(node)) + projectPath = node->filePath().toString(); + + addLibraryImpl(projectPath, nullptr); +} + +void QmakeProjectManagerPluginPrivate::addLibraryImpl(const QString &fileName, BaseTextEditor *editor) +{ + if (fileName.isEmpty()) + return; + + Internal::AddLibraryWizard wizard(fileName, Core::ICore::dialogParent()); + if (wizard.exec() != QDialog::Accepted) + return; + + if (!editor) + editor = qobject_cast<BaseTextEditor *>(Core::EditorManager::openEditor(fileName, + Constants::PROFILE_EDITOR_ID, Core::EditorManager::DoNotMakeVisible)); + if (!editor) + return; + + const int endOfDoc = editor->position(EndOfDocPosition); + editor->setCursorPosition(endOfDoc); + QString snippet = wizard.snippet(); + + // add extra \n in case the last line is not empty + int line, column; + editor->convertPosition(endOfDoc, &line, &column); + const int positionInBlock = column - 1; + if (!editor->textAt(endOfDoc - positionInBlock, positionInBlock).simplified().isEmpty()) + snippet = QLatin1Char('\n') + snippet; + + editor->insert(snippet); +} + +void QmakeProjectManagerPluginPrivate::runQMake() +{ + runQMakeImpl(SessionManager::startupProject(), nullptr); +} + +void QmakeProjectManagerPluginPrivate::runQMakeContextMenu() +{ + runQMakeImpl(ProjectTree::currentProject(), ProjectTree::currentNode()); +} + +void QmakeProjectManagerPluginPrivate::runQMakeImpl(Project *p, Node *node) +{ + if (!ProjectExplorerPlugin::saveModifiedFiles()) + return; + auto *qmakeProject = qobject_cast<QmakeProject *>(p); + QTC_ASSERT(qmakeProject, return); + + if (!qmakeProject->activeTarget() || !qmakeProject->activeTarget()->activeBuildConfiguration()) + return; + + auto *bc = static_cast<QmakeBuildConfiguration *>(qmakeProject->activeTarget()->activeBuildConfiguration()); + QMakeStep *qs = bc->qmakeStep(); + if (!qs) + return; + + //found qmakeStep, now use it + qs->setForced(true); + + if (node && node != qmakeProject->rootProjectNode()) + if (auto *profile = dynamic_cast<QmakeProFileNode *>(node)) + bc->setSubNodeBuild(profile); + + BuildManager::appendStep(qs, tr("QMake")); + bc->setSubNodeBuild(nullptr); +} + +void QmakeProjectManagerPluginPrivate::buildSubDirContextMenu() +{ + handleSubDirContextMenu(BUILD, false); +} + +void QmakeProjectManagerPluginPrivate::cleanSubDirContextMenu() +{ + handleSubDirContextMenu(CLEAN, false); +} + +void QmakeProjectManagerPluginPrivate::rebuildSubDirContextMenu() +{ + handleSubDirContextMenu(REBUILD, false); +} + +void QmakeProjectManagerPluginPrivate::buildFileContextMenu() +{ + handleSubDirContextMenu(BUILD, true); +} + +void QmakeProjectManagerPluginPrivate::buildFile() +{ + if (Core::IDocument *currentDocument= Core::EditorManager::currentDocument()) { + const Utils::FilePath file = currentDocument->filePath(); + Node *n = ProjectTree::nodeForFile(file); + FileNode *node = n ? n->asFileNode() : nullptr; + Project *project = SessionManager::projectForFile(file); + + if (project && node) + handleSubDirContextMenu(BUILD, true, project, buildableFileProFile(node), node); + } +} + +void QmakeProjectManagerPlugin::buildProduct(Project *project, Node *proFileNode) +{ + QmakeProjectManagerPluginPrivate::handleSubDirContextMenu( + QmakeProjectManagerPluginPrivate::BUILD, false, project, proFileNode, nullptr); +} + +void QmakeProjectManagerPluginPrivate::handleSubDirContextMenu(Action action, bool isFileBuild) +{ + Node *node = ProjectTree::currentNode(); + + QmakeProFileNode *subProjectNode = buildableFileProFile(node); + FileNode *fileNode = node ? node->asFileNode() : nullptr; + bool buildFilePossible = subProjectNode && fileNode && fileNode->fileType() == FileType::Source; + + FileNode *buildableFileNode = buildFilePossible ? fileNode : nullptr; + + handleSubDirContextMenu(action, + isFileBuild, + ProjectTree::currentProject(), + buildableFileProFile(ProjectTree::currentNode()), + buildableFileNode); +} + +void QmakeProjectManagerPluginPrivate::handleSubDirContextMenu(Action action, bool isFileBuild, + Project *contextProject, Node *contextNode, + FileNode *buildableFile) +{ + QTC_ASSERT(contextProject, return); + Target *target = contextProject->activeTarget(); + if (!target) + return; + + auto *bc = qobject_cast<QmakeBuildConfiguration *>(target->activeBuildConfiguration()); + if (!bc) + return; + + if (!contextNode || !buildableFile) + isFileBuild = false; + + if (auto *prifile = dynamic_cast<QmakePriFileNode *>(contextNode)) { + if (QmakeProFileNode *profile = prifile->proFileNode()) { + if (profile != contextProject->rootProjectNode() || isFileBuild) + bc->setSubNodeBuild(profile->proFileNode()); + } + } + + if (isFileBuild) + bc->setFileNodeBuild(buildableFile); + if (ProjectExplorerPlugin::saveModifiedFiles()) { + if (action == BUILD) + BuildManager::buildList(bc->buildSteps()); + else if (action == CLEAN) + BuildManager::buildList(bc->cleanSteps()); + else if (action == REBUILD) + BuildManager::buildLists({bc->cleanSteps(), bc->buildSteps()}); + } + + bc->setSubNodeBuild(nullptr); + bc->setFileNodeBuild(nullptr); +} + void QmakeProjectManagerPluginPrivate::activeTargetChanged() { if (m_previousTarget) diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.h b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.h index 5b3176b9b7..1d11bb45cb 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.h +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.h @@ -27,6 +27,11 @@ #include <extensionsystem/iplugin.h> +namespace ProjectExplorer { +class Project; +class Node; +} // ProjectExplorer + namespace QmakeProjectManager { namespace Internal { @@ -38,6 +43,8 @@ class QmakeProjectManagerPlugin final : public ExtensionSystem::IPlugin public: ~QmakeProjectManagerPlugin() final; + static void buildProduct(ProjectExplorer::Project *project, ProjectExplorer::Node *proFileNode); + #ifdef WITH_TESTS private slots: void testQmakeOutputParsers_data(); diff --git a/src/plugins/qmakeprojectmanager/qmakestep.cpp b/src/plugins/qmakeprojectmanager/qmakestep.cpp index 0c73586938..7bee09695f 100644 --- a/src/plugins/qmakeprojectmanager/qmakestep.cpp +++ b/src/plugins/qmakeprojectmanager/qmakestep.cpp @@ -141,16 +141,14 @@ QString QMakeStep::allArguments(const BaseQtVersion *v, ArgumentFlags flags) con QMakeStepConfig QMakeStep::deducedArguments() const { - ProjectExplorer::Kit *kit = target()->kit(); + Kit *kit = target()->kit(); QMakeStepConfig config; - ProjectExplorer::ToolChain *tc - = ProjectExplorer::ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID); - ProjectExplorer::Abi targetAbi; - if (tc) { + Abi targetAbi; + if (ToolChain *tc = ToolChainKitAspect::cxxToolChain(kit)) { targetAbi = tc->targetAbi(); if (HostOsInfo::isWindowsHost() && tc->typeId() == ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID) { - config.sysRoot = ProjectExplorer::SysRootKitAspect::sysRoot(kit).toString(); + config.sysRoot = SysRootKitAspect::sysRoot(kit).toString(); config.targetTriple = tc->originalTargetTriple(); } } @@ -571,14 +569,8 @@ QMakeStepConfigWidget::QMakeStepConfigWidget(QMakeStep *step) connect(step->target(), &Target::kitChanged, this, &QMakeStepConfigWidget::qtVersionChanged); connect(abisListWidget, &QListWidget::itemChanged, this, [this]{ abisChanged(); - QmakeBuildConfiguration *bc = m_step->qmakeBuildConfiguration(); - if (!bc) - return; - - QList<ProjectExplorer::BuildStepList *> stepLists; - const Core::Id clean = ProjectExplorer::Constants::BUILDSTEPS_CLEAN; - stepLists << bc->cleanSteps(); - BuildManager::buildLists(stepLists, {ProjectExplorerPlugin::displayNameForStepId(clean)}); + if (QmakeBuildConfiguration *bc = m_step->qmakeBuildConfiguration()) + BuildManager::buildLists({bc->cleanSteps()}); }); auto chooser = new Core::VariableChooser(qmakeAdditonalArgumentsLineEdit); chooser->addMacroExpanderProvider([step] { return step->macroExpander(); }); @@ -751,15 +743,8 @@ void QMakeStepConfigWidget::updateEffectiveQMakeCall() void QMakeStepConfigWidget::recompileMessageBoxFinished(int button) { if (button == QMessageBox::Yes) { - BuildConfiguration *bc = m_step->buildConfiguration(); - if (!bc) - return; - - const Core::Id clean = ProjectExplorer::Constants::BUILDSTEPS_CLEAN; - const Core::Id build = ProjectExplorer::Constants::BUILDSTEPS_BUILD; - BuildManager::buildLists({bc->cleanSteps(), bc->buildSteps()}, - QStringList() << ProjectExplorerPlugin::displayNameForStepId(clean) - << ProjectExplorerPlugin::displayNameForStepId(build)); + if (BuildConfiguration *bc = m_step->buildConfiguration()) + BuildManager::buildLists({bc->cleanSteps(), bc->buildSteps()}); } } diff --git a/src/plugins/qmakeprojectmanager/wizards/qtwizard.cpp b/src/plugins/qmakeprojectmanager/wizards/qtwizard.cpp index 38074cb0c6..f9d66de3ed 100644 --- a/src/plugins/qmakeprojectmanager/wizards/qtwizard.cpp +++ b/src/plugins/qmakeprojectmanager/wizards/qtwizard.cpp @@ -26,7 +26,6 @@ #include "qtwizard.h" #include <qmakeprojectmanager/qmakeproject.h> -#include <qmakeprojectmanager/qmakeprojectmanager.h> #include <qmakeprojectmanager/qmakeprojectmanagerconstants.h> #include <coreplugin/icore.h> diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.cpp b/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.cpp index 10b6876949..c119dfdca1 100644 --- a/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.cpp +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.cpp @@ -138,14 +138,16 @@ void AnnotationEditor::removeFullAnnotation() if (!m_modelNode.customId().isNull()) { dialogTitle = m_modelNode.customId(); } - QMessageBox *deleteDialog = new QMessageBox(Core::ICore::dialogParent()); + QPointer<QMessageBox> deleteDialog = new QMessageBox(Core::ICore::dialogParent()); deleteDialog->setWindowTitle(dialogTitle); deleteDialog->setText(tr("Delete this annotation?")); deleteDialog->setStandardButtons(QMessageBox::Yes | QMessageBox::No); deleteDialog->setDefaultButton(QMessageBox::Yes); int result = deleteDialog->exec(); - if (deleteDialog) deleteDialog->deleteLater(); + + if (deleteDialog) + deleteDialog->deleteLater(); if (result == QMessageBox::Yes) { m_modelNode.removeCustomId(); diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp index ae4532f1f1..1163af6c58 100644 --- a/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp +++ b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.cpp @@ -58,7 +58,6 @@ ConnectionViewWidget::ConnectionViewWidget(QWidget *parent) : ui(new Ui::ConnectionViewWidget) { m_actionEditor = new QmlDesigner::ActionEditor(this); - m_deleteShortcut = new QShortcut(this); QObject::connect(m_actionEditor, &QmlDesigner::ActionEditor::accepted, [&]() { if (m_actionEditor->hasModelIndex()) { @@ -125,7 +124,6 @@ ConnectionViewWidget::~ConnectionViewWidget() { delete m_actionEditor; delete ui; - delete m_deleteShortcut; } void ConnectionViewWidget::setBindingModel(BindingModel *model) @@ -215,9 +213,11 @@ QList<QToolButton *> ConnectionViewWidget::createToolBarWidgets() connect(buttons.constLast(), &QAbstractButton::clicked, this, &ConnectionViewWidget::removeButtonClicked); connect(this, &ConnectionViewWidget::setEnabledRemoveButton, buttons.constLast(), &QWidget::setEnabled); - m_deleteShortcut->setKey(Qt::Key_Delete); - m_deleteShortcut->setContext(Qt::WidgetWithChildrenShortcut); - connect(m_deleteShortcut, &QShortcut::activated, this, &ConnectionViewWidget::removeButtonClicked); + QAction *deleteShortcut = new QAction(this); + this->addAction(deleteShortcut); + deleteShortcut->setShortcuts({QKeySequence::Delete, QKeySequence::Backspace}); + deleteShortcut->setShortcutContext(Qt::WidgetWithChildrenShortcut); + connect(deleteShortcut, &QAction::triggered, this, &ConnectionViewWidget::removeButtonClicked); return buttons; } diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.h b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.h index c1f1271fca..d69d0de280 100644 --- a/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.h +++ b/src/plugins/qmldesigner/components/connectioneditor/connectionviewwidget.h @@ -102,7 +102,6 @@ private: private: Ui::ConnectionViewWidget *ui; QmlDesigner::ActionEditor *m_actionEditor; - QShortcut *m_deleteShortcut; }; } // namespace Internal diff --git a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp index ee5f1e029c..7028ae7029 100644 --- a/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp +++ b/src/plugins/qmldesigner/components/curveeditor/detail/graphicsview.cpp @@ -611,6 +611,8 @@ void GraphicsView::drawTimeScale(QPainter *painter, const QRectF &rect) for (double i = minimumTime(); i <= maximumTime(); i += timeIncrement) paintLabeledTick(i); + drawRangeBar(painter, rect); + painter->restore(); } diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorannotationicon.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorannotationicon.cpp index c8717541d7..4ad03468bb 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorannotationicon.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorannotationicon.cpp @@ -404,14 +404,15 @@ void FormEditorAnnotationIcon::removeAnnotationDialog() if (!m_customId.isNull()) { dialogTitle = m_customId; } - QMessageBox *deleteDialog = new QMessageBox(Core::ICore::dialogParent()); + QPointer<QMessageBox> deleteDialog = new QMessageBox(Core::ICore::dialogParent()); deleteDialog->setWindowTitle(dialogTitle); deleteDialog->setText(tr("Delete this annotation?")); deleteDialog->setStandardButtons(QMessageBox::Yes | QMessageBox::No); deleteDialog->setDefaultButton(QMessageBox::Yes); int result = deleteDialog->exec(); - if (deleteDialog) deleteDialog->deleteLater(); + if (deleteDialog) + deleteDialog->deleteLater(); if (result == QMessageBox::Yes) { m_modelNode.removeCustomId(); diff --git a/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp b/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp index 883fe841d9..02f3ce9ee6 100644 --- a/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp +++ b/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp @@ -44,7 +44,6 @@ namespace QmlDesigner { SelectionIndicator::SelectionIndicator(LayerItem *layerItem) : m_layerItem(layerItem) - , m_annotationItem(nullptr) { } diff --git a/src/plugins/qmldesigner/components/formeditor/selectionindicator.h b/src/plugins/qmldesigner/components/formeditor/selectionindicator.h index 252020e990..344f8c3a1d 100644 --- a/src/plugins/qmldesigner/components/formeditor/selectionindicator.h +++ b/src/plugins/qmldesigner/components/formeditor/selectionindicator.h @@ -57,11 +57,11 @@ private: private: QHash<FormEditorItem*, QGraphicsPolygonItem *> m_indicatorShapeHash; - FormEditorItem *m_selectedItem; + FormEditorItem *m_selectedItem = nullptr; QPointer<LayerItem> m_layerItem; QCursor m_cursor; std::unique_ptr<QGraphicsPolygonItem> m_labelItem; - FormEditorAnnotationIcon *m_annotationItem; //handled by m_labelItem + FormEditorAnnotationIcon *m_annotationItem = nullptr; //handled by m_labelItem }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp index ba5b9a9f04..70cf975df7 100644 --- a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp +++ b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp @@ -68,6 +68,8 @@ static Q_LOGGING_CATEGORY(puppetStart, "qtc.puppet.start", QtWarningMsg) static Q_LOGGING_CATEGORY(puppetBuild, "qtc.puppet.build", QtWarningMsg) +using namespace ProjectExplorer; + namespace QmlDesigner { class EventFilter : public QObject { @@ -522,11 +524,7 @@ QString PuppetCreator::buildCommand() const Utils::Environment environment = Utils::Environment::systemEnvironment(); m_target->kit()->addToEnvironment(environment); - ProjectExplorer::ToolChain *toolChain - = ProjectExplorer::ToolChainKitAspect::toolChain(m_target->kit(), - ProjectExplorer::Constants::CXX_LANGUAGE_ID); - - if (toolChain) + if (ToolChain *toolChain = ToolChainKitAspect::cxxToolChain(m_target->kit())) return toolChain->makeCommand(environment).toString(); return QString(); diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp index 68c1170f2b..ea88dfcc04 100644 --- a/src/plugins/qmldesigner/designmodewidget.cpp +++ b/src/plugins/qmldesigner/designmodewidget.cpp @@ -244,13 +244,13 @@ void DesignModeWidget::setup() m_dockManager->setStyleSheet(Theme::replaceCssColors(sheet)); // Setup Actions and Menus - Core::ActionContainer *mwindow = Core::ActionManager::actionContainer(Core::Constants::M_WINDOW); + Core::ActionContainer *mview = Core::ActionManager::actionContainer(Core::Constants::M_VIEW); // Window > Views - Core::ActionContainer *mviews = Core::ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS); + Core::ActionContainer *mviews = Core::ActionManager::createMenu(Core::Constants::M_VIEW_VIEWS); mviews->menu()->addSeparator(); // Window > Workspaces Core::ActionContainer *mworkspaces = Core::ActionManager::createMenu(QmlDesigner::Constants::M_WINDOW_WORKSPACES); - mwindow->addMenu(mworkspaces, Core::Constants::G_WINDOW_VIEWS); + mview->addMenu(mworkspaces, Core::Constants::G_VIEW_VIEWS); mworkspaces->menu()->setTitle(tr("&Workspaces")); mworkspaces->setOnAllDisabledBehavior(Core::ActionContainer::Show); // Connect opening of the 'workspaces' menu with creation of the workspaces menu diff --git a/src/plugins/qmldesigner/shortcutmanager.cpp b/src/plugins/qmldesigner/shortcutmanager.cpp index 72f79a8810..617c1775ab 100644 --- a/src/plugins/qmldesigner/shortcutmanager.cpp +++ b/src/plugins/qmldesigner/shortcutmanager.cpp @@ -154,12 +154,7 @@ void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContex m_deleteAction.setIcon(QIcon::fromTheme(QLatin1String("edit-cut"), Utils::Icons::EDIT_CLEAR_TOOLBAR.icon())); command = Core::ActionManager::registerAction(&m_deleteAction, QmlDesigner::Constants::C_DELETE, qmlDesignerMainContext); - if (Utils::HostOsInfo::isMacHost()) - command->setDefaultKeySequence(QKeySequence::Backspace); - else - command->setDefaultKeySequence(QKeySequence::Delete); - - Utils::HostOsInfo::isMacHost() ; + command->setDefaultKeySequences({QKeySequence::Delete, QKeySequence::Backspace}); command->setAttribute(Core::Command::CA_Hide); // don't show delete in other modes if (!Utils::HostOsInfo::isMacHost()) @@ -193,7 +188,7 @@ void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContex command->setDefaultKeySequence(QKeySequence::SelectAll); editMenu->addAction(command, Core::Constants::G_EDIT_SELECTALL); - Core::ActionContainer *viewsMenu = Core::ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS); + Core::ActionContainer *viewsMenu = Core::ActionManager::actionContainer(Core::Constants::M_VIEW_VIEWS); command = Core::ActionManager::registerAction(&m_collapseExpandStatesAction, Constants::TOGGLE_STATES_EDITOR, qmlDesignerMainContext); command->setAttribute(Core::Command::CA_Hide); diff --git a/src/plugins/qnx/qnxconfiguration.cpp b/src/plugins/qnx/qnxconfiguration.cpp index 11a846e612..bdfef8b380 100644 --- a/src/plugins/qnx/qnxconfiguration.cpp +++ b/src/plugins/qnx/qnxconfiguration.cpp @@ -178,7 +178,7 @@ void QnxConfiguration::deactivate() foreach (Kit *kit, KitManager::kits()) { if (kit->isAutoDetected() && DeviceTypeKitAspect::deviceTypeId(kit) == Constants::QNX_QNX_OS_TYPE - && toolChainsToRemove.contains(ToolChainKitAspect::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID))) + && toolChainsToRemove.contains(ToolChainKitAspect::cxxToolChain(kit))) KitManager::deregisterKit(kit); } diff --git a/src/plugins/qnx/qnxtoolchain.cpp b/src/plugins/qnx/qnxtoolchain.cpp index f1bdb8ceae..533463e8dc 100644 --- a/src/plugins/qnx/qnxtoolchain.cpp +++ b/src/plugins/qnx/qnxtoolchain.cpp @@ -106,7 +106,7 @@ QnxToolChain::QnxToolChain() : GccToolChain(Constants::QNX_TOOLCHAIN_ID) { setOptionsReinterpreter(&reinterpretOptions); - setTypeDisplayName(QnxToolChainFactory::tr("QCC")); + setTypeDisplayName(tr("QCC")); } std::unique_ptr<ToolChainConfigWidget> QnxToolChain::createConfigurationWidget() @@ -204,7 +204,7 @@ bool QnxToolChain::operator ==(const ToolChain &other) const QnxToolChainFactory::QnxToolChainFactory() { - setDisplayName(tr("QCC")); + setDisplayName(QnxToolChain::tr("QCC")); setSupportedToolChainType(Constants::QNX_TOOLCHAIN_ID); setSupportedLanguages({ProjectExplorer::Constants::C_LANGUAGE_ID, ProjectExplorer::Constants::CXX_LANGUAGE_ID}); diff --git a/src/plugins/qnx/qnxtoolchain.h b/src/plugins/qnx/qnxtoolchain.h index 71e10a2879..3f38f2c555 100644 --- a/src/plugins/qnx/qnxtoolchain.h +++ b/src/plugins/qnx/qnxtoolchain.h @@ -33,6 +33,8 @@ namespace Internal { class QnxToolChain : public ProjectExplorer::GccToolChain { + Q_DECLARE_TR_FUNCTIONS(Qnx::Internal::QnxToolChain) + public: QnxToolChain(); @@ -65,8 +67,6 @@ private: class QnxToolChainFactory : public ProjectExplorer::ToolChainFactory { - Q_OBJECT - public: QnxToolChainFactory(); diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index 7c1a3c241d..49dd128d28 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -510,8 +510,7 @@ Tasks BaseQtVersion::validateKit(const Kit *k) if (!tdt.isEmpty() && !tdt.contains(dt)) result << BuildSystemTask(Task::Warning, tr("Device type is not supported by Qt version.")); - ToolChain *tc = ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID); - if (tc) { + if (ToolChain *tc = ToolChainKitAspect::cxxToolChain(k)) { Abi targetAbi = tc->targetAbi(); bool fuzzyMatch = false; bool fullMatch = false; @@ -538,7 +537,7 @@ Tasks BaseQtVersion::validateKit(const Kit *k) version->displayName(), qtAbiString); result << BuildSystemTask(fuzzyMatch ? Task::Warning : Task::Error, message); } - } else if (ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::C_LANGUAGE_ID)) { + } else if (ToolChainKitAspect::cToolChain(k)) { const QString message = tr("The kit has a Qt version, but no C++ compiler."); result << BuildSystemTask(Task::Warning, message); } diff --git a/src/plugins/qtsupport/qtkitinformation.cpp b/src/plugins/qtsupport/qtkitinformation.cpp index 6c5a8b90cb..0ff13d07ec 100644 --- a/src/plugins/qtsupport/qtkitinformation.cpp +++ b/src/plugins/qtsupport/qtkitinformation.cpp @@ -219,8 +219,9 @@ void QtKitAspect::fix(ProjectExplorer::Kit *k) } // Set a matching toolchain if we don't have one. - if (ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID)) + if (ToolChainKitAspect::cxxToolChain(k)) return; + const QString spec = version->mkspec(); QList<ToolChain *> possibleTcs = ToolChainManager::toolChains( [version](const ToolChain *t) { diff --git a/src/plugins/qtsupport/qtoutputformatter.cpp b/src/plugins/qtsupport/qtoutputformatter.cpp index 52517c5847..b2179f33f5 100644 --- a/src/plugins/qtsupport/qtoutputformatter.cpp +++ b/src/plugins/qtsupport/qtoutputformatter.cpp @@ -92,9 +92,8 @@ public: explicit QtOutputFormatter(Target *target); ~QtOutputFormatter() override; - void appendMessage(const QString &text, Utils::OutputFormat format) override; + void doAppendMessage(const QString &text, Utils::OutputFormat format) override; void handleLink(const QString &href) override; - void setPlainTextEdit(QPlainTextEdit *plainText) override; protected: void clearLastLine() override; @@ -106,7 +105,7 @@ private: void appendMessagePart(const QString &txt, const QTextCharFormat &fmt); void appendLine(const LinkResult &lr, const QString &line, Utils::OutputFormat format); void appendLine(const LinkResult &lr, const QString &line, const QTextCharFormat &format); - void appendMessage(const QString &text, const QTextCharFormat &format) override; + void doAppendMessage(const QString &text, const QTextCharFormat &format) override; QtOutputFormatterPrivate *d; friend class QtSupportPlugin; // for testing @@ -164,9 +163,9 @@ LinkResult QtOutputFormatter::matchLine(const QString &line) const return lr; } -void QtOutputFormatter::appendMessage(const QString &txt, OutputFormat format) +void QtOutputFormatter::doAppendMessage(const QString &txt, OutputFormat format) { - appendMessage(txt, charFormat(format)); + doAppendMessage(txt, charFormat(format)); } void QtOutputFormatter::appendMessagePart(const QString &txt, const QTextCharFormat &fmt) @@ -188,7 +187,7 @@ void QtOutputFormatter::appendMessagePart(const QString &txt, const QTextCharFor LinkResult lr = matchLine(line); if (!lr.href.isEmpty()) { // Found something && line continuation - d->cursor.insertText(deferredText, fmt); + cursor().insertText(deferredText, fmt); deferredText.clear(); if (!d->lastLine.isEmpty()) clearLastLine(); @@ -207,22 +206,20 @@ void QtOutputFormatter::appendMessagePart(const QString &txt, const QTextCharFor } d->lastLine.clear(); // Handled line continuation } - d->cursor.insertText(deferredText, fmt); + cursor().insertText(deferredText, fmt); } -void QtOutputFormatter::appendMessage(const QString &txt, const QTextCharFormat &format) +void QtOutputFormatter::doAppendMessage(const QString &txt, const QTextCharFormat &format) { - if (!d->cursor.atEnd()) - d->cursor.movePosition(QTextCursor::End); - d->cursor.beginEditBlock(); + if (!cursor().atEnd()) + cursor().movePosition(QTextCursor::End); + cursor().beginEditBlock(); const QList<FormattedText> ansiTextList = parseAnsi(txt, format); for (const FormattedText &output : ansiTextList) appendMessagePart(output.text, output.format); - d->cursor.endEditBlock(); - - emit contentChanged(); + cursor().endEditBlock(); } void QtOutputFormatter::appendLine(const LinkResult &lr, const QString &line, OutputFormat format) @@ -233,9 +230,9 @@ void QtOutputFormatter::appendLine(const LinkResult &lr, const QString &line, Ou void QtOutputFormatter::appendLine(const LinkResult &lr, const QString &line, const QTextCharFormat &format) { - d->cursor.insertText(line.left(lr.start), format); - d->cursor.insertText(line.mid(lr.start, lr.end - lr.start), linkFormat(format, lr.href)); - d->cursor.insertText(line.mid(lr.end), format); + cursor().insertText(line.left(lr.start), format); + cursor().insertText(line.mid(lr.start, lr.end - lr.start), linkFormat(format, lr.href)); + cursor().insertText(line.mid(lr.end), format); } void QtOutputFormatter::handleLink(const QString &href) @@ -304,12 +301,6 @@ void QtOutputFormatter::handleLink(const QString &href) } } -void QtOutputFormatter::setPlainTextEdit(QPlainTextEdit *plainText) -{ - OutputFormatter::setPlainTextEdit(plainText); - d->cursor = plainText ? plainText->textCursor() : QTextCursor(); -} - void QtOutputFormatter::clearLastLine() { OutputFormatter::clearLastLine(); @@ -567,7 +558,7 @@ void QtSupportPlugin::testQtOutputFormatter_appendMessage() QFETCH(QTextCharFormat, inputFormat); QFETCH(QTextCharFormat, outputFormat); - formatter.appendMessage(inputText, inputFormat); + formatter.doAppendMessage(inputText, inputFormat); QCOMPARE(edit.toPlainText(), outputText); QCOMPARE(edit.currentCharFormat(), outputFormat); @@ -588,7 +579,7 @@ void QtSupportPlugin::testQtOutputFormatter_appendMixedAssertAndAnsi() "file://test.cpp:123 " "Blue\n"; - formatter.appendMessage(inputText, QTextCharFormat()); + formatter.doAppendMessage(inputText, QTextCharFormat()); QCOMPARE(edit.toPlainText(), outputText); diff --git a/src/plugins/remotelinux/abstractpackagingstep.cpp b/src/plugins/remotelinux/abstractpackagingstep.cpp index ceb2d4c50b..b9221460c4 100644 --- a/src/plugins/remotelinux/abstractpackagingstep.cpp +++ b/src/plugins/remotelinux/abstractpackagingstep.cpp @@ -86,7 +86,7 @@ QString AbstractPackagingStep::cachedPackageDirectory() const QString AbstractPackagingStep::packageDirectory() const { - return buildConfiguration()->buildDirectory().toString(); + return buildDirectory().toString(); } bool AbstractPackagingStep::isPackagingNeeded() const diff --git a/src/plugins/remotelinux/genericdirectuploadstep.cpp b/src/plugins/remotelinux/genericdirectuploadstep.cpp index a355e94175..cd3ab65546 100644 --- a/src/plugins/remotelinux/genericdirectuploadstep.cpp +++ b/src/plugins/remotelinux/genericdirectuploadstep.cpp @@ -26,6 +26,7 @@ #include "genericdirectuploadstep.h" #include "genericdirectuploadservice.h" +#include "remotelinux_constants.h" #include <projectexplorer/deploymentdata.h> #include <projectexplorer/target.h> @@ -79,7 +80,7 @@ GenericDirectUploadStep::~GenericDirectUploadStep() = default; Core::Id GenericDirectUploadStep::stepId() { - return "RemoteLinux.DirectUploadStep"; + return Constants::DirectUploadStepId; } QString GenericDirectUploadStep::displayName() diff --git a/src/plugins/remotelinux/makeinstallstep.cpp b/src/plugins/remotelinux/makeinstallstep.cpp index 8aa811a944..b4ce1b5632 100644 --- a/src/plugins/remotelinux/makeinstallstep.cpp +++ b/src/plugins/remotelinux/makeinstallstep.cpp @@ -25,6 +25,8 @@ #include "makeinstallstep.h" +#include "remotelinux_constants.h" + #include <projectexplorer/buildconfiguration.h> #include <projectexplorer/buildsteplist.h> #include <projectexplorer/buildsystem.h> @@ -112,7 +114,7 @@ MakeInstallStep::MakeInstallStep(BuildStepList *parent, Core::Id id) : MakeStep( Core::Id MakeInstallStep::stepId() { - return "RemoteLinux.MakeInstall"; + return Constants::MakeInstallStepId; } QString MakeInstallStep::displayName() diff --git a/src/plugins/remotelinux/remotelinux_constants.h b/src/plugins/remotelinux/remotelinux_constants.h index 479dfda167..951603ccfa 100644 --- a/src/plugins/remotelinux/remotelinux_constants.h +++ b/src/plugins/remotelinux/remotelinux_constants.h @@ -30,5 +30,9 @@ namespace Constants { const char GenericLinuxOsType[] = "GenericLinuxOsType"; +const char CheckForFreeDiskSpaceId[] = "RemoteLinux.CheckForFreeDiskSpaceStep"; +const char DirectUploadStepId[] = "RemoteLinux.DirectUploadStep"; +const char MakeInstallStepId[] = "RemoteLinux.MakeInstall"; + } // Constants } // RemoteLinux diff --git a/src/plugins/resourceeditor/qrceditor/resourcefile.cpp b/src/plugins/resourceeditor/qrceditor/resourcefile.cpp index 81c211cb0a..71f5fb05c4 100644 --- a/src/plugins/resourceeditor/qrceditor/resourcefile.cpp +++ b/src/plugins/resourceeditor/qrceditor/resourcefile.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -448,6 +448,18 @@ QString ResourceFile::absolutePath(const QString &rel_path) const return QDir::cleanPath(rc); } +void ResourceFile::orderList() +{ + for (Prefix *p : m_prefix_list) { + std::sort(p->file_list.begin(), p->file_list.end(), [&](File *f1, File *f2) { + return *f1 < *f2; + }); + } + + if (!save()) + m_error_message = tr("Cannot save file."); +} + bool ResourceFile::contains(const QString &prefix, const QString &lang, const QString &file) const { int pref_idx = indexOfPrefix(prefix, lang); @@ -688,6 +700,11 @@ QList<QModelIndex> ResourceModel::nonExistingFiles() const return files; } +void ResourceModel::orderList() +{ + m_resource_file.orderList(); +} + Qt::ItemFlags ResourceModel::flags(const QModelIndex &index) const { Qt::ItemFlags f = QAbstractItemModel::flags(index); diff --git a/src/plugins/resourceeditor/qrceditor/resourcefile_p.h b/src/plugins/resourceeditor/qrceditor/resourcefile_p.h index 8957a56f0e..0afb55290c 100644 --- a/src/plugins/resourceeditor/qrceditor/resourcefile_p.h +++ b/src/plugins/resourceeditor/qrceditor/resourcefile_p.h @@ -170,6 +170,8 @@ public: QString relativePath(const QString &abs_path) const; QString absolutePath(const QString &rel_path) const; + void orderList(); + static QString fixPrefix(const QString &prefix); private: @@ -260,6 +262,8 @@ public: bool dirty() const { return m_dirty; } void setDirty(bool b); + void orderList(); + private: QMimeData *mimeData (const QModelIndexList & indexes) const override; diff --git a/src/plugins/resourceeditor/qrceditor/resourceview.cpp b/src/plugins/resourceeditor/qrceditor/resourceview.cpp index 8e2c70ad79..1fc524bf28 100644 --- a/src/plugins/resourceeditor/qrceditor/resourceview.cpp +++ b/src/plugins/resourceeditor/qrceditor/resourceview.cpp @@ -175,7 +175,7 @@ void ResourceView::removeFiles(int prefixIndex, int firstFileIndex, int lastFile void ResourceView::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Delete) + if (e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace) emit removeItem(); else Utils::TreeView::keyPressEvent(e); diff --git a/src/plugins/resourceeditor/resourceeditorw.cpp b/src/plugins/resourceeditor/resourceeditorw.cpp index 2255810bb9..8467b8bf13 100644 --- a/src/plugins/resourceeditor/resourceeditorw.cpp +++ b/src/plugins/resourceeditor/resourceeditorw.cpp @@ -95,6 +95,7 @@ ResourceEditorW::ResourceEditorW(const Core::Context &context, &ResourceEditorW::renameCurrentFile); m_copyFileNameAction = m_contextMenu->addAction(tr("Copy Resource Path to Clipboard"), this, &ResourceEditorW::copyCurrentResourcePath); + m_orderList = m_contextMenu->addAction(tr("Sort Alphabetically"), this, &ResourceEditorW::orderList); connect(m_resourceDocument, &ResourceEditorDocument::loaded, m_resourceEditor, &QrcEditor::loaded); @@ -331,6 +332,11 @@ void ResourceEditorW::copyCurrentResourcePath() QApplication::clipboard()->setText(m_resourceEditor->currentResourcePath()); } +void ResourceEditorW::orderList() +{ + m_resourceDocument->model()->orderList(); +} + void ResourceEditorW::onUndo() { m_resourceEditor->onUndo(); diff --git a/src/plugins/resourceeditor/resourceeditorw.h b/src/plugins/resourceeditor/resourceeditorw.h index 8ac4e8d9b2..90fbc93bb3 100644 --- a/src/plugins/resourceeditor/resourceeditorw.h +++ b/src/plugins/resourceeditor/resourceeditorw.h @@ -101,6 +101,7 @@ private: void openFile(const QString &fileName); void renameCurrentFile(); void copyCurrentResourcePath(); + void orderList(); const QString m_extension; const QString m_fileFilter; @@ -114,6 +115,7 @@ private: QToolBar *m_toolBar; QAction *m_renameAction; QAction *m_copyFileNameAction; + QAction *m_orderList; public: void onRefresh(); diff --git a/src/plugins/scxmleditor/common/structure.cpp b/src/plugins/scxmleditor/common/structure.cpp index be49e9711d..08164e0aa3 100644 --- a/src/plugins/scxmleditor/common/structure.cpp +++ b/src/plugins/scxmleditor/common/structure.cpp @@ -239,7 +239,7 @@ void Structure::childAdded(const QModelIndex &childIndex) void Structure::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Delete) { + if (e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace) { QModelIndex ind = m_proxyModel->mapToSource(m_structureView->currentIndex()); auto tag = static_cast<ScxmlTag*>(ind.internalPointer()); if (tag && m_currentDocument) { diff --git a/src/plugins/scxmleditor/plugin_interface/graphicsscene.cpp b/src/plugins/scxmleditor/plugin_interface/graphicsscene.cpp index 5513ed1ee7..863b40ae0c 100644 --- a/src/plugins/scxmleditor/plugin_interface/graphicsscene.cpp +++ b/src/plugins/scxmleditor/plugin_interface/graphicsscene.cpp @@ -679,7 +679,7 @@ void GraphicsScene::keyPressEvent(QKeyEvent *event) { QGraphicsItem *focusItem = this->focusItem(); if (!focusItem || focusItem->type() != TextType) { - if (event->key() == Qt::Key_Delete) + if (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) removeSelectedItems(); } QGraphicsScene::keyPressEvent(event); diff --git a/src/plugins/scxmleditor/plugin_interface/transitionitem.cpp b/src/plugins/scxmleditor/plugin_interface/transitionitem.cpp index e388a43cc8..fb0c5743ab 100644 --- a/src/plugins/scxmleditor/plugin_interface/transitionitem.cpp +++ b/src/plugins/scxmleditor/plugin_interface/transitionitem.cpp @@ -457,7 +457,7 @@ void TransitionItem::selectedMenuAction(const QAction *action) void TransitionItem::keyPressEvent(QKeyEvent *event) { - if (event->key() == Qt::Key_Delete) { + if (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) { bool bFound = false; if (m_cornerGrabbers.count() > 2) { for (int i = m_cornerGrabbers.count() - 1; i >= 1; i--) { diff --git a/src/plugins/texteditor/behaviorsettingswidget.cpp b/src/plugins/texteditor/behaviorsettingswidget.cpp index f5dc751eb6..fe7e983fad 100644 --- a/src/plugins/texteditor/behaviorsettingswidget.cpp +++ b/src/plugins/texteditor/behaviorsettingswidget.cpp @@ -101,6 +101,8 @@ BehaviorSettingsWidget::BehaviorSettingsWidget(QWidget *parent) this, &BehaviorSettingsWidget::slotStorageSettingsChanged); connect(d->m_ui.cleanIndentation, &QAbstractButton::clicked, this, &BehaviorSettingsWidget::slotStorageSettingsChanged); + connect(d->m_ui.skipTrailingWhitespace, &QAbstractButton::clicked, + this, &BehaviorSettingsWidget::slotStorageSettingsChanged); connect(d->m_ui.mouseHiding, &QAbstractButton::clicked, this, &BehaviorSettingsWidget::slotBehaviorSettingsChanged); connect(d->m_ui.mouseNavigation, &QAbstractButton::clicked, @@ -190,6 +192,9 @@ void BehaviorSettingsWidget::setAssignedStorageSettings(const StorageSettings &s d->m_ui.inEntireDocument->setChecked(storageSettings.m_inEntireDocument); d->m_ui.cleanIndentation->setChecked(storageSettings.m_cleanIndentation); d->m_ui.addFinalNewLine->setChecked(storageSettings.m_addFinalNewLine); + d->m_ui.skipTrailingWhitespace->setChecked(storageSettings.m_skipTrailingWhitespace); + d->m_ui.ignoreFileTypes->setText(storageSettings.m_ignoreFileTypes); + d->m_ui.ignoreFileTypes->setEnabled(d->m_ui.skipTrailingWhitespace->isChecked()); } void BehaviorSettingsWidget::assignedStorageSettings(StorageSettings *storageSettings) const @@ -198,6 +203,8 @@ void BehaviorSettingsWidget::assignedStorageSettings(StorageSettings *storageSet storageSettings->m_inEntireDocument = d->m_ui.inEntireDocument->isChecked(); storageSettings->m_cleanIndentation = d->m_ui.cleanIndentation->isChecked(); storageSettings->m_addFinalNewLine = d->m_ui.addFinalNewLine->isChecked(); + storageSettings->m_skipTrailingWhitespace = d->m_ui.skipTrailingWhitespace->isChecked(); + storageSettings->m_ignoreFileTypes = d->m_ui.ignoreFileTypes->text(); } void BehaviorSettingsWidget::updateConstrainTooltipsBoxTooltip() const @@ -273,6 +280,10 @@ void BehaviorSettingsWidget::slotStorageSettingsChanged() { StorageSettings settings; assignedStorageSettings(&settings); + + bool ignoreFileTypesEnabled = d->m_ui.cleanWhitespace->isChecked() && d->m_ui.skipTrailingWhitespace->isChecked(); + d->m_ui.ignoreFileTypes->setEnabled(ignoreFileTypesEnabled); + emit storageSettingsChanged(settings); } diff --git a/src/plugins/texteditor/behaviorsettingswidget.ui b/src/plugins/texteditor/behaviorsettingswidget.ui index c36bb9ae47..d6d9fed5c6 100644 --- a/src/plugins/texteditor/behaviorsettingswidget.ui +++ b/src/plugins/texteditor/behaviorsettingswidget.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>801</width> - <height>547</height> + <height>693</height> </rect> </property> <layout class="QHBoxLayout" name="horizontalLayout"> @@ -169,13 +169,72 @@ Specifies how backspace interacts with indentation. <string>Cleanups Upon Saving</string> </property> <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="0" colspan="2"> - <widget class="QCheckBox" name="cleanWhitespace"> + <item row="5" column="1"> + <widget class="QWidget" name="widget" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QCheckBox" name="skipTrailingWhitespace"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>For the file patterns listed, do not trim trailing whitespace.</string> + </property> + <property name="text"> + <string>Skip clean whitespace for file types:</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <property name="tristate"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="ignoreFileTypes"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>List of wildcard-aware file patterns, separated by commas or semicolons.</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="9" column="0" colspan="2"> + <widget class="QCheckBox" name="addFinalNewLine"> + <property name="enabled"> + <bool>true</bool> + </property> <property name="toolTip"> - <string>Removes trailing whitespace upon saving.</string> + <string>Always writes a newline character at the end of the file.</string> </property> <property name="text"> - <string>&Clean whitespace</string> + <string>&Ensure newline at end of file</string> </property> </widget> </item> @@ -195,26 +254,17 @@ Specifies how backspace interacts with indentation. </property> </spacer> </item> - <item row="1" column="1"> - <widget class="QCheckBox" name="inEntireDocument"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> + <item row="0" column="0" colspan="2"> + <widget class="QCheckBox" name="cleanWhitespace"> <property name="toolTip"> - <string>Cleans whitespace in entire document instead of only for changed parts.</string> + <string>Removes trailing whitespace upon saving.</string> </property> <property name="text"> - <string>In entire &document</string> + <string>&Clean whitespace</string> </property> </widget> </item> - <item row="2" column="1"> + <item row="3" column="1"> <widget class="QCheckBox" name="cleanIndentation"> <property name="enabled"> <bool>false</bool> @@ -227,13 +277,22 @@ Specifies how backspace interacts with indentation. </property> </widget> </item> - <item row="3" column="0" colspan="2"> - <widget class="QCheckBox" name="addFinalNewLine"> + <item row="1" column="1"> + <widget class="QCheckBox" name="inEntireDocument"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="toolTip"> - <string>Always writes a newline character at the end of the file.</string> + <string>Cleans whitespace in entire document instead of only for changed parts.</string> </property> <property name="text"> - <string>&Ensure newline at end of file</string> + <string>In entire &document</string> </property> </widget> </item> @@ -521,5 +580,37 @@ Specifies how backspace interacts with indentation. </hint> </hints> </connection> + <connection> + <sender>cleanWhitespace</sender> + <signal>toggled(bool)</signal> + <receiver>skipTrailingWhitespace</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>530</x> + <y>48</y> + </hint> + <hint type="destinationlabel"> + <x>548</x> + <y>144</y> + </hint> + </hints> + </connection> + <connection> + <sender>cleanWhitespace</sender> + <signal>toggled(bool)</signal> + <receiver>ignoreFileTypes</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>530</x> + <y>48</y> + </hint> + <hint type="destinationlabel"> + <x>556</x> + <y>177</y> + </hint> + </hints> + </connection> </connections> </ui> diff --git a/src/plugins/texteditor/storagesettings.cpp b/src/plugins/texteditor/storagesettings.cpp index a1c4645b0c..9a0f6e2c54 100644 --- a/src/plugins/texteditor/storagesettings.cpp +++ b/src/plugins/texteditor/storagesettings.cpp @@ -25,8 +25,10 @@ #include "storagesettings.h" +#include <utils/hostosinfo.h> #include <utils/settingsutils.h> +#include <QRegularExpression> #include <QSettings> #include <QString> @@ -36,13 +38,18 @@ static const char cleanWhitespaceKey[] = "cleanWhitespace"; static const char inEntireDocumentKey[] = "inEntireDocument"; static const char addFinalNewLineKey[] = "addFinalNewLine"; static const char cleanIndentationKey[] = "cleanIndentation"; +static const char skipTrailingWhitespaceKey[] = "skipTrailingWhitespace"; +static const char ignoreFileTypesKey[] = "ignoreFileTypes"; static const char groupPostfix[] = "StorageSettings"; +static const char defaultTrailingWhitespaceBlacklist[] = "*.md, *.MD, Makefile"; StorageSettings::StorageSettings() - : m_cleanWhitespace(true), + : m_ignoreFileTypes(defaultTrailingWhitespaceBlacklist), + m_cleanWhitespace(true), m_inEntireDocument(false), m_addFinalNewLine(true), - m_cleanIndentation(true) + m_cleanIndentation(true), + m_skipTrailingWhitespace(true) { } @@ -63,6 +70,8 @@ void StorageSettings::toMap(const QString &prefix, QVariantMap *map) const map->insert(prefix + QLatin1String(inEntireDocumentKey), m_inEntireDocument); map->insert(prefix + QLatin1String(addFinalNewLineKey), m_addFinalNewLine); map->insert(prefix + QLatin1String(cleanIndentationKey), m_cleanIndentation); + map->insert(prefix + QLatin1String(skipTrailingWhitespaceKey), m_skipTrailingWhitespace); + map->insert(prefix + QLatin1String(ignoreFileTypesKey), m_ignoreFileTypes.toLatin1().data()); } void StorageSettings::fromMap(const QString &prefix, const QVariantMap &map) @@ -75,6 +84,48 @@ void StorageSettings::fromMap(const QString &prefix, const QVariantMap &map) map.value(prefix + QLatin1String(addFinalNewLineKey), m_addFinalNewLine).toBool(); m_cleanIndentation = map.value(prefix + QLatin1String(cleanIndentationKey), m_cleanIndentation).toBool(); + m_skipTrailingWhitespace = + map.value(prefix + QLatin1String(skipTrailingWhitespaceKey), m_skipTrailingWhitespace).toBool(); + m_ignoreFileTypes = + map.value(prefix + QLatin1String(ignoreFileTypesKey), m_ignoreFileTypes).toString(); +} + +bool StorageSettings::removeTrailingWhitespace(const QString &fileName) const +{ + // if the user has elected not to trim trailing whitespace altogether, then + // early out here + if (!m_skipTrailingWhitespace) { + return true; + } + + const QString ignoreFileTypesRegExp(R"(\s*((?>\*\.)?[\w\d\.\*]+)[,;]?\s*)"); + + // use the ignore-files regex to extract the specified file patterns + QRegularExpression re(ignoreFileTypesRegExp); + QRegularExpressionMatchIterator iter = re.globalMatch(m_ignoreFileTypes); + + while (iter.hasNext()) { + QRegularExpressionMatch match = iter.next(); + QString pattern = match.captured(1); + + QString wildcardRegExp +#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) + = QRegularExpression::wildcardToRegularExpression(pattern); +#else + = QRegExp(pattern, Utils::HostOsInfo::fileNameCaseSensitivity(), + QRegExp::Wildcard).pattern(); +#endif + QRegularExpression patternRegExp(wildcardRegExp); + QRegularExpressionMatch patternMatch = patternRegExp.match(fileName); + if (patternMatch.hasMatch()) { + // if the filename has a pattern we want to ignore, then we need to return + // false ("don't remove trailing whitespace") + return false; + } + } + + // the supplied pattern does not match, so we want to remove trailing whitespace + return true; } bool StorageSettings::equals(const StorageSettings &ts) const @@ -82,7 +133,9 @@ bool StorageSettings::equals(const StorageSettings &ts) const return m_addFinalNewLine == ts.m_addFinalNewLine && m_cleanWhitespace == ts.m_cleanWhitespace && m_inEntireDocument == ts.m_inEntireDocument - && m_cleanIndentation == ts.m_cleanIndentation; + && m_cleanIndentation == ts.m_cleanIndentation + && m_skipTrailingWhitespace == ts.m_skipTrailingWhitespace + && m_ignoreFileTypes == ts.m_ignoreFileTypes; } } // namespace TextEditor diff --git a/src/plugins/texteditor/storagesettings.h b/src/plugins/texteditor/storagesettings.h index ffe7823f0f..cd9c176b59 100644 --- a/src/plugins/texteditor/storagesettings.h +++ b/src/plugins/texteditor/storagesettings.h @@ -46,12 +46,17 @@ public: void toMap(const QString &prefix, QVariantMap *map) const; void fromMap(const QString &prefix, const QVariantMap &map); + // calculated based on boolean setting plus file type blacklist examination + bool removeTrailingWhitespace(const QString &filePattern) const; + bool equals(const StorageSettings &ts) const; + QString m_ignoreFileTypes; bool m_cleanWhitespace; bool m_inEntireDocument; bool m_addFinalNewLine; bool m_cleanIndentation; + bool m_skipTrailingWhitespace; }; inline bool operator==(const StorageSettings &t1, const StorageSettings &t2) { return t1.equals(t2); } diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index 319f77a397..0f3ef7a05f 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -622,7 +622,7 @@ bool TextDocument::save(QString *errorString, const QString &saveFileName, bool cursor.movePosition(QTextCursor::Start); if (d->m_storageSettings.m_cleanWhitespace) - cleanWhitespace(cursor, d->m_storageSettings.m_cleanIndentation, d->m_storageSettings.m_inEntireDocument); + cleanWhitespace(cursor, d->m_storageSettings); if (d->m_storageSettings.m_addFinalNewLine) ensureFinalNewLine(cursor); cursor.endEditBlock(); @@ -883,14 +883,22 @@ void TextDocument::cleanWhitespace(const QTextCursor &cursor) QTextCursor copyCursor = cursor; copyCursor.setVisualNavigation(false); copyCursor.beginEditBlock(); - cleanWhitespace(copyCursor, true, true); + + cleanWhitespace(copyCursor, d->m_storageSettings); + if (!hasSelection) ensureFinalNewLine(copyCursor); + copyCursor.endEditBlock(); } -void TextDocument::cleanWhitespace(QTextCursor &cursor, bool cleanIndentation, bool inEntireDocument) +void TextDocument::cleanWhitespace(QTextCursor &cursor, const StorageSettings &storageSettings) { + if (!d->m_storageSettings.m_cleanWhitespace) + return; + + const QString fileName(filePath().fileName()); + auto documentLayout = qobject_cast<TextDocumentLayout*>(d->m_document.documentLayout()); Q_ASSERT(cursor.visualNavigation() == false); @@ -901,7 +909,7 @@ void TextDocument::cleanWhitespace(QTextCursor &cursor, bool cleanIndentation, b QVector<QTextBlock> blocks; while (block.isValid() && block != end) { - if (inEntireDocument || block.revision() != documentLayout->lastSaveRevision) + if (storageSettings.m_inEntireDocument || block.revision() != documentLayout->lastSaveRevision) blocks.append(block); block = block.next(); } @@ -914,9 +922,12 @@ void TextDocument::cleanWhitespace(QTextCursor &cursor, bool cleanIndentation, b foreach (block, blocks) { QString blockText = block.text(); - currentTabSettings.removeTrailingWhitespace(cursor, block); + + if (storageSettings.removeTrailingWhitespace(fileName)) + currentTabSettings.removeTrailingWhitespace(cursor, block); + const int indent = indentations[block.blockNumber()]; - if (cleanIndentation && !currentTabSettings.isIndentationClean(block, indent)) { + if (storageSettings.m_cleanIndentation && !currentTabSettings.isIndentationClean(block, indent)) { cursor.setPosition(block.position()); int firstNonSpace = currentTabSettings.firstNonSpace(blockText); if (firstNonSpace == blockText.length()) { @@ -934,6 +945,9 @@ void TextDocument::cleanWhitespace(QTextCursor &cursor, bool cleanIndentation, b void TextDocument::ensureFinalNewLine(QTextCursor& cursor) { + if (!d->m_storageSettings.m_addFinalNewLine) + return; + cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); bool emptyFile = !cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor); diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h index 447edd0e50..35e6b334ef 100644 --- a/src/plugins/texteditor/textdocument.h +++ b/src/plugins/texteditor/textdocument.h @@ -169,7 +169,7 @@ protected: private: OpenResult openImpl(QString *errorString, const QString &fileName, const QString &realFileName, bool reload); - void cleanWhitespace(QTextCursor &cursor, bool cleanIndentation, bool inEntireDocument); + void cleanWhitespace(QTextCursor &cursor, const StorageSettings &storageSettings); void ensureFinalNewLine(QTextCursor &cursor); void modificationChanged(bool modified); void updateLayout() const; diff --git a/src/plugins/valgrind/memcheckerrorview.cpp b/src/plugins/valgrind/memcheckerrorview.cpp index 3dfa939ddd..0e45b76d43 100644 --- a/src/plugins/valgrind/memcheckerrorview.cpp +++ b/src/plugins/valgrind/memcheckerrorview.cpp @@ -61,7 +61,7 @@ MemcheckErrorView::MemcheckErrorView(QWidget *parent) {":/valgrind/images/suppressoverlay.png", Utils::Theme::IconsErrorColor}}, Utils::Icon::Tint | Utils::Icon::PunchEdges).icon(); m_suppressAction->setIcon(icon); - m_suppressAction->setShortcut(QKeySequence(Qt::Key_Delete)); + m_suppressAction->setShortcuts({QKeySequence::Delete, QKeySequence::Backspace}); m_suppressAction->setShortcutContext(Qt::WidgetWithChildrenShortcut); connect(m_suppressAction, &QAction::triggered, this, &MemcheckErrorView::suppressError); addAction(m_suppressAction); diff --git a/src/plugins/vcsbase/basevcseditorfactory.cpp b/src/plugins/vcsbase/basevcseditorfactory.cpp index 12f467afa0..8f25813885 100644 --- a/src/plugins/vcsbase/basevcseditorfactory.cpp +++ b/src/plugins/vcsbase/basevcseditorfactory.cpp @@ -54,7 +54,6 @@ VcsEditorFactory::VcsEditorFactory(const VcsBaseEditorParameters *parameters, const EditorWidgetCreator editorWidgetCreator, std::function<void(const QString &, const QString &)> describeFunc) { - setProperty("VcsEditorFactoryName", QByteArray(parameters->id)); setId(parameters->id); setDisplayName(QCoreApplication::translate("VCS", parameters->displayName)); if (QLatin1String(parameters->mimeType) != QLatin1String(DiffEditor::Constants::DIFF_EDITOR_MIMETYPE)) diff --git a/src/plugins/vcsbase/basevcseditorfactory.h b/src/plugins/vcsbase/basevcseditorfactory.h index b1b828716e..0afddcd5ce 100644 --- a/src/plugins/vcsbase/basevcseditorfactory.h +++ b/src/plugins/vcsbase/basevcseditorfactory.h @@ -37,8 +37,6 @@ class VcsBaseEditorParameters; class VCSBASE_EXPORT VcsEditorFactory : public TextEditor::TextEditorFactory { - Q_OBJECT - public: VcsEditorFactory(const VcsBaseEditorParameters *parameters, const EditorWidgetCreator editorWidgetCreator, diff --git a/src/plugins/vcsbase/vcsoutputformatter.cpp b/src/plugins/vcsbase/vcsoutputformatter.cpp index 9e454da544..2b2e2a3796 100644 --- a/src/plugins/vcsbase/vcsoutputformatter.cpp +++ b/src/plugins/vcsbase/vcsoutputformatter.cpp @@ -42,14 +42,14 @@ VcsOutputFormatter::VcsOutputFormatter() : { } -void VcsOutputFormatter::appendMessage(const QString &text, Utils::OutputFormat format) +void VcsOutputFormatter::doAppendMessage(const QString &text, Utils::OutputFormat format) { QRegularExpressionMatchIterator it = m_regexp.globalMatch(text); int begin = 0; while (it.hasNext()) { const QRegularExpressionMatch match = it.next(); const QTextCharFormat normalFormat = charFormat(format); - OutputFormatter::appendMessage(text.mid(begin, match.capturedStart() - begin), format); + OutputFormatter::doAppendMessage(text.mid(begin, match.capturedStart() - begin), format); QTextCursor tc = plainTextEdit()->textCursor(); QStringView url = match.capturedView(); begin = match.capturedEnd(); @@ -61,7 +61,7 @@ void VcsOutputFormatter::appendMessage(const QString &text, Utils::OutputFormat tc.insertText(url.toString(), linkFormat(normalFormat, url.toString())); tc.movePosition(QTextCursor::End); } - OutputFormatter::appendMessage(text.mid(begin), format); + OutputFormatter::doAppendMessage(text.mid(begin), format); } void VcsOutputFormatter::handleLink(const QString &href) diff --git a/src/plugins/vcsbase/vcsoutputformatter.h b/src/plugins/vcsbase/vcsoutputformatter.h index b9fd8c6c7e..fe1bae89fd 100644 --- a/src/plugins/vcsbase/vcsoutputformatter.h +++ b/src/plugins/vcsbase/vcsoutputformatter.h @@ -37,7 +37,7 @@ class VcsOutputFormatter : public Utils::OutputFormatter public: VcsOutputFormatter(); ~VcsOutputFormatter() override = default; - void appendMessage(const QString &text, Utils::OutputFormat format) override; + void doAppendMessage(const QString &text, Utils::OutputFormat format) override; void handleLink(const QString &href) override; void fillLinkContextMenu(QMenu *menu, const QString &workingDirectory, const QString &href); diff --git a/src/plugins/vcsbase/vcsoutputwindow.cpp b/src/plugins/vcsbase/vcsoutputwindow.cpp index 1cff2dc4b7..2391a1bb03 100644 --- a/src/plugins/vcsbase/vcsoutputwindow.cpp +++ b/src/plugins/vcsbase/vcsoutputwindow.cpp @@ -228,10 +228,7 @@ void OutputWindowPlainTextEdit::appendLines(const QString &s, const QString &rep const int previousLineCount = document()->lineCount(); - const QChar newLine('\n'); - const QChar lastChar = s.at(s.size() - 1); - const bool appendNewline = (lastChar != '\r' && lastChar != newLine); - m_formatter->appendMessage(appendNewline ? s + newLine : s, m_format); + m_formatter->appendMessage(s, m_format); // Scroll down moveCursor(QTextCursor::End); diff --git a/src/plugins/webassembly/webassemblytoolchain.cpp b/src/plugins/webassembly/webassemblytoolchain.cpp index 73c407c361..30c67eb0c5 100644 --- a/src/plugins/webassembly/webassemblytoolchain.cpp +++ b/src/plugins/webassembly/webassemblytoolchain.cpp @@ -142,14 +142,14 @@ WebAssemblyToolChain::WebAssemblyToolChain() : setCompilerCommand(Utils::FilePath::fromString(command)); setSupportedAbis({toolChainAbi()}); setTargetAbi(toolChainAbi()); - const QString typeAndDisplayName = WebAssemblyToolChainFactory::tr("Emscripten Compiler"); + const QString typeAndDisplayName = tr("Emscripten Compiler"); setDisplayName(typeAndDisplayName); setTypeDisplayName(typeAndDisplayName); } WebAssemblyToolChainFactory::WebAssemblyToolChainFactory() { - setDisplayName(tr("WebAssembly")); + setDisplayName(WebAssemblyToolChain::tr("WebAssembly")); setSupportedToolChainType(Constants::WEBASSEMBLY_TOOLCHAIN_TYPEID); setSupportedLanguages({ProjectExplorer::Constants::C_LANGUAGE_ID, ProjectExplorer::Constants::CXX_LANGUAGE_ID}); diff --git a/src/plugins/webassembly/webassemblytoolchain.h b/src/plugins/webassembly/webassemblytoolchain.h index 4693bc7a10..9e01de8827 100644 --- a/src/plugins/webassembly/webassemblytoolchain.h +++ b/src/plugins/webassembly/webassemblytoolchain.h @@ -32,6 +32,8 @@ namespace Internal { class WebAssemblyToolChain final : public ProjectExplorer::ClangToolChain { + Q_DECLARE_TR_FUNCTIONS(WebAssembly::Internal::WebAssemblyToolChain) + public: void addToEnvironment(Utils::Environment &env) const override; @@ -43,8 +45,6 @@ private: class WebAssemblyToolChainFactory : public ProjectExplorer::ToolChainFactory { - Q_OBJECT - public: WebAssemblyToolChainFactory(); diff --git a/src/plugins/winrt/winrtdeployconfiguration.cpp b/src/plugins/winrt/winrtdeployconfiguration.cpp index e6eb9fd0da..f42d48c924 100644 --- a/src/plugins/winrt/winrtdeployconfiguration.cpp +++ b/src/plugins/winrt/winrtdeployconfiguration.cpp @@ -66,17 +66,5 @@ WinRtEmulatorDeployConfigurationFactory::WinRtEmulatorDeployConfigurationFactory addInitialStep(Constants::WINRT_BUILD_STEP_DEPLOY); } -WinRtDeployStepFactory::WinRtDeployStepFactory() -{ - registerStep<WinRtPackageDeploymentStep>(Constants::WINRT_BUILD_STEP_DEPLOY); - setDisplayName(QCoreApplication::translate("WinRt::Internal::WinRtDeployStepFactory", "Run windeployqt")); - setFlags(BuildStepInfo::Unclonable); - setSupportedStepList(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY); - setSupportedDeviceTypes({Constants::WINRT_DEVICE_TYPE_LOCAL, - Constants::WINRT_DEVICE_TYPE_EMULATOR, - Constants::WINRT_DEVICE_TYPE_PHONE}); - setRepeatable(false); -} - } // namespace Internal } // namespace WinRt diff --git a/src/plugins/winrt/winrtdeployconfiguration.h b/src/plugins/winrt/winrtdeployconfiguration.h index 906679ea6d..1ea45eb8e9 100644 --- a/src/plugins/winrt/winrtdeployconfiguration.h +++ b/src/plugins/winrt/winrtdeployconfiguration.h @@ -49,11 +49,5 @@ public: WinRtEmulatorDeployConfigurationFactory(); }; -class WinRtDeployStepFactory : public ProjectExplorer::BuildStepFactory -{ -public: - WinRtDeployStepFactory(); -}; - } // namespace Internal } // namespace WinRt diff --git a/src/plugins/winrt/winrtpackagedeploymentstep.cpp b/src/plugins/winrt/winrtpackagedeploymentstep.cpp index 61cb14ff0a..32a474775b 100644 --- a/src/plugins/winrt/winrtpackagedeploymentstep.cpp +++ b/src/plugins/winrt/winrtpackagedeploymentstep.cpp @@ -27,15 +27,17 @@ #include "winrtconstants.h" -#include <projectexplorer/project.h> -#include <projectexplorer/target.h> +#include <projectexplorer/abstractprocessstep.h> #include <projectexplorer/buildconfiguration.h> #include <projectexplorer/buildtargetinfo.h> #include <projectexplorer/deployablefile.h> #include <projectexplorer/deploymentdata.h> #include <projectexplorer/processparameters.h> +#include <projectexplorer/projectconfigurationaspects.h> #include <projectexplorer/projectexplorerconstants.h> +#include <projectexplorer/project.h> #include <projectexplorer/runconfiguration.h> +#include <projectexplorer/target.h> #include <qtsupport/qtkitinformation.h> @@ -57,11 +59,62 @@ namespace Internal { const char ARGUMENTS_KEY[] = "WinRt.BuildStep.Deploy.Arguments"; const char DEFAULTARGUMENTS_KEY[] = "WinRt.BuildStep.Deploy.DefaultArguments"; -WinRtArgumentsAspect::WinRtArgumentsAspect() = default; +class WinRtArgumentsAspect final : public ProjectConfigurationAspect +{ + Q_DECLARE_TR_FUNCTIONS(WinRt::Internal::WinRtArgumentsAspect) + +public: + WinRtArgumentsAspect() = default; + + void addToLayout(LayoutBuilder &builder) final; + + void fromMap(const QVariantMap &map) final; + void toMap(QVariantMap &map) const final; + + void setValue(const QString &value); + QString value() const { return m_value; } + + void setDefaultValue(const QString &value) { m_defaultValue = value; } + QString defaultValue() const { return m_defaultValue; } + + void restoreDefaultValue(); + +private: + FancyLineEdit *m_lineEdit = nullptr; + QString m_value; + QString m_defaultValue; +}; + +class WinRtPackageDeploymentStep final : public AbstractProcessStep +{ + Q_DECLARE_TR_FUNCTIONS(WinRt::Internal::WinRtPackageDeploymentStep) + +public: + WinRtPackageDeploymentStep(BuildStepList *bsl, Core::Id id); + + QString defaultWinDeployQtArguments() const; -WinRtArgumentsAspect::~WinRtArgumentsAspect() = default; + void raiseError(const QString &errorMessage); + void raiseWarning(const QString &warningMessage); -void WinRtArgumentsAspect::addToLayout(ProjectExplorer::LayoutBuilder &builder) +private: + bool init() override; + void doRun() override; + bool processSucceeded(int exitCode, QProcess::ExitStatus status) override; + void stdOutput(const QString &line) override; + + bool parseIconsAndExecutableFromManifest(QString manifestFileName, QStringList *items, QString *executable); + + WinRtArgumentsAspect *m_argsAspect = nullptr; + QString m_targetFilePath; + QString m_targetDirPath; + QString m_executablePathInManifest; + QString m_mappingFileContent; + QString m_manifestFileName; + bool m_createMappingFile = false; +}; + +void WinRtArgumentsAspect::addToLayout(LayoutBuilder &builder) { QTC_CHECK(!m_lineEdit); auto label = new QLabel(tr("Arguments:")); @@ -109,21 +162,6 @@ void WinRtArgumentsAspect::setValue(const QString &value) emit changed(); } -QString WinRtArgumentsAspect::value() const -{ - return m_value; -} - -void WinRtArgumentsAspect::setDefaultValue(const QString &value) -{ - m_defaultValue = value; -} - -QString WinRtArgumentsAspect::defaultValue() const -{ - return m_defaultValue; -} - void WinRtArgumentsAspect::restoreDefaultValue() { if (m_defaultValue == m_value) @@ -187,7 +225,7 @@ bool WinRtPackageDeploymentStep::init() return false; } params->setCommandLine(windeployqt); - params->setEnvironment(buildConfiguration()->environment()); + params->setEnvironment(buildEnvironment()); return AbstractProcessStep::init(); } @@ -346,5 +384,19 @@ bool WinRtPackageDeploymentStep::parseIconsAndExecutableFromManifest(QString man return true; } +// WinRtDeployStepFactory + +WinRtDeployStepFactory::WinRtDeployStepFactory() +{ + registerStep<WinRtPackageDeploymentStep>(Constants::WINRT_BUILD_STEP_DEPLOY); + setDisplayName(QCoreApplication::translate("WinRt::Internal::WinRtDeployStepFactory", "Run windeployqt")); + setFlags(BuildStepInfo::Unclonable); + setSupportedStepList(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY); + setSupportedDeviceTypes({Constants::WINRT_DEVICE_TYPE_LOCAL, + Constants::WINRT_DEVICE_TYPE_EMULATOR, + Constants::WINRT_DEVICE_TYPE_PHONE}); + setRepeatable(false); +} + } // namespace Internal } // namespace WinRt diff --git a/src/plugins/winrt/winrtpackagedeploymentstep.h b/src/plugins/winrt/winrtpackagedeploymentstep.h index 2b1329db79..c20898ade9 100644 --- a/src/plugins/winrt/winrtpackagedeploymentstep.h +++ b/src/plugins/winrt/winrtpackagedeploymentstep.h @@ -25,66 +25,15 @@ #pragma once -#include <projectexplorer/abstractprocessstep.h> -#include <projectexplorer/projectconfigurationaspects.h> +#include <projectexplorer/buildstep.h> namespace WinRt { namespace Internal { -class WinRtArgumentsAspect : public ProjectExplorer::ProjectConfigurationAspect +class WinRtDeployStepFactory final : public ProjectExplorer::BuildStepFactory { - Q_OBJECT - public: - WinRtArgumentsAspect(); - ~WinRtArgumentsAspect() override; - - void addToLayout(ProjectExplorer::LayoutBuilder &builder) override; - - void fromMap(const QVariantMap &map) override; - void toMap(QVariantMap &map) const override; - - void setValue(const QString &value); - QString value() const; - - void setDefaultValue(const QString &value); - QString defaultValue() const; - - void restoreDefaultValue(); - -private: - Utils::FancyLineEdit *m_lineEdit = nullptr; - QString m_value; - QString m_defaultValue; -}; - -class WinRtPackageDeploymentStep : public ProjectExplorer::AbstractProcessStep -{ - Q_OBJECT - -public: - WinRtPackageDeploymentStep(ProjectExplorer::BuildStepList *bsl, Core::Id id); - - QString defaultWinDeployQtArguments() const; - - void raiseError(const QString &errorMessage); - void raiseWarning(const QString &warningMessage); - -private: - bool init() override; - void doRun() override; - bool processSucceeded(int exitCode, QProcess::ExitStatus status) override; - void stdOutput(const QString &line) override; - - bool parseIconsAndExecutableFromManifest(QString manifestFileName, QStringList *items, QString *executable); - - WinRtArgumentsAspect *m_argsAspect = nullptr; - QString m_targetFilePath; - QString m_targetDirPath; - QString m_executablePathInManifest; - QString m_mappingFileContent; - QString m_manifestFileName; - bool m_createMappingFile = false; + WinRtDeployStepFactory(); }; } // namespace Internal diff --git a/src/plugins/winrt/winrtplugin.cpp b/src/plugins/winrt/winrtplugin.cpp index c42cde7c17..314443e134 100644 --- a/src/plugins/winrt/winrtplugin.cpp +++ b/src/plugins/winrt/winrtplugin.cpp @@ -24,14 +24,16 @@ ****************************************************************************/ #include "winrtplugin.h" + #include "winrtconstants.h" -#include "winrtdevice.h" +#include "winrtdebugsupport.h" #include "winrtdeployconfiguration.h" -#include "winrtqtversion.h" +#include "winrtdevice.h" +#include "winrtpackagedeploymentstep.h" #include "winrtphoneqtversion.h" +#include "winrtqtversion.h" #include "winrtrunconfiguration.h" #include "winrtruncontrol.h" -#include "winrtdebugsupport.h" #include <projectexplorer/devicesupport/devicemanager.h> #include <projectexplorer/devicesupport/idevice.h> diff --git a/src/shared/help/bookmarkmanager.cpp b/src/shared/help/bookmarkmanager.cpp index c067334d4c..e67f910e9c 100644 --- a/src/shared/help/bookmarkmanager.cpp +++ b/src/shared/help/bookmarkmanager.cpp @@ -273,6 +273,7 @@ bool BookmarkDialog::eventFilter(QObject *object, QEvent *e) } } break; + case Qt::Key_Backspace: case Qt::Key_Delete: { bookmarkManager->removeBookmarkItem(ui.treeView, proxyModel->mapToSource(index)); @@ -489,7 +490,7 @@ bool BookmarkWidget::eventFilter(QObject *object, QEvent *e) treeView->edit(index); item->setEditable(false); } - } else if (ke->key() == Qt::Key_Delete) { + } else if (ke->key() == Qt::Key_Delete || ke->key() == Qt::Key_Backspace) { bookmarkManager->removeBookmarkItem(treeView, src); } } diff --git a/src/tools/qml2puppet/CMakeLists.txt b/src/tools/qml2puppet/CMakeLists.txt index da25ec5396..94bc6a2fce 100644 --- a/src/tools/qml2puppet/CMakeLists.txt +++ b/src/tools/qml2puppet/CMakeLists.txt @@ -97,19 +97,8 @@ extend_qtc_executable(qml2puppet FEATURE_INFO "Qt Quick 3D" DEPENDS Qt5::Quick3D Qt5::Quick3DPrivate DEFINES QUICK3D_MODULE -) - -extend_qtc_executable(qml2puppet - SOURCES_PREFIX "${SRCDIR}/interfaces" - SOURCES - commondefines.h - nodeinstanceclientinterface.h - nodeinstanceglobal.h - nodeinstanceserverinterface.cpp nodeinstanceserverinterface.h -) -extend_qtc_executable(qml2puppet - SOURCES_PREFIX "${SRCDIR}/qml2puppet/editor3d" + SOURCES_PREFIX "${SRCDIR}/qmlpuppet/editor3d" SOURCES generalhelper.cpp generalhelper.h mousearea3d.cpp mousearea3d.h @@ -121,6 +110,15 @@ extend_qtc_executable(qml2puppet ) extend_qtc_executable(qml2puppet + SOURCES_PREFIX "${SRCDIR}/interfaces" + SOURCES + commondefines.h + nodeinstanceclientinterface.h + nodeinstanceglobal.h + nodeinstanceserverinterface.cpp nodeinstanceserverinterface.h +) + +extend_qtc_executable(qml2puppet SOURCES_PREFIX "${SRCDIR}/qml2puppet/instances" SOURCES anchorchangesnodeinstance.cpp anchorchangesnodeinstance.h |