Skip to main content

A navigation widget based on PySide6

Project description

Sprintify Navigation

A navigation widget for PySide6 that handles large datasets efficiently. Built for interactive time-series visualization, Gantt charts, stock data, heatmaps - anything that needs smooth pan/zoom.

Sprintify Navigation Demo

## What it does
  • A toolbox to build specialized interactive navigation UIs
  • Easy to understand for AIs and humans
  • Built for time-series, Gantt charts, stock data, heatmaps, scatter plots, and more
  • Smooth pan/zoom with mouse wheel and drag
  • Renders only visible data (handles millions of points)
  • Dark/light mode through ColorMap
  • Mouse wheel pan/zoom, click-drag pan
  • Simple drawing API for rects, lines, text, or custom QPainter

Get started

pip install sprintify-navigation

Basic usage:

from sprintify.navigation.colors.modes import ColorMap
from sprintify.navigation.rulers import TimelineRuler, NumberRuler
from sprintify.navigation.navigation_widget import NavigationWidget
from PySide6.QtWidgets import QMainWindow, QApplication
from PySide6.QtGui import QBrush, QPen
from datetime import datetime, timedelta


class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.color_map = ColorMap(darkmode=True)

        # Setup rulers
        self.h_ruler = TimelineRuler(datetime(2024, 1, 1), datetime(2024, 12, 31))
        self.v_ruler = NumberRuler(0, 100, reverse=True)

        # Create widget
        self.widget = NavigationWidget(self.h_ruler, self.v_ruler, self.color_map)
        self.setCentralWidget(self.widget)

        # Draw stuff
        blue = self.color_map.get_saturated_color("blue", "fill")
        self.widget.draw_rects(
            "my_rects",
            lambda: [
                (datetime(2024, 3, 1), 20, timedelta(days=30), 15),
                (datetime(2024, 6, 1), 50, timedelta(days=45), 20),
            ],
            brush=QBrush(blue)
        )


if __name__ == "__main__":
    app = QApplication([])
    window = MyWindow()
    window.show()
    app.exec()

Examples

Check the examples/ folder for complete working apps:

Stock App

Stock App

stock_app.py - Real stock data via yfinance.

Scheduling App

Scheduling App

scheduling_app.py - Employee shifts (200 people, ItemRuler usage).

Sales Heatmap App

Navigation App

sales_heatmap_app.py - Sales correlation between products (ItemRuler x ItemRuler).

Navigation App

Navigation App

navigation_app.py - Random lines and Squares

Rulers

TimelineRuler

Date/time on horizontal axis. Auto-formats years/months/days/hours depending on zoom.

ruler = TimelineRuler(datetime(2024, 1, 1), datetime(2024, 12, 31))

NumberRuler

Numeric axis with SI units (k, M, G, etc). Can reverse for top-to-bottom.

ruler = NumberRuler(0, 10000, reverse=False)

ItemRuler

Categorical data - one band per item (employees, stocks, products, etc).

ruler = ItemRuler(
    item_count=100,
    default_pixels_per_item=40,
    min_pixels_per_item=20,
    max_pixels_per_item=150
)

Drawing

Rectangles

widget.draw_rects("layer_name", get_rects_func, brush=QBrush(color), pen=QPen(border))
# get_rects_func returns [(x, y, width, height), ...]

Lines

widget.draw_lines("layer_name", get_lines_func, pen=QPen(color, width))
# get_lines_func returns [(x1, y1, x2, y2), ...]

Text

widget.draw_texts("layer_name", get_texts_func, pen=QPen(color), font=QFont("Arial", 12))
# get_texts_func returns [(text, x, y), ...]

Custom drawing

def my_draw(painter):
    painter.setPen(QPen(Qt.red, 2))
    painter.drawEllipse(x, y, w, h)

widget.add_draw_command("custom", my_draw)

Colors

ColorMap handles theming:

color_map = ColorMap(darkmode=True)

# UI colors
bg = color_map.get_object_color("surface-base")
border = color_map.get_object_color("border")
text = color_map.get_object_color("text-base")

# Data viz colors
red = color_map.get_saturated_color("red", "fill")
blue = color_map.get_saturated_color("blue", "border")

Available: red, green, blue, cyan, orange, purple, pink, teal, lime, amber, grey

Controls

  • Wheel: Pan horizontal/vertical
  • Ctrl+Wheel: Zoom at mouse position
  • Alt+Wheel: Zoom vertical axis (NumberRuler only)
  • Click+Drag: Pan both axes

Performance tips

Only fetch visible data:

def get_visible_rects():
    start = self.h_ruler.visible_start
    end = self.h_ruler.visible_stop
    
    return [
        (x, y, w, h) 
        for x, y, w, h in all_data 
        if x + w >= start and x <= end
    ]

widget.draw_rects("rects", get_visible_rects, brush=QBrush(color))

Custom labels

ruler = ItemRuler(item_count=50)
widget = NavigationWidget(h_ruler, ruler, color_map)
widget.left_ruler_widget.get_label = lambda i: f"Employee {i+1}"

Ruler combinations

Mix rulers for different visualizations:

# Gantt chart
NavigationWidget(TimelineRuler(...), ItemRuler(...), color_map)

# Stock chart
NavigationWidget(TimelineRuler(...), NumberRuler(...), color_map)

# Correlation matrix
NavigationWidget(ItemRuler(...), ItemRuler(...), color_map)

# Scatter plot
NavigationWidget(NumberRuler(...), NumberRuler(...), color_map)

Architecture

Simple model-view split:

  • Rulers: Handle coordinate transforms, zoom, pan math
  • RulerWidgets: Render ticks/labels, handle mouse events
  • DrawingWidget: Canvas for data visualization
  • NavigationWidget: Composite putting it all together

Requirements

  • Python 3.8+
  • PySide6
  • yfinance (optional, only for stock example)

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sprintify_navigation-1.0.15.tar.gz (33.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sprintify_navigation-1.0.15-py3-none-any.whl (37.4 kB view details)

Uploaded Python 3

File details

Details for the file sprintify_navigation-1.0.15.tar.gz.

File metadata

  • Download URL: sprintify_navigation-1.0.15.tar.gz
  • Upload date:
  • Size: 33.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.12.3

File hashes

Hashes for sprintify_navigation-1.0.15.tar.gz
Algorithm Hash digest
SHA256 95a9163a25f9e5f1b87b78097dde1840b0c809665658180fddec54056288f311
MD5 97abc4f9125d31f873e84f8e203f11de
BLAKE2b-256 f65c85e65b73762cf699b301ba39103cc5140dc64f6e78b972445fbf761df1b2

See more details on using hashes here.

File details

Details for the file sprintify_navigation-1.0.15-py3-none-any.whl.

File metadata

File hashes

Hashes for sprintify_navigation-1.0.15-py3-none-any.whl
Algorithm Hash digest
SHA256 d8c49b938af1179b482ffef3e14209426a645bc0bc6539149263bd8d6b3596ea
MD5 30c3bc24cca436a31f84c424a5433f91
BLAKE2b-256 0b64e03a4e6faa34d8881d6bc3ef13f66ff6b622074c288dc761e133f1fdb578

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page