Coder Social home page Coder Social logo

cneben / quickqanava Goto Github PK

View Code? Open in Web Editor NEW
1.1K 69.0 217.0 19.85 MB

:link: C++17 network / graph visualization library - Qt6 / QML node editor.

Home Page: http://cneben.github.io/QuickQanava/index.html

License: Other

QML 14.50% C++ 84.77% QMake 0.04% C 0.19% CMake 0.50%
graph dataflow-programming graphs qml cpp-library qt-containers graph-visualization complex-networks graph-theory cpp

quickqanava's Introduction

QuickQanava

Linux Qt5 g++ qmake Win64 Qt5 msvc qmake Win64 Qt6 msvc CMake

Documentation License Twitter URL

QuickQanava is a C++17 library developed for rendering graphs and relational content within a Qt/QML application. It offers QML components and C++ classes designed for visualizing medium-sized directed graphs in a C++/QML application. QuickQanava emphasizes the presentation of relational content in a dynamic user interface, featuring Drag-and-Drop support, resizable content, and visual creation of topology. QuickQanava focus authoring of topology delegates in pure QML.

QuickQanava main repository is hosted on GitHub: http://cneben.github.io/QuickQanava/index.html

QuickQanava is primarily developed with Qt 6.6.1 with MSVC2019 and g++11 (minimal required Qt version is Qt 6.5.0, recommended is Qt 6.6.1).

If you are interested in Qt5.15 support, last release supporting Qt5 is 2.4.0

❓ benoit_à_destrat.io

QuickQanava Showcase

Edges:

Curved-Straight Edges

Nodes: User Doc: QuickStart - Custom Nodes

Custom content

Visual Connector: User Doc: QuickStart - Visual Connector

Visual Connector

Groups: User Doc: QuickStart - Using Groups

Groups

Styles: User Doc: QuickStart - Using Styles

Contributors

GitHub Contributors Image

  • @kwallner / Conan.io and CMake configuration
  • @Letrab / Edge configuration
  • @machinekoder / QML plugin and CMake configuration
  • @NielsBillen / Ports support and stability fixes
  • @walterbrebels
  • @chesnoksatan / Major connector feature, build configuration

QuickQanava include bezier library distributed with MIT licence on https://github.com/oysteinmyrmo/bezier

License

License

Copyright (c) 2017-2024 BA

quickqanava's People

Contributors

anahit-m avatar carpikes avatar cjgdev avatar cneben avatar emmenlau avatar fpaupier avatar jrens avatar kwallner avatar letrab avatar linslzero avatar machinekoder avatar nielsbillenluminex avatar pahakul avatar rakhimov avatar sanchaez avatar sc-one avatar shuangliu1992 avatar stefanvk avatar ulricheck avatar walterbrebels avatar winterheart avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

quickqanava's Issues

Using C++ class enums in QML

Due to a bug in Qt (already there since 5.8) the registrations of C++ enum classes in QML are not handled properly (because of this bug: https://bugreports.qt.io/browse/QTBUG-58454).

E.g. an example is that in QML Qan.PortItem.Out is not known.
Which causes that the function insertPort cannot be called with custom parameters.

Fix is easy by manually declaring the enum with Q_DECLARE_METATYPE , as normally Q_ENUM should do already... Or remove the "class" in "enum class".

Affected enums:
NodeItem:
Q_ENUM(Connectable)
Q_ENUM(Dock)
PortItem:
Q_ENUM(Type)
Q_ENUM(Multiplicity)
Style:
Q_ENUM(FillType)
Q_ENUM(EffectType)
Q_ENUM(LineType)

Feature request: Add support for port associated delegate components and other enhancements

I am trying to copy this look:
blender

  • As you can see, each port has an associated "qml component" with it. (Now only the graph has a port delegate.)

  • I'd like to create node ports dynamically with custom and different delegates (as you can see in the pic). And this being not only visual but each port having a value QVariant property that can be read (and modified from within node/port).

  • A model for ports (getting the label, dock type, value..)

  • Also it would be nice to being able to connect ports without needing to click on the port and drag the connector, and just drag from the port (less of a pain).

  • Expose the selection rectangle instead of {color,weight,margin} for better configurability (like radius etc.)

Edge start end geometry configuration new feature

First issues/todos with recent edge start/end geometry configuration:

  • Edge items are invisible until host node is moved (missing an initial call to updateItem() ?).
  • Round items are not working when src and dst are both Qan.EdgeItem.Cirlce/Qan.EdgeItem.CircleOpen

image

Cannot click on connector (its real place is shifted from where its visually drawn)

The example project from #29 can demostrate this.
Try to move the node's connector: you can't, it just moves the node. But if you click a bit shifted away, to the top-left, compared to the connector, then you can grab it. In my personal project on windows i cant even click on a node but have to shift. Right click also does not appear where it should but shifted to the right-bottom direction. Seems universal. And yes, this is a windows-only issue....:)

