提交 042dd2bc 编写于 作者: baowanyu's avatar baowanyu 提交者: Jiangtao Hu

framework: split cc_library for cyber_monitor

上级 d2d199f2
......@@ -2,13 +2,14 @@ export CYBER_PATH=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
binary_path="/apollo/bazel-bin/cyber"
tool_path="/apollo/bazel-bin/cyber/tools"
recorder_path="${tool_path}/cyber_recorder"
monitor_path="${tool_path}/cyber_monitor"
PYTHON_LD_PATH="/apollo/bazel-bin/cyber/py_wrapper"
launch_path="${CYBER_PATH}/tools/cyber_launch"
qt_path=${CYBER_PATH}/../third_party/Qt5.5.1/5.5/gcc_64
export LD_LIBRARY_PATH=${qt_path}/lib:$LD_LIBRARY_PATH
export QT_QPA_PLATFORM_PLUGIN_PATH=${qt_path}/plugins
export PATH=${binary_path}:${tool_path}:${recorder_path}:${launch_path}:${qt_path}/bin:$PATH
export PATH=${binary_path}:${recorder_path}:${monitor_path}:${launch_path}:${qt_path}/bin:$PATH
export PYTHONPATH=${PYTHON_LD_PATH}:${CYBER_PATH}/python:$PYTHONPATH
export CYBER_DOMAIN_ID=80
......
load("//tools:cpplint.bzl", "cpplint")
package(default_visibility = ["//visibility:public"])
cc_binary(
name = "cyber_monitor",
srcs = glob([
"cvt/monitor/*.cc",
"cvt/monitor/*.h",
]),
deps = [
"//cyber:cyber_core",
],
linkopts = [
"-pthread",
"-lncurses"
],
#linkstatic = False,
)
#cpplint()
/******************************************************************************
* Copyright 2018 The Apollo Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
#include "./about_dialog.h"
#include "ui_about_dialog.h"
AboutDialog::AboutDialog(QWidget *parent)
: QDialog(parent), ui_(new Ui::AboutDialog) {
ui_->setupUi(this);
}
AboutDialog::~AboutDialog() { delete ui_; }
/******************************************************************************
* Copyright 2018 The Apollo Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
#ifndef TOOLS_CVT_VTOPOLOGY_ABOUTDIALOG_H_
#define TOOLS_CVT_VTOPOLOGY_ABOUTDIALOG_H_
#include <QDialog>
namespace Ui {
class AboutDialog;
}
class AboutDialog : public QDialog {
Q_OBJECT
public:
explicit AboutDialog(QWidget *parent = 0);
~AboutDialog();
private:
Ui::AboutDialog *ui_;
};
#endif // TOOLS_CVT_VTOPOLOGY_ABOUTDIALOG_H_
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AboutDialog</class>
<widget class="QDialog" name="AboutDialog">
<property name="windowModality">
<enum>Qt::ApplicationModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>443</width>
<height>121</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="infoLabel">
<property name="text">
<string>VTopology
One Visualization Tool for Presenting Cyber Topology</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="closePushButton">
<property name="text">
<string>close</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>closePushButton</sender>
<signal>clicked()</signal>
<receiver>AboutDialog</receiver>
<slot>close()</slot>
<hints>
<hint type="sourcelabel">
<x>416</x>
<y>232</y>
</hint>
<hint type="destinationlabel">
<x>456</x>
<y>250</y>
</hint>
</hints>
</connection>
</connections>
</ui>
/******************************************************************************
* Copyright 2018 The Apollo Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
#include "./arrow.h"
#include "./composite_item.h"
#include <cmath>
#include <iostream>
#include <QPainter>
#include <QPen>
constexpr double PI = 3.14159265358979323846264338327950288419716939937510;
constexpr double ArrowSize = 10;
Arrow::Arrow(CompositeItem *startItem, CompositeItem *endItem,
QGraphicsItem *parent)
: QGraphicsLineItem(parent),
start_item_(startItem),
end_item_(endItem),
polygon_() {
setPen(QPen(Qt::black, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
}
QRectF Arrow::boundingRect() const {
qreal extra = (pen().width() + 20) / 2.0;
return QRectF(line().p1(), QSizeF(line().p2().x() - line().p1().x(),
line().p2().y() - line().p1().y()))
.normalized()
.adjusted(-extra, -extra, extra, extra);
}
QPainterPath Arrow::shape() const {
QPainterPath path = QGraphicsLineItem::shape();
path.addPolygon(polygon_);
return path;
}
void Arrow::updatePosition() {
QLineF line(mapFromItem(start_item_, 0, 0), mapFromItem(end_item_, 0, 0));
setLine(line);
}
QPointF Arrow::Intersect(const QPolygonF &polygon, const QPointF &point,
const QLineF &line) {
QPointF p1 = polygon.first() + point;
QPointF p2;
QPointF intersectPoint(0, 0);
QLineF polyLine;
for (int i = 1; i < polygon.count(); ++i) {
p2 = polygon.at(i) + point;
polyLine = QLineF(p1, p2);
QLineF::IntersectType intersectType =
polyLine.intersect(line, &intersectPoint);
if (intersectType == QLineF::BoundedIntersection) break;
p1 = p2;
}
return intersectPoint;
}
void Arrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
QWidget *) {
if (start_item_->collidesWithItem(end_item_)) {
return;
}
painter->setPen(pen());
painter->setBrush(pen().color());
QPointF startPoint =
start_item_->pos() + QPointF(start_item_->boundingRect().width() / 2,
start_item_->boundingRect().height() / 2);
QPointF endPoint =
end_item_->pos() + QPointF(end_item_->boundingRect().width() / 2,
end_item_->boundingRect().height() / 2);
QLineF centerLine(startPoint, endPoint);
endPoint = Intersect(end_item_->polygon(), end_item_->pos(), centerLine);
startPoint =
Intersect(start_item_->polygon(), start_item_->pos(), centerLine);
setLine(QLineF(endPoint, startPoint));
double angle = std::acos(line().dx() / line().length());
if (line().dy() >= 0) angle = (PI * 2) - angle;
QPointF arrowP1 = line().p1() + QPointF(std::sin(angle + PI / 3) * ArrowSize,
std::cos(angle + PI / 3) * ArrowSize);
QPointF arrowP2 =
line().p1() + QPointF(std::sin(angle + PI - PI / 3) * ArrowSize,
std::cos(angle + PI - PI / 3) * ArrowSize);
polygon_.clear();
polygon_ << line().p1() << arrowP1 << arrowP2;
painter->drawLine(line());
painter->drawPolygon(polygon_);
}
/******************************************************************************
* Copyright 2018 The Apollo Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
#ifndef TOOLS_CVT_VTOPOLOGY_ARROW_H_
#define TOOLS_CVT_VTOPOLOGY_ARROW_H_
#include <QColor>
#include <QGraphicsLineItem>
#include <QPainterPath>
#include <QPen>
#include <QRectF>
#include <QString>
class CompositeItem;
class Arrow : public QGraphicsLineItem {
public:
enum { Type = UserType + 9 };
Arrow(CompositeItem *startItem, CompositeItem *endItem,
QGraphicsItem *parent = nullptr);
~Arrow() {
start_item_ = nullptr;
end_item_ = nullptr;
}
int type() const override { return Type; }
QRectF boundingRect() const override;
QPainterPath shape() const override;
CompositeItem *start_item() const { return start_item_; }
CompositeItem *end_item() const { return end_item_; }
void updatePosition();
protected:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget = 0) override;
private:
static QPointF Intersect(const QPolygonF &polygon, const QPointF &point,
const QLineF &line);
CompositeItem *start_item_;
CompositeItem *end_item_;
QPolygonF polygon_;
};
#endif // TOOLS_CVT_VTOPOLOGY_ARROW_H_
/******************************************************************************
* Copyright 2018 The Apollo Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
#include "./composite_item.h"
#include "./arrow.h"
#include <QGraphicsScene>
#include <QPainter>
#include <QPainterPath>
#include <iostream>
CompositeItem::CompositeItem(ItemType itemType, const QString &text,
QGraphicsItem *parent)
: QGraphicsItemGroup(parent),
item_type_(itemType),
old_pen_(Qt::black),
current_pen_(Qt::black),
text_(text),
shape_() {
QRectF rect = text_.boundingRect();
QPainterPath path;
switch (itemType) {
case ItemType::Node:
rect.adjust(-8, -8, 8, 8);
path.addEllipse(rect);
break;
case ItemType::Channel:
default:
path.addRect(rect);
break;
}
shape_.setPolygon(path.toFillPolygon());
addToGroup(&text_);
addToGroup(&shape_);
setFocusProxy(&shape_);
setFlag(QGraphicsItem::ItemIsMovable);
setFlag(QGraphicsItem::ItemIsSelectable);
}
QPolygonF CompositeItem::polygon() const { return shape_.polygon(); }
void CompositeItem::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget) {
text_.setDefaultTextColor(current_pen_.color());
text_.paint(painter, option, widget);
shape_.setPen(current_pen_);
shape_.paint(painter, option, widget);
}
void CompositeItem::hoverEnterEvent(QGraphicsSceneHoverEvent * /*event*/) {
old_pen_ = current_pen_;
current_pen_.setColor(Qt::red);
}
void CompositeItem::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/) {
current_pen_ = old_pen_;
}
void CompositeItem::removeArrow(Arrow *arrow) {
int index = arrows_.indexOf(arrow);
if (index != -1) arrows_.removeAt(index);
}
void CompositeItem::removeArrows() {
for (Arrow *arrow : arrows_) {
arrow->setVisible(false);
if (arrow->start_item() != this) arrow->start_item()->removeArrow(arrow);
if (arrow->end_item() != this) arrow->end_item()->removeArrow(arrow);
scene()->removeItem(arrow);
delete arrow;
}
arrows_.clear();
}
QVariant CompositeItem::itemChange(GraphicsItemChange change,
const QVariant &value) {
if (change == QGraphicsItem::ItemPositionChange) {
for (Arrow *arrow : arrows_) {
arrow->updatePosition();
}
}
return value;
}
/******************************************************************************
* Copyright 2018 The Apollo Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
#ifndef TOOLS_CVT_VTOPOLOGY_COMPOSITEITEM_H_
#define TOOLS_CVT_VTOPOLOGY_COMPOSITEITEM_H_
#include <QGraphicsItemGroup>
#include <QGraphicsPolygonItem>
#include <QGraphicsTextItem>
#include <QList>
#include <QPen>
#include <QVariant>
class Arrow;
class CompositeItem : public QGraphicsItemGroup {
public:
enum { Type = UserType + 10 };
enum ItemType { Node, Channel };
CompositeItem(ItemType itemType, const QString& text,
QGraphicsItem* parent = 0);
void SetPenColor(const QColor& c) {
old_pen_.setColor(c);
current_pen_.setColor(c);
}
QColor CurrentPenColor(void) const { return current_pen_.color(); }
QColor OldPenColor(void) const { return old_pen_.color(); }
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option,
QWidget* widget = 0) override;
int type() const override { return Type; }
const QString text(void) const { return text_.toPlainText(); }
QPolygonF polygon() const;
void AddArrow(Arrow* arrow) {
if (arrow) {
arrows_.append(arrow);
}
}
void removeArrow(Arrow* arrow);
void removeArrows(void);
protected:
QVariant itemChange(GraphicsItemChange change,
const QVariant& value) override;
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent* event);
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* event);
private:
ItemType item_type_;
QPen old_pen_;
QPen current_pen_;
QGraphicsTextItem text_;
QGraphicsPolygonItem shape_;
QList<Arrow*> arrows_;
};
#endif // COMPOSITEITEM_H
/******************************************************************************
* Copyright 2018 The Apollo Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
#include "./interactive_graphicsview.h"
#include <iostream>
#include <QKeyEvent>
#include <QWheelEvent>
namespace {
constexpr double translate_speed_ = 1.0;
constexpr double zoom_delta_ = 0.1;
}
InteractiveGraphicsView::InteractiveGraphicsView(QWidget *parent)
: QGraphicsView(parent) {
init();
}
InteractiveGraphicsView::InteractiveGraphicsView(QGraphicsScene *scene,
QWidget *parent)
: QGraphicsView(scene, parent) {
init();
}
void InteractiveGraphicsView::init(void) {
mouse_left_button_pressed_ = false;
scaleVal_ = 1.0;
setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
setCursor(Qt::PointingHandCursor);
setRenderHint(QPainter::Antialiasing);
setSceneRect(INT_MIN, INT_MIN, INT_MAX, INT_MAX);
centerOn(0, 0);
}
void InteractiveGraphicsView::keyPressEvent(QKeyEvent *event) {
switch (event->key()) {
case Qt::Key_Up:
translate(QPointF(0, -2));
goto acceptLabel;
case Qt::Key_Down:
translate(QPointF(0, 2));
goto acceptLabel;
case Qt::Key_Left:
translate(QPointF(-2, 0));
goto acceptLabel;
case Qt::Key_Right:
translate(QPointF(2, 0));
goto acceptLabel;
case Qt::Key_Plus:
zoom_in();
goto acceptLabel;
case Qt::Key_Minus:
zoom_out();
acceptLabel:
event->setAccepted(true);
default:
QGraphicsView::keyPressEvent(event);
}
}
void InteractiveGraphicsView::mouseMoveEvent(QMouseEvent *event) {
if (mouse_left_button_pressed_) {
QPointF mouseDelta = mapToScene(event->pos()) - mapToScene(last_mouse_pos_);
translate(mouseDelta);
}
last_mouse_pos_ = event->pos();
QGraphicsView::mouseMoveEvent(event);
}
void InteractiveGraphicsView::mousePressEvent(QMouseEvent *event) {
if (event->button() == Qt::LeftButton) {
QPointF point = mapToScene(event->pos());
if (scene()->itemAt(point, transform()) == nullptr) {
last_mouse_pos_ = event->pos();
mouse_left_button_pressed_ = true;
}
}
QGraphicsView::mousePressEvent(event);
}
void InteractiveGraphicsView::mouseReleaseEvent(QMouseEvent *event) {
mouse_left_button_pressed_ = false;
QGraphicsView::mouseReleaseEvent(event);
}
void InteractiveGraphicsView::wheelEvent(QWheelEvent *event) {
QPoint scrollAmount = event->angleDelta();
scrollAmount.y() > 0 ? zoom_in() : zoom_out();
}
void InteractiveGraphicsView::zoom_in() { zoom(1 + zoom_delta_); }
void InteractiveGraphicsView::zoom_out() { zoom(1 - zoom_delta_); }
void InteractiveGraphicsView::zoom(float scalValue) {
double factor = transform()
.scale(scalValue, scalValue)
.mapRect(QRectF(0, 0, 1, 1))
.width();
if (factor < 0.07 || factor > 100) return;
scale(scalValue, scalValue);
scaleVal_ *= scalValue;
}
void InteractiveGraphicsView::translate(QPointF delta) {
delta *= scaleVal_;
delta *= translate_speed_;
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
QPoint newCenter(viewport()->rect().width() / 2 - delta.x(),
viewport()->rect().height() / 2 - delta.y());
centerOn(mapToScene(newCenter));
setTransformationAnchor(QGraphicsView::AnchorViewCenter);
}
/******************************************************************************
* Copyright 2018 The Apollo Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
#ifndef TOOLS_CVT_VTOPOLOGY_INTERACTIVEGRAPHICSVIEW_H_
#define TOOLS_CVT_VTOPOLOGY_INTERACTIVEGRAPHICSVIEW_H_
#include <QGraphicsView>
class InteractiveGraphicsView : public QGraphicsView {
Q_OBJECT
public:
explicit InteractiveGraphicsView(QWidget *parent = 0);
explicit InteractiveGraphicsView(QGraphicsScene *scene, QWidget *parent = 0);
~InteractiveGraphicsView() {}
void zoom_in();
void zoom_out();
void zoom(float scaleValue);
void translate(QPointF deltaVal);
protected:
void keyPressEvent(QKeyEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
private:
void init(void);
bool mouse_left_button_pressed_;
QPoint last_mouse_pos_;
double scaleVal_;
};
#endif // INTERACTIVEGRAPHICSVIEW_H
/******************************************************************************
* Copyright 2018 The Apollo Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
#include <QApplication>
#include <QSurfaceFormat>
#include "./main_window.h"
#include "cyber/init.h"
#include "cyber/service_discovery/topology_manager.h"
int main(int argc, char* argv[]) {
QApplication a(argc, argv);
MainWindow w;
apollo::cyber::Init(argv[0]);
auto topologyCallback =
[&w](const apollo::cyber::proto::ChangeMsg& change_msg) {
w.TopologyChanged(change_msg);
};
auto channelManager =
apollo::cyber::service_discovery::TopologyManager::Instance()
->channel_manager();
channelManager->AddChangeListener(topologyCallback);
w.show();
return a.exec();
}
/******************************************************************************
* Copyright 2018 The Apollo Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
#include "./main_window.h"
#include "./arrow.h"
#include "cyber/init.h"
#include "cyber/proto/topology_change.pb.h"
#include "ui_main_window.h"
#include <QCheckBox>
#include <QColorDialog>
#include <QDebug>
#include <QFileDialog>
#include <QFileInfo>
#include <QGraphicsScene>
#include <QMessageBox>
#include <QTreeWidgetItem>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#define MEMBER_OFFSET(StructType, Member) \
(size_t)( \
reinterpret_cast<char*>(&(reinterpret_cast<StructType*>(1)->Member)) - \
1)
#define StructPtrByMemberPtr(MemberPtr, StructType, Member) \
reinterpret_cast<StructType*>(reinterpret_cast<char*>(MemberPtr) - \
MEMBER_OFFSET(StructType, Member))
namespace {
inline void updateMaxVec(const QRectF& rect, QVector2D& v) {
if (rect.width() > v.x()) {
v.setX(rect.width());
}
if (rect.height() > v.y()) {
v.setY(rect.height());
}
}
} // namespace
struct MainWindow::ChannelData {
CompositeItem _sceneItem;
QTreeWidgetItem _treeItem;
ChannelData(const ::QString& text, ::CompositeItem::ItemType itemType);
};
MainWindow::ChannelData::ChannelData(const ::QString& text,
::CompositeItem::ItemType itemType)
: _sceneItem(itemType, text), _treeItem() {
_treeItem.setText(0, text);
}
struct MainWindow::ChannelDataSet {
MainWindow::ChannelData* _channelData;
std::vector<MainWindow::ChannelData*> _reader_nodes;
std::vector<MainWindow::ChannelData*> _writer_nodes;
};
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent),
ui_(new Ui::MainWindow),
about_dialog_(new AboutDialog),
focused_item_(nullptr),
topology_scene_(new QGraphicsScene(this)),
refresh_timer_(this),
item_raw_color_(Qt::black),
max_rect_(-1, -1) {
ui_->setupUi(this);
{
QStringList tmp;
tmp << "Channels";
all_channel_root_ = new QTreeWidgetItem(tmp);
ui_->treeWidget->addTopLevelItem(all_channel_root_);
tmp.clear();
tmp << "Readers";
all_reader_root_ = new QTreeWidgetItem(tmp);
ui_->treeWidget->addTopLevelItem(all_reader_root_);
tmp.clear();
tmp << "Writers";
all_writer_root_ = new QTreeWidgetItem(tmp);
ui_->treeWidget->addTopLevelItem(all_writer_root_);
}
topology_scene_->setSceneRect(QRectF(0, 0, 2000, 2000));
ui_->graphicsView->setScene(topology_scene_);
connect(ui_->actionAbout, SIGNAL(triggered()), about_dialog_, SLOT(show()));
connect(ui_->treeWidget, SIGNAL(doubleClicked(QModelIndex)), this,
SLOT(TreeItemChanged(void)));
connect(topology_scene_, SIGNAL(selectionChanged()), this,
SLOT(SceneItemSelectionChanged(void)));
refresh_timer_.setInterval(40);
connect(&refresh_timer_, SIGNAL(timeout()), this, SLOT(UpdateSceneItem()));
refresh_timer_.start();
}
MainWindow::~MainWindow() {
apollo::cyber::Shutdown();
all_channel_root_->takeChildren();
all_reader_root_->takeChildren();
all_writer_root_->takeChildren();
topology_scene_->clear();
for (auto iter = channel_reader_writer_map_.begin();
iter != channel_reader_writer_map_.end(); ++iter) {
delete iter->second;
}
delete ui_;
delete about_dialog_;
}
void MainWindow::TopologyChanged(
const apollo::cyber::proto::ChangeMsg& change_msg) {
const std::string& channelName = change_msg.role_attr().channel_name();
const std::string& nodeName = change_msg.role_attr().node_name();
ChangeSceneItemFunc changeSceneFunc = &MainWindow::AddSceneItem;
if (change_msg.operate_type() ==
apollo::cyber::proto::OperateType::OPT_LEAVE) {
changeSceneFunc = &MainWindow::RemoveSceneItem;
}
if (change_msg.change_type() ==
apollo::cyber::proto::ChangeType::CHANGE_CHANNEL) {
if (change_msg.role_type() ==
apollo::cyber::proto::RoleType::ROLE_WRITER) {
(this->*changeSceneFunc)(channelName, nodeName, false);
}
if (change_msg.role_type() ==
apollo::cyber::proto::RoleType::ROLE_READER) {
(this->*changeSceneFunc)(channelName, nodeName, true);
}
}
}
inline Arrow* MainWindow::createArrow(CompositeItem* startItem,
CompositeItem* endItem) {
Arrow* a = new Arrow(startItem, endItem);
if (a) {
startItem->AddArrow(a);
endItem->AddArrow(a);
buffer_list_.append(a);
}
return a;
}
inline void MainWindow::delSceneItemAndArrow(MainWindow::ChannelData* item) {
if (item) {
delete_list_.append(item);
}
}
void MainWindow::UpdateSceneItem() {
if (!buffer_list_.isEmpty() || !delete_list_.isEmpty()) {
AdjustSceneLayout();
}
while (!buffer_list_.isEmpty()) {
topology_scene_->addItem(buffer_list_.takeFirst());
}
while (!delete_list_.isEmpty()) {
ChannelData* item = delete_list_.takeFirst();
item->_sceneItem.setVisible(false);
item->_sceneItem.removeArrows();
topology_scene_->removeItem(&(item->_sceneItem));
delete item;
}
topology_scene_->update();
}
void MainWindow::AddSceneItem(const std::string& channelName,
const std::string& nodeName, bool isReader) {
auto iter = channel_reader_writer_map_.find(channelName);
if (iter == channel_reader_writer_map_.cend()) {
auto dataSet = new ChannelDataSet();
if (dataSet == nullptr) return;
dataSet->_channelData =
new ChannelData(QString(channelName.c_str()), CompositeItem::Channel);
if (dataSet->_channelData == nullptr) {
delete dataSet;
return;
}
ChannelData* nodeData =
new ChannelData(QString(nodeName.c_str()), CompositeItem::Node);
if (nodeData == nullptr) {
delete dataSet;
return;
}
updateMaxVec(dataSet->_channelData->_sceneItem.boundingRect(), max_rect_);
if (isReader) {
dataSet->_reader_nodes.push_back(nodeData);
createArrow(&(dataSet->_channelData->_sceneItem),
&(nodeData->_sceneItem));
all_reader_root_->addChild(&(nodeData->_treeItem));
} else {
dataSet->_writer_nodes.push_back(nodeData);
createArrow(&(nodeData->_sceneItem),
&(dataSet->_channelData->_sceneItem));
all_writer_root_->addChild(&(nodeData->_treeItem));
}
updateMaxVec(nodeData->_sceneItem.boundingRect(), max_rect_);
all_channel_root_->addChild(&(dataSet->_channelData->_treeItem));
buffer_list_.append(&(dataSet->_channelData->_sceneItem));
buffer_list_.append(&(nodeData->_sceneItem));
channel_reader_writer_map_[channelName] = dataSet;
} else {
ChannelData* nodeData =
new ChannelData(QString(nodeName.c_str()), CompositeItem::Node);
if (nodeData == nullptr) {
return;
}
if (isReader) {
iter->second->_reader_nodes.push_back(nodeData);
createArrow(&(iter->second->_channelData->_sceneItem),
&(nodeData->_sceneItem));
all_reader_root_->addChild(&(nodeData->_treeItem));
} else {
iter->second->_writer_nodes.push_back(nodeData);
createArrow(&(nodeData->_sceneItem),
&(iter->second->_channelData->_sceneItem));
all_writer_root_->addChild(&(nodeData->_treeItem));
}
updateMaxVec(nodeData->_sceneItem.boundingRect(), max_rect_);
buffer_list_.append(&(nodeData->_sceneItem));
}
ui_->treeWidget->setRootIsDecorated(true);
}
void MainWindow::RemoveSceneItem(const std::string& channelName,
const std::string& nodeName, bool isReader) {
auto iter = channel_reader_writer_map_.find(channelName);
if (iter != channel_reader_writer_map_.cend()) {
ChannelData* item = nullptr;
std::vector<ChannelData*>* nodesPtr = isReader
? &(iter->second->_reader_nodes)
: &(iter->second->_writer_nodes);
for (auto nodeIter = nodesPtr->begin(); nodeIter != nodesPtr->end();
++nodeIter) {
if ((*nodeIter)->_sceneItem.text().toStdString() == nodeName) {
item = *nodeIter;
*nodeIter = nullptr;
nodesPtr->erase(nodeIter);
break;
}
}
if (item) {
QTreeWidgetItem* root = isReader ? all_reader_root_ : all_writer_root_;
root->removeChild(&(item->_treeItem));
delSceneItemAndArrow(item);
}
if (!iter->second->_reader_nodes.size() &&
!iter->second->_writer_nodes.size()) {
all_channel_root_->removeChild(&(iter->second->_channelData->_treeItem));
delSceneItemAndArrow(iter->second->_channelData);
iter->second = nullptr;
channel_reader_writer_map_.erase(iter);
}
}
}
void MainWindow::AdjustSceneLayout(void) {
int index = 0;
int baseH = 0;
int maxCellHeight = max_rect_.y();
int maxCellWidth = max_rect_.x();
maxCellWidth += 5;
int w2 = (topology_scene_->width() - maxCellWidth) / 2;
for (auto iter = channel_reader_writer_map_.begin();
iter != channel_reader_writer_map_.end(); ++iter, ++index) {
unsigned s = iter->second->_reader_nodes.size();
if (s < iter->second->_writer_nodes.size())
s = iter->second->_writer_nodes.size();
s /= 2;
++s;
baseH = baseH + s * maxCellHeight;
iter->second->_channelData->_sceneItem.setPos(w2, baseH);
int rwH, rwIndex;
int w = w2 - maxCellWidth / 3 -
(iter->second->_writer_nodes.size() + 1) / 2 * maxCellWidth;
rwIndex = 0;
auto rwIter = iter->second->_writer_nodes.begin();
for (; rwIter != iter->second->_writer_nodes.end(); ++rwIter, ++rwIndex) {
rwH = (rwIndex + 1) / 2 * maxCellHeight;
if (rwIndex & 1)
rwH = baseH - rwH;
else
rwH = baseH + rwH;
(*rwIter)->_sceneItem.setPos(w + (rwIndex + 1) / 2 * maxCellWidth, rwH);
}
w = w2 + maxCellWidth / 3 +
(iter->second->_reader_nodes.size() + 1) / 2 * maxCellWidth;
rwIndex = 0;
rwIter = iter->second->_reader_nodes.begin();
for (; rwIter != iter->second->_reader_nodes.end(); ++rwIter, ++rwIndex) {
rwH = (rwIndex + 1) / 2 * maxCellHeight;
if (rwIndex & 1)
rwH = baseH - rwH;
else
rwH = baseH + rwH;
(*rwIter)->_sceneItem.setPos(w - (rwIndex + 1) / 2 * maxCellWidth, rwH);
}
baseH += s * maxCellHeight;
}
}
void MainWindow::TreeItemChanged(void) {
QTreeWidgetItem* item = ui_->treeWidget->currentItem();
if (item) {
if (item == all_channel_root_) return;
if (item == all_reader_root_) return;
if (item == all_writer_root_) return;
ChannelData* channelData =
StructPtrByMemberPtr(item, ChannelData, _treeItem);
if (focused_item_ == &channelData->_sceneItem) {
return;
}
if (focused_item_) {
focused_item_->SetPenColor(item_raw_color_);
}
focused_item_ = &channelData->_sceneItem;
item_raw_color_ = focused_item_->CurrentPenColor();
focused_item_->SetPenColor(Qt::green);
topology_scene_->setFocusItem(focused_item_);
ui_->graphicsView->centerOn(focused_item_);
}
}
void MainWindow::SceneItemSelectionChanged(void) {
QGraphicsItem* item = topology_scene_->mouseGrabberItem();
if (item == nullptr) {
ui_->graphicsView->clearFocus();
ui_->treeWidget->clearFocus();
return;
}
item = item->parentItem();
if (item == nullptr) return;
if (item == focused_item_) return;
if (focused_item_) {
focused_item_->SetPenColor(item_raw_color_);
}
focused_item_ = static_cast<CompositeItem*>(item);
item_raw_color_ = focused_item_->OldPenColor();
focused_item_->SetPenColor(Qt::green);
ChannelData* channelData =
StructPtrByMemberPtr(focused_item_, ChannelData, _sceneItem);
channelData->_treeItem.parent()->setExpanded(true);
ui_->treeWidget->setCurrentItem(&channelData->_treeItem);
}
/******************************************************************************
* Copyright 2018 The Apollo Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
#ifndef TOOLS_CVT_VTOPOLOGY_MAINWINDOW_H_
#define TOOLS_CVT_VTOPOLOGY_MAINWINDOW_H_
#include <QColor>
#include <QList>
#include <QMainWindow>
#include <QMutex>
#include <QPixmap>
#include <QTimer>
#include <QVector2D>
#include <map>
#include <memory>
#include <string>
#include "./about_dialog.h"
#include "./composite_item.h"
class QTreeWidgetItem;
class GraphicsScene;
class QGraphicsItem;
class Arrow;
namespace Ui {
class MainWindow;
}
namespace apollo {
namespace cyber {
namespace proto {
class ChangeMsg;
}
} // namespace cyber
} // namespace apollo
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget* parent = nullptr);
~MainWindow();
void TopologyChanged(const apollo::cyber::proto::ChangeMsg& change_msg);
private slots:
void UpdateSceneItem(void);
void TreeItemChanged(void);
void SceneItemSelectionChanged(void);
private:
struct ChannelData;
void AddSceneItem(const std::string& channelName, const std::string& nodeName,
bool isReader);
void RemoveSceneItem(const std::string& channelName,
const std::string& nodeName, bool isReader);
using ChangeSceneItemFunc =
void (MainWindow::*)(const std::string& channelName,
const std::string& nodeName, bool isReader);
Arrow* createArrow(CompositeItem* startItem, CompositeItem* endItem);
void delSceneItemAndArrow(ChannelData* item);
void AdjustSceneLayout(void);
Ui::MainWindow* ui_;
AboutDialog* about_dialog_;
QTreeWidgetItem* all_channel_root_;
QTreeWidgetItem* all_reader_root_;
QTreeWidgetItem* all_writer_root_;
CompositeItem* focused_item_;
QGraphicsScene* topology_scene_;
QTimer refresh_timer_;
QColor item_raw_color_;
QVector2D max_rect_;
QList<QGraphicsItem*> buffer_list_;
QList<ChannelData*> delete_list_;
struct ChannelDataSet;
std::map<std::string, ChannelDataSet*> channel_reader_writer_map_;
};
#endif // MAINWINDOW_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1049</width>
<height>807</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>VTopology</string>
</property>
<widget class="QWidget" name="centralWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QTreeWidget" name="treeWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>512</width>
<height>16777215</height>
</size>
</property>
<column>
<property name="text">
<string/>
</property>
</column>
</widget>
<widget class="InteractiveGraphicsView" name="graphicsView"/>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1049</width>
<height>25</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="actionGlobal"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="actionExit"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>Help</string>
</property>
<addaction name="actionAbout"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuHelp"/>
</widget>
<action name="actionExit">
<property name="text">
<string>Exit</string>
</property>
</action>
<action name="actionAbout">
<property name="text">
<string>About</string>
</property>
</action>
<action name="actionGlobal">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Global</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>InteractiveGraphicsView</class>
<extends>QGraphicsView</extends>
<header>interactive_graphicsview.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>actionExit</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>close()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>199</x>
<y>149</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionGlobal</sender>
<signal>toggled(bool)</signal>
<receiver>treeWidget</receiver>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>264</x>
<y>415</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>OnStepSlideChanged(int)</slot>
<slot>OnCameraTypeChanged(int)</slot>
<slot>SetLeftDockHidden(bool)</slot>
<slot>SetRightDockHidden(bool)</slot>
<slot>ActionOpenImage()</slot>
<slot>ActionOpenPointCloud()</slot>
<slot>ActionGlobalView(bool)</slot>
<slot>ActionSceneCamera(bool)</slot>
<slot>ActionDelVideoImage()</slot>
<slot>UpdateActions()</slot>
<slot>ActionAddGrid()</slot>
</slots>
</ui>
load("//tools:cpplint.bzl", "cpplint")
package(default_visibility = ["//visibility:public"])
cc_binary(
name = "cyber_monitor",
srcs = [
"channel_msg_factory.cc",
"cyber_channel_message.cc",
"cyber_topology_message.cc",
"general_channel_message.cc",
"general_message.cc",
"general_message_base.cc",
"main.cc",
"renderable_message.cc",
"screen.cc",
],
deps = [
"channel_msg_factory",
"cyber_channel_message",
"cyber_topology_message",
"general_channel_message",
"screen",
"//cyber:init",
"//cyber/service_discovery:topology_manager",
],
linkopts = [
"-pthread",
"-lncurses"
],
)
cc_library(
name = "channel_msg_factory",
hdrs = [ "channel_msg_factory.h", ],
)
cc_library(
name = "cyber_channel_message",
hdrs = [ "cyber_channel_message.h", ],
deps = [
"general_message",
"renderable_message",
"//cyber:cyber",
"//cyber/time:time",
"//cyber/time:duration",
],
)
cc_library(
name = "cyber_topology_message",
hdrs = [ "cyber_topology_message.h", ],
deps = [
"renderable_message",
],
)
cc_library(
name = "general_channel_message",
hdrs = [ "general_channel_message.h", ],
deps = [
"general_message_base",
"general_message",
"screen",
"//cyber/message:raw_message"
],
)
cc_library(
name = "general_message",
hdrs = [ "general_message.h", ],
deps = [
"general_message_base",
"//cyber:cyber",
"//cyber/message:raw_message",
],
)
cc_library(
name = "general_message_base",
hdrs = [ "general_message_base.h", ],
deps = [
"renderable_message",
],
)
cc_library(
name = "renderable_message",
hdrs = [ "renderable_message.h", ],
deps = [
"screen",
],
)
cc_library(
name = "screen",
hdrs = [ "screen.h", ],
)
#cpplint()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册