Skip to content

Commit

Permalink
Made custom properties selectable
Browse files Browse the repository at this point in the history
- Top-level properties can be selected by clicking.
- Holding Ctrl or Shift allows selecting multiple.
- Keyboard handling for selection implemented.
- Remove and Rename actions on tool bar now functional.
- Copy/paste shortcuts work.

As part of implementing this, the VariantEditor and VariantEditorView
have been merged into a single PropertiesView class.

ToDo:

- selectedPropertiesChanged may not get emitted when a selected property
  is removed.
- Add Copy/Paste actions to context menu.
  • Loading branch information
bjorn committed Nov 29, 2024
1 parent ca2e8ac commit bcf4b75
Show file tree
Hide file tree
Showing 11 changed files with 956 additions and 509 deletions.
4 changes: 2 additions & 2 deletions src/tiled/projectpropertiesdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ ProjectPropertiesDialog::ProjectPropertiesDialog(Project &project, QWidget *pare
ui->propertiesWidget->customPropertiesGroup()->setName(QString());

// Tweak margins
const auto margin = Utils::dpiScaled(3);
ui->propertiesWidget->propertiesView()->widget()->setContentsMargins(0, margin, 0, margin);
const auto halfSpacing = Utils::dpiScaled(2);
ui->propertiesWidget->propertiesView()->widget()->setContentsMargins(0, halfSpacing, 0, halfSpacing);

ui->propertiesWidget->setDocument(mLocalProjectDocument);
}
Expand Down
105 changes: 51 additions & 54 deletions src/tiled/propertieswidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2160,9 +2160,12 @@ class WangColorProperties : public ObjectProperties