Arrow shader issue under linux: GLSL 1.50 is not supported

QOpenGLShader::compile(Vertex): 0:1(10): error: GLSL 1.50 is not supported. Supported versions are: 1.10, 1.20, 1.30, 1.00 ES, and 3.00 ES

*** Problematic Vertex shader source code ***
#version 150 core
#define lowp
#define mediump
#define highp
#line 1

attribute highp vec2 vertex;

void main() {
    gl_Position = vec4( vertex, 0., 1. );
}

***
QOpenGLShader::compile(Fragment): 0:1(10): error: GLSL 1.50 is not supported. Supported versions are: 1.10, 1.20, 1.30, 1.00 ES, and 3.00 ES

*** Problematic Fragment shader source code ***
#version 150 core
#define lowp
#define mediump
#define highp
#line 1

uniform lowp float opacity;
uniform lowp vec4 color;
uniform highp float width;
smooth in float dist;

void main() {
    lowp float feather = ( width < 1.00001 ? width :
                                             1.0 - smoothstep( 0.65, 1.0, abs(dist) ) );
    gl_FragColor = color * opacity * feather;
}

Insert qan::Edge directly with qan::Graph::insertEdge(org, dst, ...) being org and dst qan::PortItem

Hello! This is posible?
I see that qan::PortItem inhertis from qan::NodeItem.
I thik that this idea might work:

auto node1 = graph->insertNode<CustomNode>();
auto node2 = graph->insertNode<CustomNode>();
auto in1 = graph->insertPort<CustomPort>(node1, qan::NodeItem::Dock::Left, qan::PortItem::Type::In, "IN1", "in1");
auto out1 = graph->insertPort<CustomPort>(node2, qan::NodeItem::Dock::Right, qan::PortItem::Type::Out, "OUT1", "out1");
...
auto portIn = node1->findPort("IN1");
auto portOut = node2->findPort("OUT1");
if(portIn && portOut){
    graph->insertEdge<CustomEdge>(portIn, portOut);
}

GTpo: Unable to build with Clang on MacOS: noexcept on default constructors

I cannot build anymore on MacOS since latest updates (since merge commit d8bc6b2) because of compiler errors.

Apparently it is not allowed to use noexcept on default constructors, as also mentioned here:

https://stackoverflow.com/questions/29483120/program-with-noexcept-constructor-accepted-by-gcc-rejected-by-clang

For me only file GTpo/src/behaviour.h caused a problem, changing these lines fixed it:

- behaviour( const behaviour& rhs ) noexcept = default;
- behaviour& operator=( const behaviour& rhs ) noexcept = default;
+ behaviour( const behaviour& rhs ) = default;
+ behaviour& operator=( const behaviour& rhs ) = default;

(Un)Selection misbehaviour

When using the Groups sample project with the latest master revision, strange behaviour is obtained when unselecting a Node (haven't tried with Groups yet) via CTRL + click.

Steps to reproduce + problem:

  • Select N3
  • Press CTRL
  • Select N2
  • Release CTRL
  • Move N2
    N2 and N3 move
  • Press CTRL
  • Select N3
  • Click empty space (unselect all)
    NOK: N2 gets unselected, N3 is not [unselect bug]
  • Drag N3 (no first click, directly drag)
    OK
  • Drag N2
    OK
  • Keep N2 selected and drag N3
    NOK: Both N2 and N3 move
  • Keep N2 selected and drag N2
    OK: Only N2 moves [+unselect bug]

After this sequence I cannot find a way to unselect N3 (visually at least)...

Sorry for the spam, I just like to contribute to make your library even better ;-).

Runtime error on Ubuntu 18.04 : "QtQuick.Shapes" is not installed

Cloned the source with Git and compiled with QTCreator, compilation ends without any error.
Running any of the examples fails with the following message:

QML debugging is enabled. Only use this in a safe environment.
QuickQanava::initialize(): Warning: QuickQanava depends on Qt Quick Shapes library available since Qt 5.10.
QQmlApplicationEngine failed to load component
qrc:/style.qml:43 Type Qan.GraphView unavailable
qrc:/QuickQanava/GraphView.qml:36 module "QtQuick.Shapes" is not installed

