Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
4257d16
PM-140 Added experimental API section
MostafaNanticock Oct 19, 2025
7815966
PM-140 Add support for removing property editors
MostafaNanticock Oct 20, 2025
76f1100
PM-140 Move addProperty template implementation
MostafaNanticock Oct 20, 2025
927979e
PM-140 Refactor PropertyContext to standalone header file
MostafaNanticock Oct 20, 2025
cb06e3f
PM-140 Add replacePropertyEditor API to PropertyGrid
MostafaNanticock Oct 20, 2025
5b30ddd
PM-140 Refactor property editor registration and usage
MostafaNanticock Oct 20, 2025
3a3d9d5
PM-140 Rename internal headers to *_p.h and update includes
MostafaNanticock Oct 20, 2025
3b89fc0
PM-140Add Qt version-compatible string helpers
MostafaNanticock Oct 20, 2025
bafea65
PM-140 Ignore markdown file changes in CI workflows
MostafaNanticock Oct 20, 2025
1c7f1e6
PM-140 fix build errors for Qt <= 5.12
MostafaNanticock Oct 20, 2025
0d4eeac
Merge pull request #4 from Nanticock/PM-140-Eliminate-the-need-to-exp…
MostafaNanticock Oct 20, 2025
ffbe7ca
Revise README for current status and features
MostafaNanticock Oct 20, 2025
dbf5ca8
Add option to control building of example projects
MostafaNanticock Oct 20, 2025
527bf42
Update README with PropertyContext file details
MostafaNanticock Oct 20, 2025
975cd62
PM-183 initial implementation for object_property_grid
MostafaNanticock Nov 24, 2025
f267fb5
PM-183 refactored ObjectPropertyGrid::updateProperties()
MostafaNanticock Nov 24, 2025
07434e3
PM-183 Added MainWindow
MostafaNanticock Nov 24, 2025
fb4d285
PM-183 Added MainWindow logic
MostafaNanticock Nov 24, 2025
4431a01
PM-183 cleaned object_property_grid example
MostafaNanticock Nov 25, 2025
fb17a53
Merge pull request #5 from Nanticock/PM-183-Add-an-ObjectPropertyGrid…
MostafaNanticock Nov 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ on:
workflow_dispatch:
push:
branches: [main, develop]
paths-ignore:
- '*.md'

pull_request:
branches: [main, develop]
paths-ignore:
- '*.md'

jobs:
get-matrix:
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ on:
workflow_dispatch:
push:
branches: [main, develop]
paths-ignore:
- '*.md'

pull_request:
branches: [main, develop]
paths-ignore:
- '*.md'

jobs:
get-matrix:
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ on:
workflow_dispatch:
push:
branches: [main, develop]
paths-ignore:
- '*.md'

pull_request:
branches: [main, develop]
paths-ignore:
- '*.md'

jobs:
get-matrix:
Expand Down
7 changes: 6 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,10 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

option(PM_BUILD_PROPERTY_GRID_EXAMPLES "Determines whether or not the example projects should be built with the library" ON)

add_subdirectory(src)
add_subdirectory(examples)

if(PM_BUILD_PROPERTY_GRID_EXAMPLES)
add_subdirectory(examples)
endif()
93 changes: 44 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,49 +16,10 @@ This library provides a flexible and customizable property editor that displays
> **Current Status:**
> - ✅ **API is stable** - Safe to use in your projects without worrying about breaking changes
> - ⚠️ **Implementation is not fully polished** - Some features may have rough edges
> - 🚧 **Work in progress** - Actively being improved in my free time to become production-ready
> - 🚧 **Work in progress** - Actively being improved to become production-ready
>
> Feel free to use it, report issues, and contribute! The core functionality works well, and the API won't change in ways that break your code.

## Features

- **Comprehensive Type Support**: Built-in support for all major Qt types including:
- Basic types: `int`, `bool`, `QString`, `double`
- Geometric types: `QPoint`, `QPointF`, `QSize`, `QSizeF`, `QRect`, `QRectF`, `QLine`, `QLineF`
- Graphics types: `QColor`, `QFont`, `QIcon`, `QPixmap`, `QBitmap`, `QImage`
- Advanced types: `QVector2D`, `QVector3D`, `QVector4D`, `QMatrix4x4`, `QPolygon`, `QPolygonF`
- Date/Time types: `QDate`, `QTime`, `QDateTime`
- UI types: `QKeySequence`, `QCursor`, `QChar`
- Object types: `QObject*` and custom enums