PropertiesWidget::PropertiesWidget(QWidget *parent)
: QWidget{parent}
, mCustomProperties(new CustomProperties(this))
, mPropertyBrowser(new VariantEditorView(this))
, mRootProperty(new GroupProperty())
, mCustomProperties(new CustomProperties(mRootProperty))
, mPropertiesView(new PropertiesView(this))
{
mRootProperty->addProperty(mCustomProperties);

mActionAddProperty = new QAction(this);
mActionAddProperty->setEnabled(false);
mActionAddProperty->setIcon(QIcon(QLatin1String(":/images/16/add.png")));
Expand All @@ -2181,8 +2184,8 @@ PropertiesWidget::PropertiesWidget(QWidget *parent)
mActionRenameProperty->setEnabled(false);
mActionRenameProperty->setIcon(QIcon(QLatin1String(":/images/16/rename.png")));
mActionRenameProperty->setPriority(QAction::LowPriority);
// connect(mActionRenameProperty, &QAction::triggered,
// this, &PropertiesWidget::renameProperty);
connect(mActionRenameProperty, &QAction::triggered,
this, &PropertiesWidget::renameSelectedProperty);

Utils::setThemeIcon(mActionAddProperty, "add");
Utils::setThemeIcon(mActionRemoveProperty, "remove");
Expand All @@ -2200,15 +2203,15 @@ PropertiesWidget::PropertiesWidget(QWidget *parent)
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
layout->addWidget(mPropertyBrowser);
layout->addWidget(mPropertiesView);
layout->addWidget(toolBar);
setLayout(layout);

mPropertyBrowser->setContextMenuPolicy(Qt::CustomContextMenu);
connect(mPropertyBrowser, &QWidget::customContextMenuRequested,
mPropertiesView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(mPropertiesView, &QWidget::customContextMenuRequested,
this, &PropertiesWidget::showContextMenu);
// connect(mPropertyBrowser, &PropertyBrowser::selectedItemsChanged,
// this, &PropertiesWidget::updateActions);
connect(mPropertiesView, &PropertiesView::selectedPropertiesChanged,
this, &PropertiesWidget::updateActions);

connect(mCustomProperties, &VariantMapProperty::renameRequested,
this, &PropertiesWidget::renameProperty);
Expand All @@ -2219,7 +2222,7 @@ PropertiesWidget::PropertiesWidget(QWidget *parent)
PropertiesWidget::~PropertiesWidget()
{
// Disconnect to avoid crashing due to signals emitted during destruction
mPropertyBrowser->disconnect(this);
mPropertiesView->disconnect(this);
}

void PropertiesWidget::setDocument(Document *document)
Expand Down Expand Up @@ -2261,25 +2264,25 @@ GroupProperty *PropertiesWidget::customPropertiesGroup() const

void PropertiesWidget::selectCustomProperty(const QString &name)
{
if (auto property = mCustomProperties->property(name))
mPropertyBrowser->focusProperty(property);
if (auto property = mCustomProperties->property(name)) {
mPropertiesView->focusProperty(property);
mPropertiesView->setSelectedProperties({ property });
}
}

void PropertiesWidget::currentObjectChanged(Object *object)
{
mPropertyBrowser->clear();

// Remember the expanded states
if (mPropertiesObject) {
// Remember the expanded states
const auto &subProperties = mPropertiesObject->subProperties();
for (int i = 0; i < subProperties.size(); ++i) {
if (auto subGroupProperty = qobject_cast<GroupProperty*>(subProperties.at(i)))
mExpandedStates[i] = subGroupProperty->isExpanded();
}
}

delete mPropertiesObject;
mPropertiesObject = nullptr;
mRootProperty->deleteProperty(mPropertiesObject);
mPropertiesObject = nullptr;
}

if (object) {
switch (object->typeId()) {
Expand Down Expand Up @@ -2347,20 +2350,17 @@ void PropertiesWidget::currentObjectChanged(Object *object)
if (auto subGroupProperty = qobject_cast<GroupProperty*>(subProperties.at(i)))
subGroupProperty->setExpanded(mExpandedStates.value(i, true));
}
}

if (object) {
if (mPropertiesObject)
mPropertyBrowser->addProperty(mPropertiesObject);

mPropertyBrowser->addProperty(mCustomProperties);
mRootProperty->insertProperty(0, mPropertiesObject);
}

mPropertiesView->setRootProperty(object ? mRootProperty : nullptr);

bool editingTileset = mDocument && mDocument->type() == Document::TilesetDocumentType;
bool isTileset = object && object->isPartOfTileset();
bool enabled = object && (!isTileset || editingTileset);

mPropertyBrowser->setEnabled(object);
mPropertiesView->setEnabled(object);
mActionAddProperty->setEnabled(enabled);
}

Expand Down Expand Up @@ -2430,27 +2430,24 @@ void CustomProperties::setPropertyValue(const QStringList &path, const QVariant

void PropertiesWidget::updateActions()
{
#if 0
const QList<QtBrowserItem*> items = mPropertyBrowser->selectedItems();
bool allCustomProperties = !items.isEmpty() && mPropertyBrowser->allCustomPropertyItems(items);
const auto properties = mPropertiesView->selectedProperties();
bool editingTileset = mDocument && mDocument->type() == Document::TilesetDocumentType;
bool isTileset = mPropertyBrowser->object() && mPropertyBrowser->object()->isPartOfTileset();
bool canModify = allCustomProperties && (!isTileset || editingTileset);
bool isTileset = mDocument && mDocument->currentObject() && mDocument->currentObject()->isPartOfTileset();
bool canModify = !properties.isEmpty() && (!isTileset || editingTileset);

// Disable remove and rename actions when none of the selected objects
// actually have the selected property (it may be inherited).
if (canModify) {
for (QtBrowserItem *item : items) {
if (!anyObjectHasProperty(mDocument->currentObjects(), item->property()->propertyName())) {
for (auto property : properties) {
if (!anyObjectHasProperty(mDocument->currentObjects(), property->name())) {
canModify = false;
break;
}
}
}

mActionRemoveProperty->setEnabled(canModify);
mActionRenameProperty->setEnabled(canModify && items.size() == 1);
#endif
mActionRenameProperty->setEnabled(canModify && properties.size() == 1);
}

void PropertiesWidget::cutProperties()
Expand All @@ -2461,19 +2458,15 @@ void PropertiesWidget::cutProperties()

bool PropertiesWidget::copyProperties()
{
#if 0
Object *object = mPropertyBrowser->object();
Object *object = mDocument ? mDocument->currentObject() : nullptr;
if (!object)
return false;

Properties properties;

const QList<QtBrowserItem*> items = mPropertyBrowser->selectedItems();
for (QtBrowserItem *item : items) {
if (!mPropertyBrowser->isCustomPropertyItem(item))
return false;

const QString name = item->property()->propertyName();
const auto selectedProperties = mPropertiesView->selectedProperties();
for (auto property : selectedProperties) {
const QString name = property->name();
const QVariant value = object->property(name);
if (!value.isValid())
return false;
Expand All @@ -2482,7 +2475,7 @@ bool PropertiesWidget::copyProperties()
}

ClipboardManager::instance()->setProperties(properties);
#endif

return true;
}

Expand Down Expand Up @@ -2540,7 +2533,7 @@ void PropertiesWidget::showAddValueProperty()
mCustomProperties->addProperty(mAddValueProperty);
}

mPropertyBrowser->focusProperty(mAddValueProperty, VariantEditor::FocusLabel);
mPropertiesView->focusProperty(mAddValueProperty, PropertiesView::FocusLabel);
}

void PropertiesWidget::addProperty(const QString &name, const QVariant &value)
Expand All @@ -2558,24 +2551,20 @@ void PropertiesWidget::addProperty(const QString &name, const QVariant &value)
name, value));
}