The following packages are installed:
dpkg -l |grep qtquick
ii qml-module-qtquick-controls:amd64 5.9.5-0ubuntu1 amd64 Qt 5 Quick Controls QML module
ii qml-module-qtquick-controls2:amd64 5.9.5-0ubuntu2 amd64 Qt 5 Qt Quick Controls 2 QML module
ii qml-module-qtquick-dialogs:amd64 5.9.5-0ubuntu1 amd64 Qt 5 Dialogs QML module
ii qml-module-qtquick-extras:amd64 5.9.5-0ubuntu1 amd64 Qt 5 Quick Extras QML module
ii qml-module-qtquick-layouts:amd64 5.9.5-0ubuntu1.1 amd64 Qt 5 Quick Layouts QML module
ii qml-module-qtquick-privatewidgets:amd64 5.9.5-0ubuntu1 amd64 Qt 5 Private Widgets QML module
ii qml-module-qtquick-scene2d:amd64 5.9.5+dfsg-0ubuntu2 amd64 Qt 5 Quick Scene 2D QML module
ii qml-module-qtquick-scene3d:amd64 5.9.5+dfsg-0ubuntu2 amd64 Qt 5 Quick Scene 3D QML module
ii qml-module-qtquick-templates2:amd64 5.9.5-0ubuntu2 amd64 Qt 5 Qt Quick Templates 2 QML module
ii qml-module-qtquick-window2:amd64 5.9.5-0ubuntu1.1 amd64 Qt 5 window 2 QML module
ii qml-module-qtquick2:amd64 5.9.5-0ubuntu1.1 amd64 Qt 5 Qt Quick 2 QML module
ii qtquickcontrols2-5-dev:amd64 5.9.5-0ubuntu2 amd64 Qt 5 Quick Controls 2 development files
ii qtquickcontrols2-5-doc 5.9.5-0ubuntu2 all Qt 5 Quick Controls 2 documentation
ii qtquickcontrols5-doc 5.9.5-0ubuntu1 all Qt 5 Quick Controls documentation

module “QtQuick.Shapes” is not installed (qt 5.12.2)

Cloned the source with Git and compiled with QTCreator, compilation ends without any error.
Running any of the examples successed with QtCreator,but when i run the release version with the .exe , then the message show up that "module “QtQuick.Shapes” is not installed "

in example topolopy, when i execute "clear Graph" that is error

in example topolopy, when i execute "clear Graph", the message show "TypeError: Property 'clear' of object qan::FaceGraph_QML_70(0x7884400, "graph") is not a function",so i modify "void clear() noexcept;" to " Q_INVOKABLE void clear() noexcept;" in the file "qanGraph.h" 103 line ,but that still error.

v0.12.0 discussion

First 0.12.0 commit 28c8c65 in 0_12_0 branch.

Changelog:

  • gtpo::group<> concept removed.
  • every node is now potentially a group ... and every group is simply a node, meaning that node could be connected to group by an edge and that group could be "grouped" inside another group.
  • Lot of duplicated glue code removed from qan::NodeItem / qan::GroupItem.
  • There should not be a lot of changes from a user code POV.

BUGS:

  • qan::Graph::groupAt() should take group "global z" into account (ie all parent z + local z), otherwise node can't be dropped in a group item inside a group.
  • gtpo::node<> group adjacent edge set generation is broken (edges are not refresh correctly when a group with adjacent edges is moved).

image

Build Failure on Mac OSX

Build failures on Mac:

Qt version: Qt5.9
Compiler: clang 64bit and/or gcc

/Users/theUser/Depot/external/QuickQanava/src/qanDraggableCtrl.hpp:251: error: static_cast from 'qan::GroupItem ' to 'QQuickItem ', which are not related by inheritance, is not allowed
static_cast<QQuickItem
>(group->getItem()) != static_cast<QQuickItem
>(_targetItem.data()) ) // Do not drop a group in itself

macOS 10.14.1 Qt 5.11.1 Clang

macOS 10.14.1 Qt 5.11.1 Clang compiled successfully. Please update build results.
Apple LLVM version 10.0.0 (clang-1000.11.45.5)
Qt 5.11.1
macOS 10.14.1

Qan.Graph: Unable to change node/port delegate

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3

