Compare commits

...

11 Commits
V1.1 ... main

Author SHA1 Message Date
e965427be4
Update Readme 2022-11-02 17:06:37 +08:00
629698c05c
update gitignore 2022-10-02 11:56:27 +08:00
06fb056c09
Add support for QT version 6.4.0 2022-10-02 11:44:01 +08:00
6309cce382 Fixed bugs for QT version 5.9.9 and display issue for ubuntu 2022-02-25 15:51:35 +08:00
5a5a3541bf Fix bugs for QT5.9.9 and adjust display for ubuntu 2022-02-25 15:49:21 +08:00
002b291023 Upload course
Course now available!!!
2022-01-28 00:01:21 +08:00
霖落
c2059dad4b
Create README.md 2022-01-15 10:35:50 +08:00
354da102e5 upload map 2021-12-09 14:59:09 +08:00
f735ff31d4 Update hide functions
Now hiding unvisited items is available
2021-12-06 10:22:19 +08:00
dd1fc7f34b Delete qDebug() and update version 2021-12-06 08:34:24 +08:00
234994c385 Add generate forest function
Now traverse can generate forest
2021-12-06 08:24:38 +08:00
29 changed files with 704 additions and 79 deletions

1
.gitignore vendored
View File

@ -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
View File

@ -0,0 +1,181 @@
# 从头开始完成GraphBuilder工程
## 实验要求
1. 以邻接多重表为存储结构,实现联通无向图的深度优先和广度优先遍历。以指定的节点为起点,分别输出每种遍历下的节点访问序列和相应生成树的边集。
2. 以邻接表为存储结构,建立深度优先生成树和广度优先生成树,并以树型输出生成树。
3. 测试数据如图:![测试](gb_commentary/testbench.png)
## 分析需求
> 在本节中将分析上述题目要求,大致明确程序所需要完成的模块及功能
由于需要以树型输出生成树,因此最好能够实现**可视化控件**,其需要支持显示图结构
为了便于添加点和线,故可视化控件需要支持**添加及删除点和线**的功能
从测试数据图中看出,输入的数据为带权图,因此对于该控件还需要实现**添加及修改权重**的功能
由于需要进行遍历,为了体现遍历过程,该控件需要实现**创建节点和边的访问动画**功能
在数据结构层面,需要实现**邻接表**和**邻接多重表**两种数据结构
为了避免演示时不同数据结构需要分开建立测试数据,因此需要为两种不同的数据结构实现一个**虚基类**,并使两种不同的结构均从该虚基类继承并添加**转换函数**,实现两种不同数据结构的互相转换
## 程序设计
> 在本节中,将依据上述需求,对各个需要实现的模块进行更进一步的分析,并给出其实现的过程
从上述需求可以看出,实现最基本的功能大致需要将程序分为两个主要部分:
- **可视化控件**:类画板控件,负责处理图中点和线的元素对象的显示、修改等操作,并为数据结构提供功能接口,诸如调用动画等
- **数据结构**:需要使用要求的数据结构类将上述可视化控件中的元素对象组织起来,并调用其提供的接口实现如深度优先遍历等功能
下面将依次完成这两个主要部分
### 可视化控件(画板)
由于需要实现的这个可视化控件的主要功能是**对图元对象进行管理并使它们可视化**。
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
View 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
![CreatePalette](screenshots/CreatePalette.gif)
![BFS](screenshots/BFS.gif)
![DFS](screenshots/DFS.gif)
![Dijkstra](screenshots/Dijkstra.gif)
![ChangeType](screenshots/ChangeType.gif)

87
cities.map Normal file
View 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

View File

@ -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
} }
} }

View File

@ -13,6 +13,7 @@
#include <QMouseEvent> #include <QMouseEvent>
#include <QWheelEvent> #include <QWheelEvent>
#include <QTimer> #include <QTimer>
#include <QtMath>
#define MAXSPEED 70 #define MAXSPEED 70

View File

@ -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

2
fonts.qrc Normal file
View File

@ -0,0 +1,2 @@
<!DOCTYPE RCC>
<RCC version="1.0"/>

BIN
fonts/corbel.ttf Executable file

Binary file not shown.

BIN
fonts/corbelb.ttf Executable file

Binary file not shown.

BIN
fonts/corbeli.ttf Executable file

Binary file not shown.

BIN
fonts/corbell.ttf Executable file

Binary file not shown.

BIN
fonts/corbelli.ttf Executable file

Binary file not shown.

BIN
fonts/corbelz.ttf Executable file

Binary file not shown.

View File

@ -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){
@ -795,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;
@ -820,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;
@ -847,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){

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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,23 +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 about 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.1 beta"); 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/5"); 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); textInputItem *GitHub = new textInputItem("git", defaultSettingsPage);
GitHub->setValue("github.com/Linloir"); GitHub->setValue("github.com/Linloir");
GitHub->setEnabled(false); GitHub->setEnabled(false);
defaultSettingsPage->AddContent(GitHub); defaultSettingsPage->AddContent(GitHub);
defaultSettingsPage->AddContent(lic);
defaultSettingsPage->AddContent(Author); defaultSettingsPage->AddContent(Author);
defaultSettingsPage->AddContent(updateDate); defaultSettingsPage->AddContent(updateDate);
defaultSettingsPage->AddContent(version); defaultSettingsPage->AddContent(version);
@ -325,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
} }
} }
@ -356,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());
@ -387,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
} }
} }
@ -398,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);
@ -439,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){

View File

@ -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;if(event->globalPosition().y() < 2) controlWindowScale();} 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;

View File

@ -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);
}
}

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

BIN
screenshots/ChangeType.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 MiB

BIN
screenshots/DFS.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

BIN
screenshots/Dijkstra.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 MiB

View File

@ -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);