- **Property Attributes**: Rich attribute system for enhanced property configuration:
- `DescriptionAttribute`: Add helpful descriptions to properties
- `DefaultValueAttribute`: Define default values for properties
- `CategoryAttribute`: Organize properties into collapsible categories
- `ReadOnlyAttribute`: Mark properties as read-only

- **Flexible API**: Multiple ways to add properties:
- Simple property addition with automatic type detection
- Detailed property configuration with attributes
- Batch property addition with categories

- **Interactive Features**:
- Collapsible categories for better organization
- Real-time property value change notifications
- Support for custom property editors
- Responsive tree-based layout

- **Cross-Platform**: Compatible with Qt 5.9+ on Windows, macOS, and Linux

- **Wide Qt Compatibility**: Designed to work with all Qt versions from Qt 5.9 onward, ensuring maximum compatibility across projects

## Requirements

- **CMake**: 3.10 or higher
- **Qt**: 5.9+ (Widgets module required)
- **C++ Standard**: C++17 (can work on C++14 if you have a replacement implementation for `std::variant`)
- **Compiler**: MSVC 2019, GCC, or Clang with C++17 support

## Quick Start

```cpp
Expand All @@ -71,14 +32,6 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);

PM::PropertyGrid propertyGrid;
//
// ONLY FOR NOW...
//
// Add editors for the property types that you're using
// This won't be required in the future
//
propertyGrid.addPropertyEditor<PM::BoolPropertyEditor>();
propertyGrid.addPropertyEditor<PM::ColorPropertyEditor>();

// Add simple properties
propertyGrid.addProperty("Name", QString("My Object"));
Expand Down Expand Up @@ -107,6 +60,45 @@ int main(int argc, char *argv[])
}
```

## Features

- **Comprehensive Type Support**: Planned Built-in support for all major Qt types including:
- [x] **Basic types**: `int`, `bool`, `QString`, `double`
- [ ] **Geometric types**: `QPoint`, `QPointF`, `QSize`, `QSizeF`, `QRect`, `QRectF`, `QLine`, `QLineF`
- [x] **Graphics types**: `QColor`, `QFont`, `QIcon`, `QPixmap`, `QBitmap`, `QImage`
- [ ] **Advanced types**: `QVector2D`, `QVector3D`, `QVector4D`, `QMatrix4x4`, `QPolygon`, `QPolygonF`
- [x] **Date/Time types**: `QDate`, `QTime`, `QDateTime`
- [ ] **UI types** (partial): `QKeySequence`, `QCursor`, `QChar`
- [ ] **Object types**: `QObject*` and custom enums

- **Property Attributes**: Rich attribute system for enhanced property configuration:
- `DescriptionAttribute`: Add helpful descriptions to properties
- `DefaultValueAttribute`: Define default values for properties
- `CategoryAttribute`: Organize properties into collapsible categories
- `ReadOnlyAttribute`: Mark properties as read-only

- **Flexible API**: Multiple ways to add properties:
- Simple property addition with automatic type detection
- Detailed property configuration with attributes
- Batch property addition with categories

- **Interactive Features**:
- Collapsible categories for better organization
- Real-time property value change notifications
- Support for custom property editors
- Responsive tree-based layout

- **Cross-Platform**: Compatible with Qt 5.9+ on Windows, macOS, and Linux

- **Wide Qt Compatibility**: Designed to work with all Qt versions from Qt 5.9 onward, ensuring maximum compatibility across projects

## Requirements

- **CMake**: 3.10 or higher
- **Qt**: 5.9+ (Widgets module required)
- **C++ Standard**: C++17 (can work on C++14 if you have a replacement implementation for `std::variant`)
- **Compiler**: MSVC 2019, GCC, or Clang with C++17 support

## API Overview

### Core Classes
Expand Down Expand Up @@ -148,7 +140,8 @@ cmake --build .
You can easily integrate PmPropertyGrid into your CMake project using `add_subdirectory`:

```cmake
# Add PmPropertyGrid as a subdirectory
# Add PmPropertyGrid as a subdirectory and disable examples
set(PM_BUILD_PROPERTY_GRID_EXAMPLES OFF)
add_subdirectory(path/to/PmPropertyGrid)

# Link against your target
Expand All @@ -168,6 +161,7 @@ find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED)

# Add PmPropertyGrid
set(PM_BUILD_PROPERTY_GRID_EXAMPLES OFF)
add_subdirectory(third_party/PmPropertyGrid)

# Create your executable
Expand Down Expand Up @@ -196,6 +190,7 @@ PmPropertyGrid/
├── src/ # Core library source code
│ ├── PropertyGrid.h/cpp # Main property grid widget
│ ├── Property.h/cpp # Property definition and attributes
│ ├── PropertyContext.h/cpp # Property definition, value and associated meta info
│ └── PropertyEditor.h/cpp # Property editor framework
├── examples/ # Example applications
│ └── property_grid_showcase/ # Comprehensive demo
Expand Down
3 changes: 1 addition & 2 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
include_directories(${CMAKE_SOURCE_DIR}/src)

add_subdirectory(property_grid_showcase)
add_subdirectory(object_property_grid)
20 changes: 20 additions & 0 deletions examples/object_property_grid/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)

add_executable(object_property_grid
main.cpp
ObjectPropertyGrid.h ObjectPropertyGrid.cpp

MainWindow.h MainWindow.cpp MainWindow.ui
)

target_link_libraries(object_property_grid
PRIVATE
PM::PropertyGrid
)
target_link_libraries(object_property_grid PRIVATE Qt${QT_VERSION_MAJOR}::Core)
75 changes: 75 additions & 0 deletions examples/object_property_grid/MainWindow.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include "MainWindow.h"
#include "ui_MainWindow.h"

#include <QTreeWidgetItem>
#include <QVBoxLayout>

static void addWidgetToTree(QTreeWidgetItem *parentItem, QWidget *widget)
{
if (!widget)
return;

auto *item = new QTreeWidgetItem(parentItem, {widget->objectName()});
item->setData(0, Qt::UserRole, QVariant::fromValue(static_cast<QObject *>(widget)));

const QList<QWidget *> children = widget->findChildren<QWidget *>(QString(), Qt::FindDirectChildrenOnly);
for (QWidget *child : children)
addWidgetToTree(item, child);
}

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), propertyGrid(this)
{
ui->setupUi(this);

// Place propertyGrid inside the Properties dock
propertyGrid.layout()->setContentsMargins(0, 0, 0, 0);
ui->dockWidget_2->setWidget(&propertyGrid);

// Populate tree with central widget hierarchy
ui->treeWidget->setHeaderLabel("Objects");
ui->treeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);

// Instead of adding the central widget itself, add its direct children
const QList<QWidget *> children = ui->centralwidget->findChildren<QWidget *>(QString(), Qt::FindDirectChildrenOnly);
for (QWidget *child : children)
addWidgetToTree(ui->treeWidget->invisibleRootItem(), child);

// Expand everything by default
ui->treeWidget->expandAll();

// Default selection: first item
if (ui->treeWidget->topLevelItemCount() > 0)
{
ui->treeWidget->setCurrentItem(ui->treeWidget->topLevelItem(0));
QObject *obj = ui->treeWidget->topLevelItem(0)->data(0, Qt::UserRole).value<QObject *>();

if (obj)
propertyGrid.setSelectedObject(obj);
}

// Sync selection with property grid
connect(ui->treeWidget, &QTreeWidget::itemSelectionChanged, this, &MainWindow::objectsTreeSelectionChanged);
}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::objectsTreeSelectionChanged()
{
QList<QObject *> selectedObjects;
for (QTreeWidgetItem *item : ui->treeWidget->selectedItems())
{
QObject *obj = item->data(0, Qt::UserRole).value<QObject *>();
if (obj)
selectedObjects.append(obj);
}

if (selectedObjects.isEmpty())
propertyGrid.setSelectedObjects({});
else if (selectedObjects.size() == 1)
propertyGrid.setSelectedObject(selectedObjects.first());
else
propertyGrid.setSelectedObjects(selectedObjects);
}
30 changes: 30 additions & 0 deletions examples/object_property_grid/MainWindow.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include "ObjectPropertyGrid.h"

#include <QMainWindow>

namespace Ui
{
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();

private slots:
void objectsTreeSelectionChanged();

private:
Ui::MainWindow *ui;

ObjectPropertyGrid propertyGrid;
};

#endif // MAINWINDOW_H
Loading
Loading