import QuickQanava 2.0 as Qan
import "qrc:/QuickQanava" as Qan

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Qan.GraphView {
        id: graphView
        z: -1
        anchors.fill: parent
        navigable: true
        graph: Qan.Graph {
            id: graph
            anchors.fill: parent
            objectName: "graph"
            clip: true
            connectorEnabled: false
            nodeDelegate: Qan.NodeItem {
                width: 150
                height: 80

                Rectangle {
                    anchors.fill: parent
                    color: "blue"
                    border.color: "green"
                }
            }
            portDelegate: Qan.PortItem {
                width: 16
                height: 16

                Rectangle {
                    anchors.fill: parent
                    color: "black"
                    border.color: "yellow"
                }
            }

            Component.onCompleted: {
                var n1 = graph.insertNode()
                n1.label = "Default.Node"
                n1.item.x = 30
                n1.item.y = 30
                graph.insertInPort(n1, Qan.NodeItem.Left)
                graph.insertInPort(n1, Qan.NodeItem.Left)
                graph.insertInPort(n1, Qan.NodeItem.Right)
                graph.insertInPort(n1, Qan.NodeItem.Right)
            }
        }
    }
}

The nodeDelegate and portDelegate properties do not change anything.

Folded Groups issues: Edges shown when dragging + drop nodes when hidden

I am using the latest master revision and the Groups sample project:

There are happening a few strange things, in my understanding:

  • Add a Node to a Group and make a connection with a Node outside this group.
    Now fold(close) the group. As expected the Node and connecting edge is also hidden.
    Now move the visible Node around. Now the hidden edge becomes visible suddenly... This seems unwanted behaviour to me?

  • When folding a Group, it is still possible to drop a Node into the invisible Group. This is very confusing, as when re-ordering/dragging nodes around, suddenly they can become part of a hidden Group.
    Which also means that a very big group (in size) almost always will catch a drag/drop action of a Node...

Thank you very much for your work! Thumbs up!

Possible memory leak

Hi,
I'm using QuickQanava for a project and it seems to leak memory each time I load a graph.
So I've built this quick demo and I ran using the Address Sanitizer (g++ -fsanitize=address):

#include <QGuiApplication>
#include <QFont>
#include <QFontDatabase>

#include <QuickQanava>

int main(int argc, char *argv[])
{
    int fargc=0;
    QGuiApplication app(fargc, NULL);

    for(int i=0;i<10;i++) {
        printf("------BEGIN------\n");
        QQmlApplicationEngine engine;
        QuickQanava::initialize(&engine);
        engine.load(QUrl(QStringLiteral("qrc:/newscene.qml")));
    }

    return 0;
}

and there are some memory leaks proportional to the number of iterations of the loop:
leak.txt

There are a set of leaks which share a common pattern:

Indirect leak of 41600 byte(s) in 180 object(s) allocated from:
    #0 0x7f62c4818d29 in operator new(unsigned long) [...]
[... QML stuff]
    #26 0x7f62b8df98ec in qan::Connector::setEdgeComponent(QQmlComponent*) /QuickQanava/src/qanConnector.cpp:211
[... QML stuff]
    #37 0x7f62b8dfcaff in qan::Graph::createFromComponent([...]) /QuickQanava/src/qanGraph.cpp:340
    #38 0x7f62b8dfd01e in qan::Graph::componentComplete() /QuickQanava/src/qanGraph.cpp:99
[... QML stuff]
    #45 0x7f62c34008ce in QQmlApplicationEngine::load(QUrl const&) /qt5-declarative/src/qtdeclarative-everywhere-src-5.12.1/src/qml/qml/qqmlapplicationengine.cpp:259
    #46 0x40121c in main (/TestQQ/build/TestQQ+0x40121c)

So I added a bunch of printfs in each constructor/destructor of qanGraph, qanDraggable, qanConnector, etc. and i got this:

[A] 0x6120001f27c0: GraphView
[A] 0x618000007480: Graph
[A] 0x616000099fe0: Draggable
[A] 0x616000099f80: NodeItem
[A] 0x616000099f80: Connector
[A] 0x615000065c00: EdgeItem
[D] 0x616000099f80: Connector
[D] 0x616000099f80: NodeItem
[D] 0x616000099fe0: Draggable

where A is allocate(the constructor) and D is the destructor: it seems that qanGraphView, qanGraph and qanEdgeItem are not deallocated after the destruction.
I tried to add the following code in Connector::~Connector which removes part of the leaks even if the
[D] 0x..: EdgeItem is not printed (wtf?):

if(_edgeItem)
    delete _edgeItem;