if (auto property = mCustomProperties->property(name))
mPropertyBrowser->focusProperty(property);
selectCustomProperty(name);
}

void PropertiesWidget::removeProperties()
{
#if 0
Object *object = mDocument->currentObject();
if (!object)
return;

const QList<QtBrowserItem*> items = mPropertyBrowser->selectedItems();
if (items.isEmpty() || !mPropertyBrowser->allCustomPropertyItems(items))
return;
const auto properties = mPropertiesView->selectedProperties();

QStringList propertyNames;
for (QtBrowserItem *item : items)
propertyNames.append(item->property()->propertyName());
for (auto property : properties)
propertyNames.append(property->name());

QUndoStack *undoStack = mDocument->undoStack();
undoStack->beginMacro(QCoreApplication::translate("Tiled::PropertiesDock",
Expand All @@ -2590,12 +2579,20 @@ void PropertiesWidget::removeProperties()
}

undoStack->endMacro();
#endif
}

void PropertiesWidget::renameSelectedProperty()
{
const auto properties = mPropertiesView->selectedProperties();
if (properties.size() != 1)
return;

renameProperty(properties.first()->name());
}

void PropertiesWidget::renameProperty(const QString &name)
{
QInputDialog *dialog = new QInputDialog(mPropertyBrowser);
QInputDialog *dialog = new QInputDialog(mPropertiesView);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setInputMode(QInputDialog::TextInput);
dialog->setLabelText(QCoreApplication::translate("Tiled::PropertiesDock", "Name:"));
Expand Down
10 changes: 6 additions & 4 deletions src/tiled/propertieswidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ class CustomProperties;
class Document;
class GroupProperty;
class ObjectProperties;
class VariantEditorView;
class PropertiesView;

/**
* The PropertiesWidget combines the PropertyBrowser with some controls that
* The PropertiesWidget combines the PropertiesView with some controls that
* allow adding and removing properties. It also implements cut, copy and paste
* actions and the context menu.
*/
Expand All @@ -56,7 +56,7 @@ class PropertiesWidget : public QWidget
void setDocument(Document *document);

GroupProperty *customPropertiesGroup() const;
VariantEditorView *propertiesView() const { return mPropertyBrowser; }
PropertiesView *propertiesView() const { return mPropertiesView; }

signals:
void bringToFront();
Expand All @@ -78,17 +78,19 @@ public slots:
void showAddValueProperty();
void addProperty(const QString &name, const QVariant &value);
void removeProperties();
void renameSelectedProperty();
void renameProperty(const QString &name);
void showContextMenu(const QPoint &pos);

void retranslateUi();

Document *mDocument = nullptr;
GroupProperty *mRootProperty = nullptr;
ObjectProperties *mPropertiesObject = nullptr;
CustomProperties *mCustomProperties = nullptr;
QPointer<AddValueProperty> mAddValueProperty;
QMap<int, bool> mExpandedStates;
VariantEditorView *mPropertyBrowser;
PropertiesView *mPropertiesView;
QAction *mActionAddProperty;
QAction *mActionRemoveProperty;
QAction *mActionRenameProperty;
Expand Down
Loading

0 comments on commit bcf4b75

Please sign in to comment.