mirror of
https://github.com/Linloir/GraphBuilder.git
synced 2025-12-18 20:48:12 +08:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e965427be4 | |||
| 629698c05c | |||
| 06fb056c09 | |||
| 6309cce382 | |||
| 5a5a3541bf | |||
| 002b291023 | |||
|
|
c2059dad4b | ||
| 354da102e5 | |||
| f735ff31d4 | |||
| dd1fc7f34b | |||
| 234994c385 | |||
| fe61551f36 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -15,6 +15,7 @@ object_script.*.Debug
|
|||||||
*_plugin_import.cpp
|
*_plugin_import.cpp
|
||||||
/.qmake.cache
|
/.qmake.cache
|
||||||
/.qmake.stash
|
/.qmake.stash
|
||||||
|
/build
|
||||||
*.pro.user
|
*.pro.user
|
||||||
*.pro.user.*
|
*.pro.user.*
|
||||||
*.qbs.user
|
*.qbs.user
|
||||||
|
|||||||
181
GraphBuilder_Commentary.md
Normal file
181
GraphBuilder_Commentary.md
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
# 从头开始完成GraphBuilder工程
|
||||||
|
|
||||||
|
## 实验要求
|
||||||
|
|
||||||
|
1. 以邻接多重表为存储结构,实现联通无向图的深度优先和广度优先遍历。以指定的节点为起点,分别输出每种遍历下的节点访问序列和相应生成树的边集。
|
||||||
|
2. 以邻接表为存储结构,建立深度优先生成树和广度优先生成树,并以树型输出生成树。
|
||||||
|
3. 测试数据如图:
|
||||||
|
|
||||||
|
## 分析需求
|
||||||
|
|
||||||
|
> 在本节中将分析上述题目要求,大致明确程序所需要完成的模块及功能
|
||||||
|
|
||||||
|
由于需要以树型输出生成树,因此最好能够实现**可视化控件**,其需要支持显示图结构
|
||||||
|
|
||||||
|
为了便于添加点和线,故可视化控件需要支持**添加及删除点和线**的功能
|
||||||
|
|
||||||
|
从测试数据图中看出,输入的数据为带权图,因此对于该控件还需要实现**添加及修改权重**的功能
|
||||||
|
|
||||||
|
由于需要进行遍历,为了体现遍历过程,该控件需要实现**创建节点和边的访问动画**功能
|
||||||
|
|
||||||
|
在数据结构层面,需要实现**邻接表**和**邻接多重表**两种数据结构
|
||||||
|
|
||||||
|
为了避免演示时不同数据结构需要分开建立测试数据,因此需要为两种不同的数据结构实现一个**虚基类**,并使两种不同的结构均从该虚基类继承并添加**转换函数**,实现两种不同数据结构的互相转换
|
||||||
|
|
||||||
|
## 程序设计
|
||||||
|
|
||||||
|
> 在本节中,将依据上述需求,对各个需要实现的模块进行更进一步的分析,并给出其实现的过程
|
||||||
|
|
||||||
|
从上述需求可以看出,实现最基本的功能大致需要将程序分为两个主要部分:
|
||||||
|
|
||||||
|
- **可视化控件**:类画板控件,负责处理图中点和线的元素对象的显示、修改等操作,并为数据结构提供功能接口,诸如调用动画等
|
||||||
|
- **数据结构**:需要使用要求的数据结构类将上述可视化控件中的元素对象组织起来,并调用其提供的接口实现如深度优先遍历等功能
|
||||||
|
|
||||||
|
下面将依次完成这两个主要部分
|
||||||
|
|
||||||
|
### 可视化控件(画板)
|
||||||
|
|
||||||
|
由于需要实现的这个可视化控件的主要功能是**对图元对象进行管理并使它们可视化**。
|
||||||
|
|
||||||
|
QT中已有的`QGraphicsView`具有相似的功能,在文档中有如下描述:
|
||||||
|
|
||||||
|
> The QGraphicsView class provides a widget for displaying the contents of a QGraphicsScene
|
||||||
|
>
|
||||||
|
> QGraphicsView类是一个将QGraphicsScene场景中的内容可视化显示出来的控件
|
||||||
|
|
||||||
|
其中,`QGraphicsScene`是管理所有图元的场景,其在文档中的描述如下:
|
||||||
|
|
||||||
|
> The QGraphicsScene class provides a surface for managing large number of 2D graphical items
|
||||||
|
>
|
||||||
|
> QGraphicsScene类提供了一个管理大量2D图形项的平台
|
||||||
|
|
||||||
|
而`QGraphicsScene`所管理的图形项均继承自`QGraphicsItem`,也就是说对于所有继承自`QGraphicsItem`的图形项目,都可以通过`QGraphicsScene`进行管理,并使用`QGraphicsView`来显示
|
||||||
|
|
||||||
|
但是由于不论是`QGraphicsView`还是`QGraphicsItem`,所提供的功能都不足以满足本次项目的功能,因此需要从它们继承并完成新类如下:
|
||||||
|
|
||||||
|
<!--
|
||||||
|
由上述`QGraphicsView`、`QGraphicsScene`以及`QGraphicsItem`的关系可以得知,本次需要完成如下新类:
|
||||||
|
-->
|
||||||
|
|
||||||
|
- `MyGraphicsView`:继承自`QGraphicsView`,添加对鼠标操作的判定和响应、动画队列等功能
|
||||||
|
- `MyGraphicsVexItem`:继承自`QGraphicsItem`,完成点的绘制和对应功能
|
||||||
|
- `MyGraphicsLineItem`:继承自`QGraphicsItem`,完成线的绘制和对应功能
|
||||||
|
|
||||||
|
下面,我将按照最初的设计思路带大家完成这三个类的实现:
|
||||||
|
|
||||||
|
#### 首先,绘制一个点
|
||||||
|
|
||||||
|
目前为止,我们面对的任务有:
|
||||||
|
|
||||||
|
- 设计点对应的`MyGraphicsVexItem`类
|
||||||
|
- 设计线对应的`MyGraphicsLineItem`类
|
||||||
|
- 设计视图框架`MyGraphicsView`将点和线联系起来
|
||||||
|
|
||||||
|
按照先挑软柿子捏的逻辑,`MyGraphicsVexItem`类应当是最先进行设计的
|
||||||
|
|
||||||
|
首先,先不考虑其他一切问题,如果仅仅只需要在视图场景中绘制一个点,由于点实际上的显示效果是一个圆,因此可以使用`QGraphicsEllipseItem`类:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <QGraphicsView>
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
#include <QGraphicsEllipseItem>
|
||||||
|
|
||||||
|
/* Declaration of Graphics View and Graphics Scene */
|
||||||
|
QGraphicsView* myView = new QGraphicsView;
|
||||||
|
QGraphicsScene* myScene = new QGraphicsScene;
|
||||||
|
myScene->setSceneRect(-100, -100, 200, 200);
|
||||||
|
myView->setScene(myScene);
|
||||||
|
|
||||||
|
/* Addition of a point */
|
||||||
|
//Create and set the top left pos of the new point to (-25, -25) and the radius to 25
|
||||||
|
QGraphicsEllipseItem* newPoint = new QGraphicsEllipseItem(-25, -25, 50, 50);
|
||||||
|
myScene->addItem(newPoint);
|
||||||
|
```
|
||||||
|
|
||||||
|
这样我们就以`(0,0)`为圆心,`25`为半径绘制了一个圆。但很显然,这不可能是我们想要的效果,我们需要在绘制出一个简单圆形的基础上添加一些特性,比如点的颜色属性、点的选择状态或是点的`Pop out`动画
|
||||||
|
|
||||||
|
为了**在画一个圆**的基础上实现这些额外的功能,我们从`QGraphicsEllipseItem`处继承得到`MyGraphicsVexItem`类
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class MyGraphicsVexItem : public QGraphicsEllipseItem {
|
||||||
|
//Constructors, Properties, Methods, etc.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 先别着急:搭建一个测试框架
|
||||||
|
|
||||||
|
在开始着手进行类的各种设计之前,为了明确我们到底设计了什么东西出来,我们需要先搭建一个测试效果用的简单程序框架,它不需要任何UI设计,只需要能够测试我们的类就足够了
|
||||||
|
|
||||||
|
首先创建一个工程,在`mainwindow.cpp`中添加如下头文件
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QGraphicsView>
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
```
|
||||||
|
|
||||||
|
在`MainWindow`构造函数中添加如下代码:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
//Set layout for central widget
|
||||||
|
QVBoxLayout* mainLayout = new QVBoxLayout();
|
||||||
|
ui->centralWidget->setLayout(mainLayout);
|
||||||
|
|
||||||
|
//Add GraphicsView widget
|
||||||
|
QGraphicsView* testView = new QGraphicsView(ui->centralWidget);
|
||||||
|
QGraphicsScene* testScene = new QGraphicsScene(ui->centralWidget);
|
||||||
|
testScene->setSceneRect(-150, -150, 300, 300);
|
||||||
|
testView->setScene(testScene);
|
||||||
|
|
||||||
|
//Add widget to layout
|
||||||
|
mainLayout->addWidget(testView);
|
||||||
|
```
|
||||||
|
|
||||||
|
编译程序,即可得到一个简单的GraphicsView显示窗口
|
||||||
|
|
||||||
|
后续的测试则通过在这个框架上添加或是修改特定的功能来测试效果
|
||||||
|
|
||||||
|
##### 迈出第一步:使用参数绘制点
|
||||||
|
|
||||||
|
为了能够在新的类里面使用给定的参数画出点,我们需要如下参数:
|
||||||
|
|
||||||
|
- `QPointF center` : 几何中心
|
||||||
|
- `qreal radius` : 半径
|
||||||
|
- `QBrush regBrush` : 默认画刷
|
||||||
|
|
||||||
|
由于考虑到其他方法也可能会访问或是修改这些参数,因此将他们作为类的成员变量。构造函数则在妥善设置和使用这些参数的基础上,结合父类构造函数完成
|
||||||
|
|
||||||
|
具体的修改代码如下:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
private:
|
||||||
|
//Geometry properties
|
||||||
|
QPointF center;
|
||||||
|
qreal radius;
|
||||||
|
|
||||||
|
//Brush properties
|
||||||
|
//default color
|
||||||
|
QBrush regBrush = QBrush(QColor(58, 143, 192));
|
||||||
|
|
||||||
|
public:
|
||||||
|
MyGraphicsVexItem(QPointF _center, qreal _radius, QGraphicsItem* parent = nullptr);
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
MyGraphicsVexItem::MyGraphicsVexItem(QPointF _center, qreal _radius, QGraphicsItem* parent) :
|
||||||
|
QGraphicsEllipseItem(_center.x() - _radius, _center.y() - _radius, 2 * _radius, 2 * _radius, parent),
|
||||||
|
center(_center),
|
||||||
|
radius(_radius)
|
||||||
|
{
|
||||||
|
this->setPen(Qt::NoPen);
|
||||||
|
this->setBrush(regBrush);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
此时我们在测试框架中用代码添加一个点测试效果:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
//Add a new vex
|
||||||
|
MyGraphicsVexItem* newVex = new MyGraphicsVexItem(QPointF(0, 0), 10);
|
||||||
|
testScene->addItem(newVex);
|
||||||
|
```
|
||||||
40
README.md
Normal file
40
README.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# GraphBuilder
|
||||||
|
|
||||||
|
This is a project inspired by my Data Structure & Algorithm Course homework, it's used to create and visualize graphs both directed or undirected, and supports underlaying data structure of either adjacent list or multiple adjacent list
|
||||||
|
|
||||||
|
## Functionalities
|
||||||
|
|
||||||
|
- Create, save or read multiple layers (or might say multiple palettes)
|
||||||
|
- Draw or remove nodes and edges
|
||||||
|
- Change name, position of nodes
|
||||||
|
- Change width, direction of edges
|
||||||
|
- Animate BFS, DFS and Dijkstra's algorithm
|
||||||
|
- Change animation speed
|
||||||
|
- Change the underlaying data structure
|
||||||
|
- Change the type of graph (directed or undirected)
|
||||||
|
- Display the generated minimum spanning tree (by hiding unvisited items)
|
||||||
|
- Support algorithms on forests
|
||||||
|
|
||||||
|
## Deploy and run
|
||||||
|
|
||||||
|
If you want to use the packed executable, you can download it from the [release page](https://github.com/Linloir/GraphBuilder/releases)
|
||||||
|
|
||||||
|
If you want to view the source code and run it from QT Creator, you might need:
|
||||||
|
|
||||||
|
- QT 6.1 or above
|
||||||
|
- QT Creator installed
|
||||||
|
- QT build kit (MSVC or MinGW) installed
|
||||||
|
|
||||||
|
Armed with the above, you can clone the repository and open the project from `GraphBuilder.pro` file in QT Creator.
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
87
cities.map
Normal file
87
cities.map
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
VFdGeWFXUnZaekl3TURJd05ESTE=
|
||||||
|
Railway Network
|
||||||
|
A map of railway network in China
|
||||||
|
128 1
|
||||||
|
25
|
||||||
|
38.599 19.965 10
|
||||||
|
Wu Lumuqi
|
||||||
|
178.354 190.333 10
|
||||||
|
Lan Zhou
|
||||||
|
278.179 58.564 10
|
||||||
|
Hu Hehaote
|
||||||
|
384.659 99.825 10
|
||||||
|
Bei Jing
|
||||||
|
485.815 137.093 10
|
||||||
|
Tian Jin
|
||||||
|
608.267 107.811 10
|
||||||
|
Shen Yang
|
||||||
|
685.465 50.578 10
|
||||||
|
Chang Chun
|
||||||
|
752.015 -2.662 10
|
||||||
|
Ha Erbin
|
||||||
|
602.943 185.009 10
|
||||||
|
Da Lian
|
||||||
|
451.209 246.235 10
|
||||||
|
Xu Zhou
|
||||||
|
347.391 240.911 10
|
||||||
|
Zheng Zhou
|
||||||
|
536.393 331.419 10
|
||||||
|
Shang Hai
|
||||||
|
419.265 400.631 10
|
||||||
|
Nan Chang
|
||||||
|
519.09 443.223 10
|
||||||
|
Fu Zhou
|
||||||
|
368.687 328.757 10
|
||||||
|
Wu Han
|
||||||
|
331.419 407.286 10
|
||||||
|
Zhu Zhou
|
||||||
|
252.89 232.925 10
|
||||||
|
Xi An
|
||||||
|
78.529 166.375 10
|
||||||
|
Xi Ning
|
||||||
|
145.079 310.123 10
|
||||||
|
Cheng Du
|
||||||
|
166.375 440.561 10
|
||||||
|
Gui Yang
|
||||||
|
81.191 455.202 10
|
||||||
|
Kun Ming
|
||||||
|
260.876 483.153 10
|
||||||
|
Liu Zhou
|
||||||
|
190.333 547.041 10
|
||||||
|
Nan Ning
|
||||||
|
336.743 493.801 10
|
||||||
|
Guang Zhou
|
||||||
|
448.547 563.013 10
|
||||||
|
Shen Zhen
|
||||||
|
30
|
||||||
|
0 1
|
||||||
|
1 2
|
||||||
|
2 3
|
||||||
|
3 4
|
||||||
|
4 5
|
||||||
|
5 6
|
||||||
|
6 7
|
||||||
|
5 8
|
||||||
|
4 9
|
||||||
|
3 10
|
||||||
|
10 9
|
||||||
|
9 11
|
||||||
|
11 12
|
||||||
|
12 13
|
||||||
|
10 14
|
||||||
|
14 15
|
||||||
|
15 12
|
||||||
|
10 16
|
||||||
|
16 1
|
||||||
|
1 17
|
||||||
|
16 18
|
||||||
|
18 19
|
||||||
|
18 20
|
||||||
|
20 19
|
||||||
|
19 15
|
||||||
|
15 21
|
||||||
|
21 19
|
||||||
|
21 22
|
||||||
|
15 23
|
||||||
|
23 24
|
||||||
|
1892 1145 668 137 704 305 242 397 674 695 349 651 825 622 534 409 367 511 676 216 842 967 1100 639 902 672 607 255 675 140
|
||||||
@ -377,7 +377,11 @@ void ScrollIndicator::mousePressEvent(QMouseEvent *event){
|
|||||||
pressed = true;
|
pressed = true;
|
||||||
//>note: globalPos -> globalPosition here due to deprecation
|
//>note: globalPos -> globalPosition here due to deprecation
|
||||||
//> may cause issues
|
//> may cause issues
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
lastY = event->globalPosition().y();
|
lastY = event->globalPosition().y();
|
||||||
|
#else
|
||||||
|
lastY = event->globalPos().y();
|
||||||
|
#endif
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,11 +389,19 @@ void ScrollIndicator::mouseMoveEvent(QMouseEvent *event){
|
|||||||
if(pressed && !aniPause->isActive()){
|
if(pressed && !aniPause->isActive()){
|
||||||
//>note: globalPos -> globalPosition here due to deprecation
|
//>note: globalPos -> globalPosition here due to deprecation
|
||||||
//> may cause issues
|
//> may cause issues
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
int dp = event->globalPosition().y() - lastY;
|
int dp = event->globalPosition().y() - lastY;
|
||||||
|
#else
|
||||||
|
int dp = event->globalPos().y() - lastY;
|
||||||
|
#endif
|
||||||
emit scrollPage(dp);
|
emit scrollPage(dp);
|
||||||
//>note: globalPos -> globalPosition here due to deprecation
|
//>note: globalPos -> globalPosition here due to deprecation
|
||||||
//> may cause issues
|
//> may cause issues
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
lastY = event->globalPosition().y();
|
lastY = event->globalPosition().y();
|
||||||
|
#else
|
||||||
|
lastY = event->globalPos().y();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QWheelEvent>
|
#include <QWheelEvent>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QtMath>
|
||||||
|
|
||||||
#define MAXSPEED 70
|
#define MAXSPEED 70
|
||||||
|
|
||||||
|
|||||||
@ -456,7 +456,7 @@ bigIconButton::bigIconButton(const QString &iconPath, const QString &description
|
|||||||
bgWidget = new QWidget(this);
|
bgWidget = new QWidget(this);
|
||||||
bgWidget->resize(this->size());
|
bgWidget->resize(this->size());
|
||||||
radiusStyle = QString::asprintf("border-radius:%dpx;", cornerRadius);
|
radiusStyle = QString::asprintf("border-radius:%dpx;", cornerRadius);
|
||||||
bgWidget->setStyleSheet(radiusStyle + "background-color:#00000000");
|
bgWidget->setStyleSheet(radiusStyle + "background-color:#04000000");
|
||||||
bgWidget->lower();
|
bgWidget->lower();
|
||||||
bgWidget->show();
|
bgWidget->show();
|
||||||
|
|
||||||
@ -479,8 +479,8 @@ void bigIconButton::resizeEvent(QResizeEvent *event){
|
|||||||
indicator->move(this->width() * 0.45, this->height() - 21);
|
indicator->move(this->width() * 0.45, this->height() - 21);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
indicator->resize(this->width() * 0.4, 6);
|
indicator->resize(this->width() * 0.1, 6);
|
||||||
indicator->move(this->width() * 0.3, this->height() - 21);
|
indicator->move(this->width() * 0.45, this->height() - 21);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -497,7 +497,7 @@ void bigIconButton::enterEvent(QEnterEvent *event){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void bigIconButton::leaveEvent(QEvent *event){
|
void bigIconButton::leaveEvent(QEvent *event){
|
||||||
bgWidget->setStyleSheet(radiusStyle + "background-color:#00000000");
|
bgWidget->setStyleSheet(radiusStyle + "background-color:#04000000");
|
||||||
QPropertyAnimation *shorter = new QPropertyAnimation(indicator, "geometry", this);
|
QPropertyAnimation *shorter = new QPropertyAnimation(indicator, "geometry", this);
|
||||||
shorter->setStartValue(indicator->geometry());
|
shorter->setStartValue(indicator->geometry());
|
||||||
if(!onSelected)
|
if(!onSelected)
|
||||||
|
|||||||
@ -15,6 +15,13 @@
|
|||||||
#include <QResizeEvent>
|
#include <QResizeEvent>
|
||||||
#include <QFocusEvent>
|
#include <QFocusEvent>
|
||||||
|
|
||||||
|
#if (QT_VERSION > QT_VERSION_CHECK(6,3,0))
|
||||||
|
#include <QGraphicsOpacityEffect>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class customIcon : public QPushButton{
|
class customIcon : public QPushButton{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
|||||||
BIN
fonts/corbel.ttf
Executable file
BIN
fonts/corbel.ttf
Executable file
Binary file not shown.
BIN
fonts/corbelb.ttf
Executable file
BIN
fonts/corbelb.ttf
Executable file
Binary file not shown.
BIN
fonts/corbeli.ttf
Executable file
BIN
fonts/corbeli.ttf
Executable file
Binary file not shown.
BIN
fonts/corbell.ttf
Executable file
BIN
fonts/corbell.ttf
Executable file
Binary file not shown.
BIN
fonts/corbelli.ttf
Executable file
BIN
fonts/corbelli.ttf
Executable file
Binary file not shown.
BIN
fonts/corbelz.ttf
Executable file
BIN
fonts/corbelz.ttf
Executable file
Binary file not shown.
@ -230,7 +230,7 @@ void ALGraph::ResetDistance(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ALGraph::DFS(int strtID){
|
void ALGraph::DFS(int strtID, bool generateForest){
|
||||||
if(strtID == -1)
|
if(strtID == -1)
|
||||||
return;
|
return;
|
||||||
vector<int> awaitVexList;
|
vector<int> awaitVexList;
|
||||||
@ -254,9 +254,35 @@ void ALGraph::DFS(int strtID){
|
|||||||
nextArc->visit();
|
nextArc->visit();
|
||||||
vexList[nextVex].visit();
|
vexList[nextVex].visit();
|
||||||
}
|
}
|
||||||
|
if(generateForest){
|
||||||
|
for(int i = 0; i < vexList.size(); i++){
|
||||||
|
if(vexList[i].visited) continue;
|
||||||
|
awaitVexList.clear();
|
||||||
|
awaitArcList.clear();
|
||||||
|
awaitVexList.push_back(i);
|
||||||
|
while(awaitVexList.size() > 0){
|
||||||
|
int nextVex = awaitVexList.back();
|
||||||
|
ALArc *nextArc = awaitArcList.size() > 0 ? awaitArcList.back() : nullptr;
|
||||||
|
awaitVexList.pop_back();
|
||||||
|
if(nextArc)
|
||||||
|
awaitArcList.pop_back();
|
||||||
|
for(ALArc *p = vexList[nextVex].firstArc; p != nullptr; p = p->nextArc){
|
||||||
|
if(vexList[p->eVexID].visited == false){
|
||||||
|
awaitVexList.push_back(p->eVexID);
|
||||||
|
awaitArcList.push_back(p);
|
||||||
|
if(type == UDG && GetIdOf(p->gArc->edVex()) != p->eVexID)
|
||||||
|
p->gArc->reverseDirection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(nextArc && !vexList[nextArc->eVexID].visited)
|
||||||
|
nextArc->visit();
|
||||||
|
vexList[nextVex].visit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ALGraph::BFS(int strtID){
|
void ALGraph::BFS(int strtID, bool generateForest){
|
||||||
if(strtID == -1)
|
if(strtID == -1)
|
||||||
return;
|
return;
|
||||||
vector<int> awaitVexList;
|
vector<int> awaitVexList;
|
||||||
@ -280,6 +306,32 @@ void ALGraph::BFS(int strtID){
|
|||||||
nextArc->visit();
|
nextArc->visit();
|
||||||
vexList[nextVex].visit();
|
vexList[nextVex].visit();
|
||||||
}
|
}
|
||||||
|
if(generateForest){
|
||||||
|
for(int i = 0; i < vexList.size(); i++){
|
||||||
|
if(vexList[i].visited) continue;
|
||||||
|
awaitVexList.clear();
|
||||||
|
awaitArcList.clear();
|
||||||
|
awaitVexList.push_back(i);
|
||||||
|
while(awaitVexList.size() > 0){
|
||||||
|
int nextVex = awaitVexList[0];
|
||||||
|
ALArc *nextArc = awaitArcList.size() > 0 ? awaitArcList[0] : nullptr;
|
||||||
|
awaitVexList.erase(awaitVexList.begin());
|
||||||
|
if(nextArc)
|
||||||
|
awaitArcList.erase(awaitArcList.begin());
|
||||||
|
for(ALArc *p = vexList[nextVex].firstArc; p != nullptr; p = p->nextArc){
|
||||||
|
if(vexList[p->eVexID].visited == false){
|
||||||
|
awaitVexList.push_back(p->eVexID);
|
||||||
|
awaitArcList.push_back(p);
|
||||||
|
if(type == UDG && GetIdOf(p->gArc->edVex()) != p->eVexID)
|
||||||
|
p->gArc->reverseDirection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(nextArc && !vexList[nextArc->eVexID].visited)
|
||||||
|
nextArc->visit();
|
||||||
|
vexList[nextVex].visit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ALGraph::Dijkstra(int strtID){
|
void ALGraph::Dijkstra(int strtID){
|
||||||
@ -482,7 +534,7 @@ void AMLGraph::DelVex(int vexID){
|
|||||||
AMLArc *nextArc = preArc->nextOutArc;
|
AMLArc *nextArc = preArc->nextOutArc;
|
||||||
while(nextArc != nullptr){
|
while(nextArc != nullptr){
|
||||||
if(nextArc->inVexID == vexID || nextArc->outVexID == vexID){
|
if(nextArc->inVexID == vexID || nextArc->outVexID == vexID){
|
||||||
if(preArc->outVexID == i){
|
if(preArc->outVexID == i || preArc->outVexID == -i){
|
||||||
if(nextArc->outVexID == i){
|
if(nextArc->outVexID == i){
|
||||||
preArc->nextOutArc = nextArc->nextOutArc;
|
preArc->nextOutArc = nextArc->nextOutArc;
|
||||||
nextArc->nextOutArc = nullptr;
|
nextArc->nextOutArc = nullptr;
|
||||||
@ -506,20 +558,52 @@ void AMLGraph::DelVex(int vexID){
|
|||||||
delete nextArc;
|
delete nextArc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nextArc = preArc->outVexID == i ? preArc->nextOutArc : preArc->nextInArc;
|
nextArc = (preArc->outVexID == i || preArc->outVexID == -i) ? preArc->nextOutArc : preArc->nextInArc;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
preArc = nextArc;
|
|
||||||
nextArc = preArc->outVexID == i ? preArc->nextOutArc : preArc->nextInArc;
|
|
||||||
if(preArc->inVexID > vexID)
|
if(preArc->inVexID > vexID)
|
||||||
preArc->inVexID = - preArc->inVexID;
|
preArc->inVexID = - preArc->inVexID;
|
||||||
else if(preArc->inVexID < 0)
|
else if(preArc->inVexID < 0)
|
||||||
preArc->inVexID = - preArc->inVexID;
|
preArc->inVexID = - preArc->inVexID - 1;
|
||||||
if(preArc->outVexID > vexID)
|
if(preArc->outVexID > vexID)
|
||||||
preArc->outVexID = - preArc->outVexID;
|
preArc->outVexID = - preArc->outVexID;
|
||||||
else if(preArc->outVexID < 0)
|
else if(preArc->outVexID < 0)
|
||||||
preArc->outVexID = - preArc->outVexID;
|
preArc->outVexID = - preArc->outVexID - 1;
|
||||||
|
preArc = nextArc;
|
||||||
|
nextArc = (preArc->outVexID == i || preArc->outVexID == -i) ? preArc->nextOutArc : preArc->nextInArc;
|
||||||
|
|
||||||
|
/********************************************************************************************/
|
||||||
|
//Issue #1
|
||||||
|
/*How this causes issue:
|
||||||
|
* Example: when vexID is 1
|
||||||
|
* preArc = nextArc => preArc: -3 -> -2
|
||||||
|
* nextArc = ... => nextArc : 3 -> 1
|
||||||
|
* Adjust pre Arc to => preArc: 2 -> 1
|
||||||
|
* In next loop: nextArc->inVexID == 1 => judge if preArc->nextOutArc == 3 (in fact it is)
|
||||||
|
* preArc->nextOutArc != 3 -> wrongly connect next out arc of 3 -> 1 to next out arc of 2 -> 1
|
||||||
|
* which leads to wrong operations
|
||||||
|
*/
|
||||||
|
|
||||||
|
//if(preArc->inVexID > vexID)
|
||||||
|
// preArc->inVexID = - preArc->inVexID;
|
||||||
|
//else if(preArc->inVexID < 0)
|
||||||
|
// preArc->inVexID = - preArc->inVexID - 1;
|
||||||
|
//if(preArc->outVexID > vexID)
|
||||||
|
// preArc->outVexID = - preArc->outVexID;
|
||||||
|
//else if(preArc->outVexID < 0)
|
||||||
|
// preArc->outVexID = - preArc->outVexID - 1;
|
||||||
|
|
||||||
|
/********************************************************************************************/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if(preArc->inVexID > vexID)
|
||||||
|
preArc->inVexID = - preArc->inVexID;
|
||||||
|
else if(preArc->inVexID < 0)
|
||||||
|
preArc->inVexID = - preArc->inVexID - 1;
|
||||||
|
if(preArc->outVexID > vexID)
|
||||||
|
preArc->outVexID = - preArc->outVexID;
|
||||||
|
else if(preArc->outVexID < 0)
|
||||||
|
preArc->outVexID = - preArc->outVexID - 1;
|
||||||
outVexList[i].firstArc = dummyHead->nextOutArc;
|
outVexList[i].firstArc = dummyHead->nextOutArc;
|
||||||
delete dummyHead;
|
delete dummyHead;
|
||||||
}
|
}
|
||||||
@ -763,7 +847,7 @@ void AMLGraph::ResetDistance(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AMLGraph::DFS(int strtID){
|
void AMLGraph::DFS(int strtID, bool generateForest){
|
||||||
if(strtID == -1)
|
if(strtID == -1)
|
||||||
return;
|
return;
|
||||||
vector<int> awaitVexList;
|
vector<int> awaitVexList;
|
||||||
@ -788,9 +872,36 @@ void AMLGraph::DFS(int strtID){
|
|||||||
nextArc->visit();
|
nextArc->visit();
|
||||||
outVexList[nextVex].visit();
|
outVexList[nextVex].visit();
|
||||||
}
|
}
|
||||||
|
if(generateForest){
|
||||||
|
for(int i = 0; i < outVexList.size(); i++){
|
||||||
|
if(outVexList[i].visited) continue;
|
||||||
|
awaitVexList.clear();
|
||||||
|
awaitArcList.clear();
|
||||||
|
awaitVexList.push_back(i);
|
||||||
|
while(awaitVexList.size() > 0){
|
||||||
|
int nextVex = awaitVexList.back();
|
||||||
|
AMLArc *nextArc = awaitArcList.size() > 0 ? awaitArcList.back() : nullptr;
|
||||||
|
awaitVexList.pop_back();
|
||||||
|
if(nextArc)
|
||||||
|
awaitArcList.pop_back();
|
||||||
|
for(AMLArc *p = outVexList[nextVex].firstArc; p != nullptr; p = p->outVexID == strtID ? p->nextOutArc : p->nextInArc){
|
||||||
|
int endID = p->outVexID == nextVex ? p->inVexID : p->outVexID;
|
||||||
|
if(outVexList[endID].visited == false){
|
||||||
|
awaitVexList.push_back(endID);
|
||||||
|
awaitArcList.push_back(p);
|
||||||
|
if(type == UDG && GetIdOf(p->gArc->edVex()) != endID)
|
||||||
|
p->gArc->reverseDirection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(nextArc && !outVexList[nextVex].visited)
|
||||||
|
nextArc->visit();
|
||||||
|
outVexList[nextVex].visit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AMLGraph::BFS(int strtID){
|
void AMLGraph::BFS(int strtID, bool generateForest){
|
||||||
if(strtID == -1)
|
if(strtID == -1)
|
||||||
return;
|
return;
|
||||||
vector<int> awaitVexList;
|
vector<int> awaitVexList;
|
||||||
@ -815,6 +926,33 @@ void AMLGraph::BFS(int strtID){
|
|||||||
nextArc->visit();
|
nextArc->visit();
|
||||||
outVexList[nextVex].visit();
|
outVexList[nextVex].visit();
|
||||||
}
|
}
|
||||||
|
if(generateForest){
|
||||||
|
for(int i = 0; i < outVexList.size(); i++){
|
||||||
|
if(outVexList[i].visited) continue;
|
||||||
|
awaitVexList.clear();
|
||||||
|
awaitArcList.clear();
|
||||||
|
awaitVexList.push_back(i);
|
||||||
|
while(awaitVexList.size() > 0){
|
||||||
|
int nextVex = awaitVexList[0];
|
||||||
|
AMLArc *nextArc = awaitArcList.size() > 0 ? awaitArcList[0] : nullptr;
|
||||||
|
awaitVexList.erase(awaitVexList.begin());
|
||||||
|
if(nextArc)
|
||||||
|
awaitArcList.erase(awaitArcList.begin());
|
||||||
|
for(AMLArc *p = outVexList[nextVex].firstArc; p != nullptr; p = p->outVexID == strtID ? p->nextOutArc : p->nextInArc){
|
||||||
|
int endID = p->outVexID == nextVex ? p->inVexID : p->outVexID;
|
||||||
|
if(outVexList[endID].visited == false){
|
||||||
|
awaitVexList.push_back(endID);
|
||||||
|
awaitArcList.push_back(p);
|
||||||
|
if(type == UDG && GetIdOf(p->gArc->edVex()) != endID)
|
||||||
|
p->gArc->reverseDirection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(nextArc && !outVexList[nextVex].visited)
|
||||||
|
nextArc->visit();
|
||||||
|
outVexList[nextVex].visit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AMLGraph::Dijkstra(int strtID){
|
void AMLGraph::Dijkstra(int strtID){
|
||||||
|
|||||||
@ -50,10 +50,10 @@ public:
|
|||||||
/* Other Function */
|
/* Other Function */
|
||||||
virtual void ClearVisit() = 0;
|
virtual void ClearVisit() = 0;
|
||||||
virtual void ResetDistance() = 0;
|
virtual void ResetDistance() = 0;
|
||||||
virtual void DFS(int strtID) = 0;
|
virtual void DFS(int strtID, bool generateForest = false) = 0;
|
||||||
virtual void DFS(MyGraphicsVexItem *strtVex) = 0;
|
virtual void DFS(MyGraphicsVexItem *strtVex, bool generateForest = false) = 0;
|
||||||
virtual void BFS(int strtID) = 0;
|
virtual void BFS(int strtID, bool generateForest = false) = 0;
|
||||||
virtual void BFS(MyGraphicsVexItem *strtVex) = 0;
|
virtual void BFS(MyGraphicsVexItem *strtVex, bool generateForest = false) = 0;
|
||||||
virtual void Dijkstra(int strtID) = 0;
|
virtual void Dijkstra(int strtID) = 0;
|
||||||
virtual void Dijkstra(MyGraphicsVexItem *strtVex) = 0;
|
virtual void Dijkstra(MyGraphicsVexItem *strtVex) = 0;
|
||||||
|
|
||||||
@ -127,10 +127,10 @@ public:
|
|||||||
/* Other Function */
|
/* Other Function */
|
||||||
void ClearVisit();
|
void ClearVisit();
|
||||||
void ResetDistance();
|
void ResetDistance();
|
||||||
void DFS(int strtID);
|
void DFS(int strtID, bool generateForest = false);
|
||||||
void DFS(MyGraphicsVexItem *strtVex){DFS(GetIdOf(strtVex));}
|
void DFS(MyGraphicsVexItem *strtVex, bool generateForest = false){DFS(GetIdOf(strtVex), generateForest);}
|
||||||
void BFS(int strtID);
|
void BFS(int strtID, bool generateForest = false);
|
||||||
void BFS(MyGraphicsVexItem *strtVex){BFS(GetIdOf(strtVex));}
|
void BFS(MyGraphicsVexItem *strtVex, bool generateForest = false){BFS(GetIdOf(strtVex), generateForest);}
|
||||||
void Dijkstra(int strtID);
|
void Dijkstra(int strtID);
|
||||||
void Dijkstra(MyGraphicsVexItem *strtVex){Dijkstra(GetIdOf(strtVex));}
|
void Dijkstra(MyGraphicsVexItem *strtVex){Dijkstra(GetIdOf(strtVex));}
|
||||||
AMLGraph* ConvertToAML();
|
AMLGraph* ConvertToAML();
|
||||||
@ -202,10 +202,10 @@ public:
|
|||||||
/* Other Function */
|
/* Other Function */
|
||||||
void ClearVisit();
|
void ClearVisit();
|
||||||
void ResetDistance();
|
void ResetDistance();
|
||||||
void DFS(int strtID);
|
void DFS(int strtID, bool generateForest = false);
|
||||||
void DFS(MyGraphicsVexItem *strtVex){DFS(GetIdOf(strtVex));}
|
void DFS(MyGraphicsVexItem *strtVex, bool generateForest = false){DFS(GetIdOf(strtVex), generateForest);}
|
||||||
void BFS(int strtID);
|
void BFS(int strtID, bool generateForest = false);
|
||||||
void BFS(MyGraphicsVexItem *strtVex){BFS(GetIdOf(strtVex));}
|
void BFS(MyGraphicsVexItem *strtVex, bool generateForest = false){BFS(GetIdOf(strtVex), generateForest);}
|
||||||
void Dijkstra(int strtID);
|
void Dijkstra(int strtID);
|
||||||
void Dijkstra(MyGraphicsVexItem *strtVex){Dijkstra(GetIdOf(strtVex));}
|
void Dijkstra(MyGraphicsVexItem *strtVex){Dijkstra(GetIdOf(strtVex));}
|
||||||
ALGraph* ConvertToAL();
|
ALGraph* ConvertToAL();
|
||||||
|
|||||||
140
graph_view.cpp
140
graph_view.cpp
@ -1,5 +1,4 @@
|
|||||||
#include "graph_view.h"
|
#include "graph_view.h"
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
viewLog::viewLog(QString log, QWidget *parent) :
|
viewLog::viewLog(QString log, QWidget *parent) :
|
||||||
QLabel(parent)
|
QLabel(parent)
|
||||||
@ -147,7 +146,11 @@ void MyGraphicsView::mouseMoveEvent(QMouseEvent *event){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MyGraphicsView::wheelEvent(QWheelEvent *event){
|
void MyGraphicsView::wheelEvent(QWheelEvent *event){
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
QPointF cursorPoint = event->position();
|
QPointF cursorPoint = event->position();
|
||||||
|
#else
|
||||||
|
QPointF cursorPoint = event->posF();
|
||||||
|
#endif
|
||||||
QPointF scenePos = this->mapToScene(QPoint(cursorPoint.x(), cursorPoint.y()));
|
QPointF scenePos = this->mapToScene(QPoint(cursorPoint.x(), cursorPoint.y()));
|
||||||
|
|
||||||
qreal viewWidth = this->viewport()->width();
|
qreal viewWidth = this->viewport()->width();
|
||||||
@ -241,6 +244,26 @@ void MyGraphicsView::RemoveArc(MyGraphicsLineItem *line){
|
|||||||
line->remove();
|
line->remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyGraphicsView::HideUnvisited(){
|
||||||
|
for(int i = 0; i < vexes.size(); i++){
|
||||||
|
if(!vexes[i]->isVisited())
|
||||||
|
vexes[i]->itemHide();
|
||||||
|
}
|
||||||
|
for(int i = 0; i < lines.size(); i++){
|
||||||
|
if(!lines[i]->isVisited())
|
||||||
|
lines[i]->itemHide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyGraphicsView::ShowUnvisited(){
|
||||||
|
for(int i = 0; i < vexes.size(); i++){
|
||||||
|
vexes[i]->itemShow();
|
||||||
|
}
|
||||||
|
for(int i = 0; i < lines.size(); i++){
|
||||||
|
lines[i]->itemShow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MyGraphicsView::SaveToFile(QTextStream &ts){
|
void MyGraphicsView::SaveToFile(QTextStream &ts){
|
||||||
//vexes
|
//vexes
|
||||||
ts << vexes.size() << "\n";
|
ts << vexes.size() << "\n";
|
||||||
@ -487,12 +510,16 @@ void MyGraphicsVexItem::visit(bool visited){
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(visitEffect, &QTimeLine::stateChanged, this, [=](){
|
connect(visitEffect, &QTimeLine::stateChanged, this, [=](){
|
||||||
if(visitEffect->state() == QTimeLine::Running)
|
if(visitEffect->state() == QTimeLine::Running){
|
||||||
|
itemShow();
|
||||||
|
this->state |= ON_VISIT;
|
||||||
emit logAdded(new viewLog("[Vex] | \""+nameText+"\" set visited"));
|
emit logAdded(new viewLog("[Vex] | \""+nameText+"\" set visited"));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
emit addAnimation(visitEffect);
|
emit addAnimation(visitEffect);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
state &= ~ON_VISIT;
|
||||||
if(state & ON_SELECTED){
|
if(state & ON_SELECTED){
|
||||||
this->setBrush(selBrush);
|
this->setBrush(selBrush);
|
||||||
if(tag)
|
if(tag)
|
||||||
@ -506,6 +533,38 @@ void MyGraphicsVexItem::visit(bool visited){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyGraphicsVexItem::itemHide(){
|
||||||
|
nameTag->setBrush(QColor(0, 0, 0, 0));
|
||||||
|
if(tag){
|
||||||
|
QBrush brush = tag->brush();
|
||||||
|
QColor color = brush.color();
|
||||||
|
color.setAlpha(0);
|
||||||
|
brush.setColor(color);
|
||||||
|
tag->setBrush(brush);
|
||||||
|
}
|
||||||
|
QBrush brush = this->brush();
|
||||||
|
QColor color = brush.color();
|
||||||
|
color.setAlpha(0);
|
||||||
|
brush.setColor(color);
|
||||||
|
this->setBrush(brush);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyGraphicsVexItem::itemShow(){
|
||||||
|
nameTag->setBrush(QColor(0, 0, 0));
|
||||||
|
if(tag){
|
||||||
|
QBrush brush = tag->brush();
|
||||||
|
QColor color = brush.color();
|
||||||
|
color.setAlpha(255);
|
||||||
|
brush.setColor(color);
|
||||||
|
tag->setBrush(brush);
|
||||||
|
}
|
||||||
|
QBrush brush = this->brush();
|
||||||
|
QColor color = brush.color();
|
||||||
|
color.setAlpha(255);
|
||||||
|
brush.setColor(color);
|
||||||
|
this->setBrush(brush);
|
||||||
|
}
|
||||||
|
|
||||||
void MyGraphicsVexItem::access(const QString &hint, bool isAccess){
|
void MyGraphicsVexItem::access(const QString &hint, bool isAccess){
|
||||||
if(isAccess){
|
if(isAccess){
|
||||||
if(!tag)
|
if(!tag)
|
||||||
@ -540,8 +599,10 @@ void MyGraphicsVexItem::access(const QString &hint, bool isAccess){
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(accessEffect, &QTimeLine::stateChanged, this, [=](){
|
connect(accessEffect, &QTimeLine::stateChanged, this, [=](){
|
||||||
if(accessEffect->state() == QTimeLine::Running)
|
if(accessEffect->state() == QTimeLine::Running){
|
||||||
|
itemShow();
|
||||||
emit logAdded(new viewLog("[Vex] | \""+nameText+"\" accessed with hint "+hint));
|
emit logAdded(new viewLog("[Vex] | \""+nameText+"\" accessed with hint "+hint));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
emit addAnimation(accessEffect);
|
emit addAnimation(accessEffect);
|
||||||
}
|
}
|
||||||
@ -602,6 +663,7 @@ void MyGraphicsVexItem::onLeftClick(QPointF position){
|
|||||||
return;
|
return;
|
||||||
if(state & (ON_LEFT_CLICK | ON_RIGHT_CLICK))
|
if(state & (ON_LEFT_CLICK | ON_RIGHT_CLICK))
|
||||||
return;
|
return;
|
||||||
|
itemShow();
|
||||||
if(this->contains(position)){
|
if(this->contains(position)){
|
||||||
emit selected(this);
|
emit selected(this);
|
||||||
state |= ON_LEFT_CLICK;
|
state |= ON_LEFT_CLICK;
|
||||||
@ -629,6 +691,7 @@ void MyGraphicsVexItem::onRightClick(QPointF position){
|
|||||||
return;
|
return;
|
||||||
if(state & (ON_LEFT_CLICK | ON_RIGHT_CLICK))
|
if(state & (ON_LEFT_CLICK | ON_RIGHT_CLICK))
|
||||||
return;
|
return;
|
||||||
|
itemShow();
|
||||||
if(this->contains(position)){
|
if(this->contains(position)){
|
||||||
emit selected(this);
|
emit selected(this);
|
||||||
state |= ON_RIGHT_CLICK;
|
state |= ON_RIGHT_CLICK;
|
||||||
@ -920,6 +983,7 @@ void MyGraphicsLineItem::onLeftClick(QPointF position){
|
|||||||
return;
|
return;
|
||||||
if(state & ON_VISIT)
|
if(state & ON_VISIT)
|
||||||
visit(false);
|
visit(false);
|
||||||
|
itemShow();
|
||||||
if(this->contains(position)){
|
if(this->contains(position)){
|
||||||
emit selected(this);
|
emit selected(this);
|
||||||
onClickEffect();
|
onClickEffect();
|
||||||
@ -946,6 +1010,7 @@ void MyGraphicsLineItem::onRightClick(QPointF position){
|
|||||||
return;
|
return;
|
||||||
if(state & ON_VISIT)
|
if(state & ON_VISIT)
|
||||||
visit(false);
|
visit(false);
|
||||||
|
itemShow();
|
||||||
if(this->contains(position)){
|
if(this->contains(position)){
|
||||||
emit selected(this);
|
emit selected(this);
|
||||||
onClickEffect();
|
onClickEffect();
|
||||||
@ -981,9 +1046,9 @@ void MyGraphicsLineItem::onMouseRelease(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyGraphicsLineItem::visit(bool visited){
|
void MyGraphicsLineItem::visit(bool visit){
|
||||||
if(visited){
|
if(visit){
|
||||||
state |= ON_VISIT;
|
//state |= ON_VISIT;
|
||||||
QTimeLine *visitEffect = new QTimeLine;
|
QTimeLine *visitEffect = new QTimeLine;
|
||||||
visitEffect->setDuration(1000);
|
visitEffect->setDuration(1000);
|
||||||
visitEffect->setFrameRange(0, 200);
|
visitEffect->setFrameRange(0, 200);
|
||||||
@ -1005,6 +1070,7 @@ void MyGraphicsLineItem::visit(bool visited){
|
|||||||
newLine2->setZValue(this->zValue() - 2);
|
newLine2->setZValue(this->zValue() - 2);
|
||||||
scene()->addItem(newLine2);
|
scene()->addItem(newLine2);
|
||||||
}
|
}
|
||||||
|
this->state |= ON_VISIT;
|
||||||
emit logAdded(new viewLog("[Arc] | Arc \""+startVex->Text()+"\" -> \""+endVex->Text()+"\" set visited"));
|
emit logAdded(new viewLog("[Arc] | Arc \""+startVex->Text()+"\" -> \""+endVex->Text()+"\" set visited"));
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@ -1028,6 +1094,68 @@ void MyGraphicsLineItem::visit(bool visited){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyGraphicsLineItem::itemHide(){
|
||||||
|
if(line1){
|
||||||
|
QPen pen = line1->pen();
|
||||||
|
QColor color = pen.color();
|
||||||
|
color.setAlpha(0);
|
||||||
|
pen.setColor(color);
|
||||||
|
line1->setPen(pen);
|
||||||
|
}
|
||||||
|
if(line2){
|
||||||
|
QPen pen = line2->pen();
|
||||||
|
QColor color = pen.color();
|
||||||
|
color.setAlpha(0);
|
||||||
|
pen.setColor(color);
|
||||||
|
line2->setPen(pen);
|
||||||
|
}
|
||||||
|
if(arrow){
|
||||||
|
QPen pen = arrow->pen();
|
||||||
|
QColor color = pen.color();
|
||||||
|
color.setAlpha(0);
|
||||||
|
pen.setColor(color);
|
||||||
|
arrow->setPen(pen);
|
||||||
|
}
|
||||||
|
if(textItem){
|
||||||
|
QBrush brush = textItem->brush();
|
||||||
|
QColor color = brush.color();
|
||||||
|
color.setAlpha(0);
|
||||||
|
brush.setColor(color);
|
||||||
|
textItem->setBrush(brush);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyGraphicsLineItem::itemShow(){
|
||||||
|
if(line1){
|
||||||
|
QPen pen = line1->pen();
|
||||||
|
QColor color = pen.color();
|
||||||
|
color.setAlpha(255);
|
||||||
|
pen.setColor(color);
|
||||||
|
line1->setPen(pen);
|
||||||
|
}
|
||||||
|
if(line2){
|
||||||
|
QPen pen = line2->pen();
|
||||||
|
QColor color = pen.color();
|
||||||
|
color.setAlpha(255);
|
||||||
|
pen.setColor(color);
|
||||||
|
line2->setPen(pen);
|
||||||
|
}
|
||||||
|
if(arrow){
|
||||||
|
QPen pen = arrow->pen();
|
||||||
|
QColor color = pen.color();
|
||||||
|
color.setAlpha(255);
|
||||||
|
pen.setColor(color);
|
||||||
|
arrow->setPen(pen);
|
||||||
|
}
|
||||||
|
if(textItem){
|
||||||
|
QBrush brush = textItem->brush();
|
||||||
|
QColor color = brush.color();
|
||||||
|
color.setAlpha(255);
|
||||||
|
brush.setColor(color);
|
||||||
|
textItem->setBrush(brush);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MyGraphicsLineItem::remove(){
|
void MyGraphicsLineItem::remove(){
|
||||||
startVex->removeStartLine(this);
|
startVex->removeStartLine(this);
|
||||||
endVex->removeEndLine(this);
|
endVex->removeEndLine(this);
|
||||||
|
|||||||
19
graph_view.h
19
graph_view.h
@ -10,7 +10,6 @@
|
|||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
|
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
|
||||||
//Header for MyVex class
|
//Header for MyVex class
|
||||||
@ -25,6 +24,10 @@
|
|||||||
#include <QTimeLine>
|
#include <QTimeLine>
|
||||||
#include <QEasingCurve>
|
#include <QEasingCurve>
|
||||||
|
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(6,0,0))
|
||||||
|
#include <QtMath>
|
||||||
|
#endif
|
||||||
|
|
||||||
class viewLog : public QLabel{
|
class viewLog : public QLabel{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
@ -126,6 +129,8 @@ public:
|
|||||||
|
|
||||||
void RemoveVex(MyGraphicsVexItem *vex);
|
void RemoveVex(MyGraphicsVexItem *vex);
|
||||||
void RemoveArc(MyGraphicsLineItem *line);
|
void RemoveArc(MyGraphicsLineItem *line);
|
||||||
|
void HideUnvisited();
|
||||||
|
void ShowUnvisited();
|
||||||
|
|
||||||
void setAniRate(qreal rate){speedRate = rate;}
|
void setAniRate(qreal rate){speedRate = rate;}
|
||||||
void setType(int _type){type = _type;}
|
void setType(int _type){type = _type;}
|
||||||
@ -185,7 +190,7 @@ private:
|
|||||||
static unsigned int internalID;
|
static unsigned int internalID;
|
||||||
QBrush regBrush = QBrush(QColor(58, 143, 192));
|
QBrush regBrush = QBrush(QColor(58, 143, 192));
|
||||||
QBrush selBrush = QBrush(QColor(208, 90, 110));
|
QBrush selBrush = QBrush(QColor(208, 90, 110));
|
||||||
QBrush visitedBrush = QBrush(QColor(93, 172, 129));
|
QBrush visitedBrush = QBrush(QColor(0, 137, 108));
|
||||||
QBrush accessBrush = QBrush(QColor(152, 109, 178));
|
QBrush accessBrush = QBrush(QColor(152, 109, 178));
|
||||||
|
|
||||||
QPointF center;
|
QPointF center;
|
||||||
@ -227,6 +232,8 @@ public:
|
|||||||
void select();
|
void select();
|
||||||
void visit(bool visited = true);
|
void visit(bool visited = true);
|
||||||
void access(const QString &hint = "", bool isAccess = true);
|
void access(const QString &hint = "", bool isAccess = true);
|
||||||
|
void itemHide();
|
||||||
|
void itemShow();
|
||||||
QString Text(){return nameText;}
|
QString Text(){return nameText;}
|
||||||
void setText(const QString & text){nameTag->setText(text);nameText = text;}
|
void setText(const QString & text){nameTag->setText(text);nameText = text;}
|
||||||
void addStartLine(MyGraphicsLineItem *line){linesStartWith.push_back(line);}
|
void addStartLine(MyGraphicsLineItem *line){linesStartWith.push_back(line);}
|
||||||
@ -237,6 +244,7 @@ public:
|
|||||||
|
|
||||||
bool equalTo(MyGraphicsVexItem *v){return id == v->id;}
|
bool equalTo(MyGraphicsVexItem *v){return id == v->id;}
|
||||||
int type() const override {return Type;}
|
int type() const override {return Type;}
|
||||||
|
bool isVisited(){return state & ON_VISIT;}
|
||||||
qreal getRadius() {return radius;}
|
qreal getRadius() {return radius;}
|
||||||
QString getData(){return QString::asprintf("%g %g %g\n", center.x(), center.y(), radius)+nameText;}
|
QString getData(){return QString::asprintf("%g %g %g\n", center.x(), center.y(), radius)+nameText;}
|
||||||
|
|
||||||
@ -295,7 +303,7 @@ private:
|
|||||||
QColor defaultColor = QColor(125, 185, 222);
|
QColor defaultColor = QColor(125, 185, 222);
|
||||||
QColor hoverColor = QColor(0, 98, 132);
|
QColor hoverColor = QColor(0, 98, 132);
|
||||||
QColor selColor = QColor(208, 90, 110);
|
QColor selColor = QColor(208, 90, 110);
|
||||||
QColor visitColor = QColor(93, 172, 129);
|
QColor visitColor = QColor(0, 137, 108);
|
||||||
QColor accessColor = QColor(178, 143, 206);
|
QColor accessColor = QColor(178, 143, 206);
|
||||||
QPen defaultPen;
|
QPen defaultPen;
|
||||||
QPen curPen;
|
QPen curPen;
|
||||||
@ -345,11 +353,14 @@ public:
|
|||||||
MyGraphicsVexItem* edVex(){return endVex;}
|
MyGraphicsVexItem* edVex(){return endVex;}
|
||||||
QString weightText(){return text;}
|
QString weightText(){return text;}
|
||||||
|
|
||||||
void visit(bool visited = true);
|
void visit(bool visit = true);
|
||||||
|
void itemHide();
|
||||||
|
void itemShow();
|
||||||
void remove();
|
void remove();
|
||||||
void access();
|
void access();
|
||||||
|
|
||||||
int type() const override {return Type;}
|
int type() const override {return Type;}
|
||||||
|
bool isVisited(){return state & ON_VISIT;}
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void setHover(bool in = true);
|
void setHover(bool in = true);
|
||||||
|
|||||||
8
main.cpp
8
main.cpp
@ -1,9 +1,17 @@
|
|||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
//int id = QFontDatabase::addApplicationFont(":/fonts/fonts/corbel.ttf");
|
||||||
|
//qDebug() << id;
|
||||||
|
//QFontDatabase::addApplicationFont(":/fonts/fonts/corbell.ttf");
|
||||||
|
//Qt::AA_EnableHighDpiScaling;
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
|
#endif
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
MainWindow w;
|
MainWindow w;
|
||||||
w.setWindowFlag(Qt::FramelessWindowHint);
|
w.setWindowFlag(Qt::FramelessWindowHint);
|
||||||
|
|||||||
@ -5,12 +5,21 @@
|
|||||||
#include <QRegion>
|
#include <QRegion>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
#if (QT_VERSION > QT_VERSION_CHECK(6,3,0))
|
||||||
|
#include <QFileDialog>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
: QMainWindow(parent)
|
: QMainWindow(parent)
|
||||||
, ui(new Ui::MainWindow)
|
, ui(new Ui::MainWindow)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->centralwidget->setMouseTracking(true);
|
ui->centralwidget->setMouseTracking(true);
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
ui->verticalLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
cornerRadius = 0;
|
||||||
|
#endif
|
||||||
QTimer *t = new QTimer(this);
|
QTimer *t = new QTimer(this);
|
||||||
connect(t, &QTimer::timeout, this, [=](){Init();});
|
connect(t, &QTimer::timeout, this, [=](){Init();});
|
||||||
t->setSingleShot(true);
|
t->setSingleShot(true);
|
||||||
@ -21,8 +30,13 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
|
|
||||||
void MainWindow::Init(){
|
void MainWindow::Init(){
|
||||||
/* Create main widget and set mask, style sheet and shadow */
|
/* Create main widget and set mask, style sheet and shadow */
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
QPainterPath path;
|
||||||
|
path.addRect(ui->mainWidget->rect());
|
||||||
|
#else
|
||||||
QPainterPath path;
|
QPainterPath path;
|
||||||
path.addRoundedRect(ui->mainWidget->rect(), cornerRadius - 1, cornerRadius - 1);
|
path.addRoundedRect(ui->mainWidget->rect(), cornerRadius - 1, cornerRadius - 1);
|
||||||
|
#endif
|
||||||
QRegion mask(path.toFillPolygon().toPolygon());
|
QRegion mask(path.toFillPolygon().toPolygon());
|
||||||
ui->mainWidget->setMask(mask);
|
ui->mainWidget->setMask(mask);
|
||||||
|
|
||||||
@ -30,15 +44,19 @@ void MainWindow::Init(){
|
|||||||
ui->mainWidget->setObjectName("mainWidget");
|
ui->mainWidget->setObjectName("mainWidget");
|
||||||
mainStyle = "QWidget#mainWidget{background-color:" + mainBackGround.name() + QString::asprintf(";border-radius:%dpx", cornerRadius) + "}";
|
mainStyle = "QWidget#mainWidget{background-color:" + mainBackGround.name() + QString::asprintf(";border-radius:%dpx", cornerRadius) + "}";
|
||||||
ui->mainWidget->setStyleSheet(mainStyle);
|
ui->mainWidget->setStyleSheet(mainStyle);
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
windowShadow = new QGraphicsDropShadowEffect(this);
|
windowShadow = new QGraphicsDropShadowEffect(this);
|
||||||
windowShadow->setBlurRadius(30);
|
windowShadow->setBlurRadius(30);
|
||||||
windowShadow->setColor(QColor(0, 0, 0));
|
windowShadow->setColor(QColor(0, 0, 0));
|
||||||
windowShadow->setOffset(0, 0);
|
windowShadow->setOffset(0, 0);
|
||||||
ui->mainWidget->setGraphicsEffect(windowShadow);
|
ui->mainWidget->setGraphicsEffect(windowShadow);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
/**********************************************************/
|
/**********************************************************/
|
||||||
|
|
||||||
/* Create border in order to cover the zigzag edge of the region */
|
/* Create border in order to cover the zigzag edge of the region */
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
border = new QWidget(this);
|
border = new QWidget(this);
|
||||||
border->move(ui->mainWidget->pos() - QPoint(1, 1));
|
border->move(ui->mainWidget->pos() - QPoint(1, 1));
|
||||||
border->resize(ui->mainWidget->size() + QSize(2, 2));
|
border->resize(ui->mainWidget->size() + QSize(2, 2));
|
||||||
@ -47,19 +65,28 @@ void MainWindow::Init(){
|
|||||||
border->setStyleSheet(borderStyle);
|
border->setStyleSheet(borderStyle);
|
||||||
border->setAttribute(Qt::WA_TransparentForMouseEvents);
|
border->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
border->show();
|
border->show();
|
||||||
|
#endif
|
||||||
/*****************************************************************/
|
/*****************************************************************/
|
||||||
|
|
||||||
/* Create settings page */
|
/* Create about page */
|
||||||
defaultSettingsPage = new SlidePage(cornerRadius, "ABOUT", ui->mainWidget);
|
defaultSettingsPage = new SlidePage(cornerRadius, "ABOUT", ui->mainWidget);
|
||||||
textInputItem *version = new textInputItem("version", defaultSettingsPage);
|
textInputItem *version = new textInputItem("version", defaultSettingsPage);
|
||||||
version->setValue("1.0");
|
version->setValue("1.3-beta");
|
||||||
version->setEnabled(false);
|
version->setEnabled(false);
|
||||||
textInputItem *updateDate = new textInputItem("last-upd", defaultSettingsPage);
|
textInputItem *updateDate = new textInputItem("last-upd", defaultSettingsPage);
|
||||||
updateDate->setValue("2021/12/4");
|
updateDate->setValue("2021/12/6 10:14");
|
||||||
updateDate->setEnabled(false);
|
updateDate->setEnabled(false);
|
||||||
textInputItem *Author = new textInputItem("author", defaultSettingsPage);
|
textInputItem *Author = new textInputItem("author", defaultSettingsPage);
|
||||||
Author->setValue("Linloir | Made with love");
|
Author->setValue("Linloir | Made with love");
|
||||||
Author->setEnabled(false);
|
Author->setEnabled(false);
|
||||||
|
textInputItem *lic = new textInputItem("lic", defaultSettingsPage);
|
||||||
|
lic->setValue("MIT License");
|
||||||
|
lic->setEnabled(false);
|
||||||
|
textInputItem *GitHub = new textInputItem("git", defaultSettingsPage);
|
||||||
|
GitHub->setValue("github.com/Linloir");
|
||||||
|
GitHub->setEnabled(false);
|
||||||
|
defaultSettingsPage->AddContent(GitHub);
|
||||||
|
defaultSettingsPage->AddContent(lic);
|
||||||
defaultSettingsPage->AddContent(Author);
|
defaultSettingsPage->AddContent(Author);
|
||||||
defaultSettingsPage->AddContent(updateDate);
|
defaultSettingsPage->AddContent(updateDate);
|
||||||
defaultSettingsPage->AddContent(version);
|
defaultSettingsPage->AddContent(version);
|
||||||
@ -321,7 +348,11 @@ MainWindow::~MainWindow()
|
|||||||
void MainWindow::mousePressEvent(QMouseEvent *event){
|
void MainWindow::mousePressEvent(QMouseEvent *event){
|
||||||
if(event->button() == Qt::LeftButton){
|
if(event->button() == Qt::LeftButton){
|
||||||
mousePressed = true;
|
mousePressed = true;
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
lastPos = event->globalPosition().toPoint() - this->frameGeometry().topLeft();
|
lastPos = event->globalPosition().toPoint() - this->frameGeometry().topLeft();
|
||||||
|
#else
|
||||||
|
lastPos = event->globalPos() - this->frameGeometry().topLeft();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,22 +383,28 @@ void MainWindow::mouseMoveEvent(QMouseEvent *event){
|
|||||||
else{
|
else{
|
||||||
if(mouseState == 0){
|
if(mouseState == 0){
|
||||||
if(maximized){
|
if(maximized){
|
||||||
qDebug() << event->pos() << ui->mainWidget->width();
|
|
||||||
qreal wRatio = (double)event->pos().x() / (double)ui->mainWidget->width();
|
qreal wRatio = (double)event->pos().x() / (double)ui->mainWidget->width();
|
||||||
qDebug() << wRatio;
|
|
||||||
controlWindowScale();
|
controlWindowScale();
|
||||||
qDebug() << ui->mainWidget->width();
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
qDebug() << QPoint(event->globalPosition().x() - ui->mainWidget->width() * wRatio, event->globalPosition().y());
|
|
||||||
qDebug() << this->frameGeometry().topLeft();
|
|
||||||
this->move(QPoint(event->globalPosition().x() - ui->mainWidget->width() * wRatio, -30));
|
this->move(QPoint(event->globalPosition().x() - ui->mainWidget->width() * wRatio, -30));
|
||||||
qDebug() << this->frameGeometry().topLeft();
|
#else
|
||||||
|
this->move(QPoint(event->globalPos().x() - ui->mainWidget->width() * wRatio, -30));
|
||||||
|
#endif
|
||||||
lastPos = QPoint(ui->mainWidget->width() * wRatio, event->pos().y());
|
lastPos = QPoint(ui->mainWidget->width() * wRatio, event->pos().y());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
this->move(event->globalPosition().toPoint() - lastPos);
|
this->move(event->globalPosition().toPoint() - lastPos);
|
||||||
|
#else
|
||||||
|
this->move(event->globalPos() - lastPos);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
QPoint d = event->globalPosition().toPoint() - frameGeometry().topLeft() - lastPos;
|
QPoint d = event->globalPosition().toPoint() - frameGeometry().topLeft() - lastPos;
|
||||||
|
#else
|
||||||
|
QPoint d = event->globalPos() - frameGeometry().topLeft() - lastPos;
|
||||||
|
#endif
|
||||||
if(mouseState & AT_LEFT){
|
if(mouseState & AT_LEFT){
|
||||||
this->move(this->frameGeometry().x() + d.x(), this->frameGeometry().y());
|
this->move(this->frameGeometry().x() + d.x(), this->frameGeometry().y());
|
||||||
this->resize(this->width() - d.x(), this->height());
|
this->resize(this->width() - d.x(), this->height());
|
||||||
@ -383,7 +420,11 @@ void MainWindow::mouseMoveEvent(QMouseEvent *event){
|
|||||||
this->resize(this->width(), this->height() + d.y());
|
this->resize(this->width(), this->height() + d.y());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
lastPos = event->globalPosition().toPoint() - this->frameGeometry().topLeft();
|
lastPos = event->globalPosition().toPoint() - this->frameGeometry().topLeft();
|
||||||
|
#else
|
||||||
|
lastPos = event->globalPos() - this->frameGeometry().topLeft();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,18 +435,23 @@ void MainWindow::resizeEvent(QResizeEvent *event){
|
|||||||
|
|
||||||
//Resize mask
|
//Resize mask
|
||||||
QPainterPath path;
|
QPainterPath path;
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
path.addRoundedRect(ui->mainWidget->rect(), cornerRadius - 1, cornerRadius - 1);
|
path.addRoundedRect(ui->mainWidget->rect(), cornerRadius - 1, cornerRadius - 1);
|
||||||
|
#else
|
||||||
|
path.addRect(ui->mainWidget->rect());
|
||||||
|
#endif
|
||||||
QRegion mask(path.toFillPolygon().toPolygon());
|
QRegion mask(path.toFillPolygon().toPolygon());
|
||||||
ui->mainWidget->setMask(mask);
|
ui->mainWidget->setMask(mask);
|
||||||
|
|
||||||
//Resize all pages
|
//Resize all pages
|
||||||
for(int i = 0; i < pageList.size(); i++){
|
for(int i = 0; i < pageList.size(); i++){
|
||||||
pageList[i]->resize(ui->mainWidget->width() * 0.3 < pageList[i]->preferWidth ? pageList[i]->preferWidth - 1 : ui->mainWidget->width() * 0.3 - 1, ui->mainWidget->height());
|
pageList[i]->resize(ui->mainWidget->width() * 0.4 < pageList[i]->preferWidth ? pageList[i]->preferWidth - 1 : ui->mainWidget->width() * 0.4 - 1, ui->mainWidget->height());
|
||||||
pageList[i]->resize(pageList[i]->width() + 1, pageList[i]->height());
|
pageList[i]->resize(pageList[i]->width() + 1, pageList[i]->height());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::controlWindowScale(){
|
void MainWindow::controlWindowScale(){
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
if(!maximized){
|
if(!maximized){
|
||||||
lastGeometry = this->frameGeometry();
|
lastGeometry = this->frameGeometry();
|
||||||
windowShadow->setEnabled(false);
|
windowShadow->setEnabled(false);
|
||||||
@ -435,6 +481,7 @@ void MainWindow::controlWindowScale(){
|
|||||||
this->move(lastGeometry.x(), lastGeometry.y());
|
this->move(lastGeometry.x(), lastGeometry.y());
|
||||||
maximized = false;
|
maximized = false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
MyCanvas* MainWindow::loadCanvas(const QString &path){
|
MyCanvas* MainWindow::loadCanvas(const QString &path){
|
||||||
|
|||||||
11
mainwindow.h
11
mainwindow.h
@ -48,7 +48,16 @@ private:
|
|||||||
QPoint lastPos;
|
QPoint lastPos;
|
||||||
void mouseMoveEvent(QMouseEvent *event);
|
void mouseMoveEvent(QMouseEvent *event);
|
||||||
void mousePressEvent(QMouseEvent *event);
|
void mousePressEvent(QMouseEvent *event);
|
||||||
void mouseReleaseEvent(QMouseEvent *event){mousePressed = false;}
|
void mouseReleaseEvent(QMouseEvent *event){
|
||||||
|
mousePressed = false;
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
|
||||||
|
if(event->globalPosition().y() < 2)
|
||||||
|
controlWindowScale();
|
||||||
|
#else
|
||||||
|
if(event->globalPos().y() < 2)
|
||||||
|
controlWindowScale();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
void resizeEvent(QResizeEvent *event);
|
void resizeEvent(QResizeEvent *event);
|
||||||
|
|
||||||
bool maximized = false;
|
bool maximized = false;
|
||||||
|
|||||||
58
mycanvas.cpp
58
mycanvas.cpp
@ -89,6 +89,14 @@ void MyCanvas::CreateSettings(int radius){
|
|||||||
view->setType(id == 0 ? MyGraphicsView::DG : MyGraphicsView::UDG);
|
view->setType(id == 0 ? MyGraphicsView::DG : MyGraphicsView::UDG);
|
||||||
type = id == 0 ? DG : UDG;
|
type = id == 0 ? DG : UDG;
|
||||||
});
|
});
|
||||||
|
singleSelectGroup *dfsSetting = new singleSelectGroup("Traverse Mode", this);
|
||||||
|
selectionItem *setGenerateTree = new selectionItem("Tree", "Generate tree", this);
|
||||||
|
selectionItem *setGenerateForest = new selectionItem("Forest", "Generate forest", this);
|
||||||
|
dfsSetting->AddItem(setGenerateTree);
|
||||||
|
dfsSetting->AddItem(setGenerateForest);
|
||||||
|
connect(dfsSetting, &singleSelectGroup::selectedItemChange, this, [=](int id){
|
||||||
|
generateForest = id == 1;
|
||||||
|
});
|
||||||
QWidget *whiteSpace = new QWidget(this);
|
QWidget *whiteSpace = new QWidget(this);
|
||||||
whiteSpace->setFixedHeight(30);
|
whiteSpace->setFixedHeight(30);
|
||||||
horizontalValueAdjuster *aniSpeed = new horizontalValueAdjuster("Animation speed", 0.1, 20, 0.1, this);
|
horizontalValueAdjuster *aniSpeed = new horizontalValueAdjuster("Animation speed", 0.1, 20, 0.1, this);
|
||||||
@ -100,6 +108,12 @@ void MyCanvas::CreateSettings(int radius){
|
|||||||
textInputItem *redesc = new textInputItem("Detail", this);
|
textInputItem *redesc = new textInputItem("Detail", this);
|
||||||
redesc->setValue(canvasDescription);
|
redesc->setValue(canvasDescription);
|
||||||
connect(redesc, &textInputItem::textEdited, this, [=](QString text){canvasDescription = text; emit descChanged(text);});
|
connect(redesc, &textInputItem::textEdited, this, [=](QString text){canvasDescription = text; emit descChanged(text);});
|
||||||
|
textButton *hideBtn = new textButton("Hide Unvisited Items", this);
|
||||||
|
connect(hideBtn, &textButton::clicked, this, [=](){view->HideUnvisited();});
|
||||||
|
textButton *showBtn = new textButton("Show Unvisited Items", this);
|
||||||
|
connect(showBtn, &textButton::clicked, this, [=](){view->ShowUnvisited();});
|
||||||
|
QWidget *whiteSpace2 = new QWidget(this);
|
||||||
|
whiteSpace2->setFixedHeight(30);
|
||||||
textButton *saveBtn = new textButton("Save to file", this);
|
textButton *saveBtn = new textButton("Save to file", this);
|
||||||
connect(saveBtn, &textButton::clicked, this, [=](){
|
connect(saveBtn, &textButton::clicked, this, [=](){
|
||||||
QString savePath = QFileDialog::getSaveFileName(this, tr("Save map"), " ", tr("Map file(*.map)"));
|
QString savePath = QFileDialog::getSaveFileName(this, tr("Save map"), " ", tr("Map file(*.map)"));
|
||||||
@ -110,6 +124,10 @@ void MyCanvas::CreateSettings(int radius){
|
|||||||
connect(delBtn, &textButton::clicked, this, [=](){emit setDel(this);});
|
connect(delBtn, &textButton::clicked, this, [=](){emit setDel(this);});
|
||||||
settings->AddContent(delBtn);
|
settings->AddContent(delBtn);
|
||||||
settings->AddContent(saveBtn);
|
settings->AddContent(saveBtn);
|
||||||
|
settings->AddContent(whiteSpace2);
|
||||||
|
settings->AddContent(showBtn);
|
||||||
|
settings->AddContent(hideBtn);
|
||||||
|
settings->AddContent(dfsSetting);
|
||||||
settings->AddContent(dirSetting);
|
settings->AddContent(dirSetting);
|
||||||
settings->AddContent(structureSetting);
|
settings->AddContent(structureSetting);
|
||||||
settings->AddContent(aniSpeed);
|
settings->AddContent(aniSpeed);
|
||||||
@ -353,19 +371,22 @@ void MyCanvas::Init(){
|
|||||||
viewLog *newLog = new viewLog("[BFS] | --- BFS start ---");
|
viewLog *newLog = new viewLog("[BFS] | --- BFS start ---");
|
||||||
newLog->setStyleSheet("color:#0078d4");
|
newLog->setStyleSheet("color:#0078d4");
|
||||||
logDisplay->addWidget(newLog);
|
logDisplay->addWidget(newLog);
|
||||||
bfs();
|
g->BFS(view->selectedVex(), generateForest);
|
||||||
|
view->hasVisitedItem = true;
|
||||||
});
|
});
|
||||||
connect(startDfs, &textButton::clicked, this, [=](){
|
connect(startDfs, &textButton::clicked, this, [=](){
|
||||||
viewLog *newLog = new viewLog("[DFS] | --- DFS start ---");
|
viewLog *newLog = new viewLog("[DFS] | --- DFS start ---");
|
||||||
newLog->setStyleSheet("color:#0078d4");
|
newLog->setStyleSheet("color:#0078d4");
|
||||||
logDisplay->addWidget(newLog);
|
logDisplay->addWidget(newLog);
|
||||||
dfs();
|
g->DFS(view->selectedVex(), generateForest);
|
||||||
|
view->hasVisitedItem = true;
|
||||||
});
|
});
|
||||||
connect(startDij, &textButton::clicked, this, [=](){
|
connect(startDij, &textButton::clicked, this, [=](){
|
||||||
viewLog *newLog = new viewLog("[Dij] | --- Dijkstra start ---");
|
viewLog *newLog = new viewLog("[Dij] | --- Dijkstra start ---");
|
||||||
newLog->setStyleSheet("color:#0078d4");
|
newLog->setStyleSheet("color:#0078d4");
|
||||||
logDisplay->addWidget(newLog);
|
logDisplay->addWidget(newLog);
|
||||||
dijkstra();
|
g->Dijkstra(view->selectedVex());
|
||||||
|
view->hasVisitedItem = true;
|
||||||
if(g->GetInfoOf(view->selectedVex())->strtVexInfo == nullptr){
|
if(g->GetInfoOf(view->selectedVex())->strtVexInfo == nullptr){
|
||||||
dijStart->setValue("Run dijkstra first");
|
dijStart->setValue("Run dijkstra first");
|
||||||
dijPrev->setValue("Run dijkstra first");
|
dijPrev->setValue("Run dijkstra first");
|
||||||
@ -429,34 +450,3 @@ void MyCanvas::addVex(MyGraphicsVexItem *vex){
|
|||||||
void MyCanvas::addArc(MyGraphicsLineItem *arc){
|
void MyCanvas::addArc(MyGraphicsLineItem *arc){
|
||||||
g->AddArc(arc);
|
g->AddArc(arc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyCanvas::dfs(){
|
|
||||||
MyGraphicsVexItem *strtVex = view->selectedVex();
|
|
||||||
if(strtVex != nullptr){
|
|
||||||
g->DFS(strtVex);
|
|
||||||
view->hasVisitedItem = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyCanvas::bfs(){
|
|
||||||
MyGraphicsVexItem *strtVex = view->selectedVex();
|
|
||||||
if(strtVex != nullptr){
|
|
||||||
g->BFS(strtVex);
|
|
||||||
view->hasVisitedItem = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyCanvas::dijkstra(){
|
|
||||||
MyGraphicsVexItem *strtVex = view->selectedVex();
|
|
||||||
if(strtVex){
|
|
||||||
g->Dijkstra(strtVex);
|
|
||||||
view->hasVisitedItem = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyCanvas::setWeight(int w){
|
|
||||||
MyGraphicsLineItem *arc = view->selectedArc();
|
|
||||||
if(arc){
|
|
||||||
g->SetWeight(arc, w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
13
mycanvas.h
13
mycanvas.h
@ -7,6 +7,11 @@
|
|||||||
#include "graph_view.h"
|
#include "graph_view.h"
|
||||||
#include "graph_implement.h"
|
#include "graph_implement.h"
|
||||||
|
|
||||||
|
#if (QT_VERSION > QT_VERSION_CHECK(6,3,0))
|
||||||
|
#include <QFileDialog>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class MyCanvas : public QWidget
|
class MyCanvas : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -25,6 +30,7 @@ private:
|
|||||||
AbstractGraph *g;
|
AbstractGraph *g;
|
||||||
int structure_type;
|
int structure_type;
|
||||||
int type;
|
int type;
|
||||||
|
bool generateForest = false;
|
||||||
|
|
||||||
void CreateSettings(int r);
|
void CreateSettings(int r);
|
||||||
void Init();
|
void Init();
|
||||||
@ -48,13 +54,6 @@ signals:
|
|||||||
private slots:
|
private slots:
|
||||||
void addVex(MyGraphicsVexItem*);
|
void addVex(MyGraphicsVexItem*);
|
||||||
void addArc(MyGraphicsLineItem*);
|
void addArc(MyGraphicsLineItem*);
|
||||||
//void delVex(MyGraphicsVexItem*);
|
|
||||||
//void delArc(MyGraphicsLineItem*);
|
|
||||||
void dfs();
|
|
||||||
void bfs();
|
|
||||||
void dijkstra();
|
|
||||||
void setWeight(int w);
|
|
||||||
void setAniRate(int step){view->setAniRate(step / 100.0);}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
BIN
screenshots/BFS.gif
Normal file
BIN
screenshots/BFS.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 MiB |
BIN
screenshots/ChangeType.gif
Normal file
BIN
screenshots/ChangeType.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.8 MiB |
BIN
screenshots/CreatePalette.gif
Normal file
BIN
screenshots/CreatePalette.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.0 MiB |
BIN
screenshots/DFS.gif
Normal file
BIN
screenshots/DFS.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 MiB |
BIN
screenshots/Dijkstra.gif
Normal file
BIN
screenshots/Dijkstra.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.6 MiB |
@ -7,7 +7,7 @@ SlidePage::SlidePage(int radius, QString name, QWidget *parent) :
|
|||||||
{
|
{
|
||||||
//if(parent)
|
//if(parent)
|
||||||
// resize(parent->width() * 0.8 <= preferWidth ? parent->width() * 0.8 : preferWidth, parent->height());
|
// resize(parent->width() * 0.8 <= preferWidth ? parent->width() * 0.8 : preferWidth, parent->height());
|
||||||
resize(parent->width() * 0.3 <= preferWidth ? preferWidth : parent->width() * 0.3, parent->height());
|
resize(parent->width() * 0.4 <= preferWidth ? preferWidth : parent->width() * 0.4, parent->height());
|
||||||
this->move(QPoint(-this->width() - 30, 0));
|
this->move(QPoint(-this->width() - 30, 0));
|
||||||
|
|
||||||
pageContentContainer = new ScrollAreaCustom(this);
|
pageContentContainer = new ScrollAreaCustom(this);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user