Do you think it's OK to deallocate the pointers inside qanConnector when the object is destroyed? Are they shared by any other class? Is there a better way to do that?

Arrow angle calculation off in special case (curved + short line + equal height)

Hi Benoit,

I found out, by coincidence, that the angle calculation of a curved line could be off, in a special case:

To (easily) reproduce, draw these nodes + edge, with a small distance between the nodes:

                var tl = graph.insertNode()
                tl.label = "TL"; tl.item.x = 50; tl.item.y = 50

                var tml = graph.insertNode()
                tml.label = "TML"; tml.item.x = 200; tml.item.y = 50
                graph.insertEdge(tl, tml);

This happens at firstly showing:

screen shot 2018-09-11 at 14 49 47

I did some tracing already, and it has to do with a special case when the cubicCurveAngleAt and lineAngle calculation lie roughly 360 degrees apart...
I added some tracing as well:

POINT 75.0007 74.9993
(p1.y() and p2.y())
SMALLER -0.0014643
(lineAngle, line.dy() is smaller than 0.0)
Special case 0.000647655 359.998
(result of resp. cubicCurveAngleAt(0.99, cache.p1, cache.p2, cache.c1, cache.c2) and lineAngle(line))
qml: Rotation 215.9990081604425
(end calculation of 0.4 * ... + 0.6 * ....)

I only was able to draw it correctly by only taking into account the angle of lineAngle(). Probably there is a more pragmatic way solving this.

With a slight drag action of a node, it is already solved, probably some pixel-alignment?
Also afterwards it is very hard to reproduce by just dragging...

Thanks

Crash when dragging over a node if the source is not a QQuickItem

This can happen for example when dragging files from the explorer into the application window, over a node.

These two lines are the issue:
QQuickItem* sourceItem = qobject_cast<QQuickItem*>(event->source());
QVariant draggedStyle = sourceItem->property( "draggedStyle" ); // The source item (usually a style node or edge delegate must expose a draggedStyle property.

The variable sourceItem should be checked for nullity before being accessed.

Unable to set leftDock or rightDock in Qan.NodeItem

When having only set

verticalDockDelegate: Component {
    VerticalDock {
    }
}

in Qan.Graph they appear fine, but when i set

leftDock: VerticalDock {
    dockType: Qan.NodeItem.Left
    hostNodeItem: root
}
rightDock: VerticalDock {
    dockType: Qan.NodeItem.Right
    hostNodeItem: root
}

in my node delegate qml file (Qan.NodeItem) both do not appear.

Full example:

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3

import QuickQanava 2.0 as Qan
import "qrc:/QuickQanava" as Qan

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Qan.GraphView {
        id: graphView
        z: -1
        anchors.fill: parent
        navigable: true
        graph: Qan.Graph {
            id: graph
            anchors.fill: parent
            objectName: "graph"
            clip: true
            connectorEnabled: false
            nodeDelegate: Qan.NodeItem {
                id: nodeItem
                width: 150
                height: 80
                leftDock: Qan.VerticalDock { // if you comment this out, it appears.
                }
                
                Rectangle {
                    anchors.fill: parent
                    color: "blue"
                    border.color: "green"
                }
            }
            portDelegate: Qan.PortItem {
                width: 16
                height: 16

                Rectangle {
                    anchors.fill: parent
                    color: "black"
                    border.color: "yellow"
                }
            }
            verticalDockDelegate: Qan.VerticalDock { // this works fine
            }

            Component.onCompleted: {
                var n1 = graph.insertNode(nodeDelegate)
                n1.label = "Default.Node"
                n1.item.x = 30
                n1.item.y = 30
                graph.insertInPort(n1, Qan.NodeItem.Left)
                graph.insertInPort(n1, Qan.NodeItem.Left)
                graph.insertInPort(n1, Qan.NodeItem.Right)
                graph.insertInPort(n1, Qan.NodeItem.Right)
            }
        }
    }
}

Install step / Build QML plugins with CMake - Discussion

Currently, there is no install step specified in the CMakeLists.txt. This makes it unclear how to use QuickQanava in an application.

I suggest deploying QuickQanava as QML module, so it can be easily used by other applications, even if they are written in PyQt for example. I have done this in my framework by installing the QML files and libraries to the QT_INSTALL_QML path (see deployment.pri). This also requires adding a plugin.cpp containing the plugin description.

Unfortunately, I haven't worked a lot with the Qt + CMake combination so far, so I can't provide any recipes. However, if QuickQanava turns out to be useful for my application, I'm happy to contribute any changes I make back upstream.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.