Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package qpwgraph for openSUSE:Factory 
checked in at 2023-03-03 22:29:08
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/qpwgraph (Old)
 and      /work/SRC/openSUSE:Factory/.qpwgraph.new.31432 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "qpwgraph"

Fri Mar  3 22:29:08 2023 rev:15 rq:1069309 version:0.4.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/qpwgraph/qpwgraph.changes        2023-01-28 
19:03:37.508815771 +0100
+++ /work/SRC/openSUSE:Factory/.qpwgraph.new.31432/qpwgraph.changes     
2023-03-03 22:32:11.680232726 +0100
@@ -1,0 +2,14 @@
+Fri Mar  3 19:11:39 UTC 2023 - Alexei Sorokin <sor.ale...@meowr.ru>
+
+- Update to version 0.4.1 (changes since 0.3.9):
+  * Node names now have the "media.name" property as a bracketed
+    suffix; when given and applicable.
+  * Node icons now reflecting their proper application/theme icons
+    or else, a bland and generic default taken from the
+    "client.api" property (eg. "pw", "jack" or "pulse").
+  * Introducing touch pinch-gesture for zooming.
+  * Attempt to make port labels as short as possible.
+  * Fix a possible crash when several PW objects (nodes and ports)
+    are created and destroyed in fast succession.
+
+-------------------------------------------------------------------

Old:
----
  qpwgraph-v0.3.9.tar.bz2

New:
----
  qpwgraph-v0.4.1.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ qpwgraph.spec ++++++
--- /var/tmp/diff_new_pack.ycS2Ei/_old  2023-03-03 22:32:12.196234926 +0100
+++ /var/tmp/diff_new_pack.ycS2Ei/_new  2023-03-03 22:32:12.200234944 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           qpwgraph
-Version:        0.3.9
+Version:        0.4.1
 Release:        0
 Summary:        PipeWire Graph Qt GUI Interface
 License:        GPL-2.0-or-later

++++++ qpwgraph-v0.3.9.tar.bz2 -> qpwgraph-v0.4.1.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/.gitlab-ci.yml 
new/qpwgraph-v0.4.1/.gitlab-ci.yml
--- old/qpwgraph-v0.3.9/.gitlab-ci.yml  2022-12-27 09:31:59.000000000 +0100
+++ new/qpwgraph-v0.4.1/.gitlab-ci.yml  2023-03-03 17:54:04.000000000 +0100
@@ -2,7 +2,7 @@
 #
 workflow:
   rules:
-    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
+    - if: $CI_COMMIT_REF_NAME != $CI_DEFAULT_BRANCH
     - when: never
 
 stages:
@@ -37,7 +37,7 @@
 .fedora:
   variables:
     # Update this tag when you want to trigger a rebuild
-    FDO_DISTRIBUTION_TAG: '2022-12-19.0'
+    FDO_DISTRIBUTION_TAG: '2023-02-27.0'
     FDO_DISTRIBUTION_VERSION: '37'
     FDO_DISTRIBUTION_PACKAGES: >-
       gcc
@@ -54,7 +54,7 @@
 .ubuntu:
   variables:
     # Update this tag when you want to trigger a rebuild
-    FDO_DISTRIBUTION_TAG: '2022-12-19.0'
+    FDO_DISTRIBUTION_TAG: '2023-02-27.0'
     FDO_DISTRIBUTION_VERSION: '22.10'
     FDO_DISTRIBUTION_PACKAGES: >-
       debhelper-compat
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/CMakeLists.txt 
new/qpwgraph-v0.4.1/CMakeLists.txt
--- old/qpwgraph-v0.3.9/CMakeLists.txt  2022-12-27 09:31:59.000000000 +0100
+++ new/qpwgraph-v0.4.1/CMakeLists.txt  2023-03-03 17:54:04.000000000 +0100
@@ -1,7 +1,7 @@
 cmake_minimum_required (VERSION 3.15)
 
 project(qpwgraph
-  VERSION 0.3.9
+  VERSION 0.4.1
   DESCRIPTION "A PipeWire Graph Qt GUI Interface"
   HOMEPAGE_URL "https://gitlab.freedesktop.org/rncbc/qpwgraph";
   LANGUAGES C CXX)
@@ -51,6 +51,7 @@
 else ()
   set (CONFIG_DEBUG 0)
   set (CONFIG_BUILD_TYPE "release")
+  set (CMAKE_BUILD_TYPE "Release")
 endif ()
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/ChangeLog 
new/qpwgraph-v0.4.1/ChangeLog
--- old/qpwgraph-v0.3.9/ChangeLog       2022-12-27 09:31:59.000000000 +0100
+++ new/qpwgraph-v0.4.1/ChangeLog       2023-03-03 17:54:04.000000000 +0100
@@ -2,6 +2,24 @@
 --------------------------------------------
 
 
+0.4.1  2023-03-03  A late-winter'23 release.
+
+- Attempt to make port labels as short as possible. (EXPERIMENTAL)
+- Fixed a possible crash when several PW objects (nodes and ports)
+  are created and destroyed in fast succession. (EXPERIMENTAL)
+
+
+0.4.0  2023-02-25  A mid-winter'23 release.
+
+- Node names now have the "media.name" property as a bracketed
+  suffix; when given and applicable. (EXPERIMENTAL) 
+- Node icons now reflecting their proper application/theme icons
+  or else, a bland and generic default taken from the "client.api"
+  property (eg. "pw", "jack" or "pulse"). (EXPERIMENTAL)
+- Introducing touch pinch-gesture for zooming. (EXPERIMENTAL)
+- Bumping copyright headers to the brand new year.
+
+
 0.3.9  2022-12-27  An end-of-year'22 release
 
 - Whether to draw connectors through or around nodes is now an
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/README.md 
new/qpwgraph-v0.4.1/README.md
--- old/qpwgraph-v0.3.9/README.md       2022-12-27 09:31:59.000000000 +0100
+++ new/qpwgraph-v0.4.1/README.md       2023-03-03 17:54:04.000000000 +0100
@@ -53,4 +53,4 @@
 
 ## Copyright
 
-  Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+  Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/debian/changelog 
new/qpwgraph-v0.4.1/debian/changelog
--- old/qpwgraph-v0.3.9/debian/changelog        2022-12-27 09:31:59.000000000 
+0100
+++ new/qpwgraph-v0.4.1/debian/changelog        2023-03-03 17:54:04.000000000 
+0100
@@ -1,3 +1,15 @@
+qpwgraph (0.4.1-23.1) unstable; urgency=low
+
+  * A late-winter'23 release.
+
+ -- Rui Nuno Capela <rn...@rncbc.org>  Fri,  3 Mar 2023 18:00:00 +0000
+
+qpwgraph (0.4.0-22.1) unstable; urgency=low
+
+  * A mid-winter'23 release.
+
+ -- Rui Nuno Capela <rn...@rncbc.org>  Sat, 25 Feb 2023 12:00:00 +0000
+
 qpwgraph (0.3.9-21.1) unstable; urgency=low
 
   * An end-of-year'22 release.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/debian/copyright 
new/qpwgraph-v0.4.1/debian/copyright
--- old/qpwgraph-v0.3.9/debian/copyright        2022-12-27 09:31:59.000000000 
+0100
+++ new/qpwgraph-v0.4.1/debian/copyright        2023-03-03 17:54:04.000000000 
+0100
@@ -7,7 +7,7 @@
 
 Copyright:
 
-   Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+   Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
 
 License:
 
@@ -28,6 +28,6 @@
 On Debian systems, the complete text of the GNU General
 Public License can be found in `/usr/share/common-licenses/GPL'.
 
-The Debian packaging is (C) 2021-2022, Rui Nuno Capela <rn...@rncbc.org> and
+The Debian packaging is (C) 2021-2023, Rui Nuno Capela <rn...@rncbc.org> and
 is licensed under the GPL, see above.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/rpm/qpwgraph.spec 
new/qpwgraph-v0.4.1/rpm/qpwgraph.spec
--- old/qpwgraph-v0.3.9/rpm/qpwgraph.spec       2022-12-27 09:31:59.000000000 
+0100
+++ new/qpwgraph-v0.4.1/rpm/qpwgraph.spec       2023-03-03 17:54:04.000000000 
+0100
@@ -1,7 +1,7 @@
 #
 # spec file for package qpwgraph
 #
-# Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+# Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -16,8 +16,8 @@
 #
 
 %define name   qpwgraph
-%define version        0.3.9
-%define release        21.1
+%define version        0.4.1
+%define release        23.1
 
 %define _prefix        /usr
 
@@ -25,7 +25,7 @@
 %define debug_package %{nil}
 %endif
 
-%if 0%{?fedora_version} >= 34 || 0%{?suse_version} > 1500
+%if 0%{?fedora_version} >= 34 || 0%{?suse_version} > 1500 || ( 
0%{?sle_version} == 150200 && 0%{?is_opensuse} )
 %define qt_major_version  6
 %else
 %define qt_major_version  5
@@ -47,14 +47,18 @@
 BuildRequires: pkgconfig
 BuildRequires: glibc-devel
 BuildRequires: gcc-c++
-%if %{defined fedora} || 0%{?suse_version} > 1500
-BuildRequires: gcc-c++ >= 8
-%define CXX            /usr/bin/g++
+BuildRequires: cmake >= 3.15
+%if 0%{?sle_version} >= 150200 && 0%{?is_opensuse}
+BuildRequires: gcc10 >= 10
+BuildRequires: gcc10-c++ >= 10
+%define _GCC   /usr/bin/gcc-10
+%define _GXX   /usr/bin/g++-10
 %else
-BuildRequires: gcc8-c++ >= 8
-%define CXX            /usr/bin/g++-8
+BuildRequires: gcc >= 10
+BuildRequires: gcc-c++ >= 10
+%define _GCC   /usr/bin/gcc
+%define _GXX   /usr/bin/g++
 %endif
-BuildRequires: cmake >= 3.15
 %if 0%{qt_major_version} == 6
 %if 0%{?sle_version} == 150200 && 0%{?is_opensuse}
 BuildRequires: qtbase6-static >= 6.1
@@ -99,7 +103,7 @@
 %setup -q
 
 %build
-CXX=%{CXX} \
+CXX=%{_GXX} CC=%{_GCC} \
 cmake -DCMAKE_INSTALL_PREFIX=%{_prefix} -DCONFIG_ALSA_MIDI=ON -Wno-dev -B build
 cmake --build build %{?_smp_mflags}
 
@@ -112,7 +116,8 @@
 
 %files
 %defattr(-,root,root)
-%doc README.md LICENSE.md ChangeLog
+%license LICENSE.md
+%doc README.md  ChangeLog
 %dir %{_datadir}/applications
 %dir %{_datadir}/icons/hicolor
 %dir %{_datadir}/icons/hicolor/32x32
@@ -136,6 +141,10 @@
 
 
 %changelog
+* Fri Mar  3 2023 Rui Nuno Capela <rn...@rncbc.org> 0.4.1
+- A late-winter'23 release.
+* Sat Feb 25 2023 Rui Nuno Capela <rn...@rncbc.org> 0.4.0
+- A mid-winter'23 release.
 * Tue Dec 27 2022 Rui Nuno Capela <rn...@rncbc.org> 0.3.9
 - An end-of-year'22 release.
 * Sat Nov 19 2022 Rui Nuno Capela <rn...@rncbc.org> 0.3.8
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/qpwgraph-v0.3.9/src/appdata/org.rncbc.qpwgraph.metainfo.xml 
new/qpwgraph-v0.4.1/src/appdata/org.rncbc.qpwgraph.metainfo.xml
--- old/qpwgraph-v0.3.9/src/appdata/org.rncbc.qpwgraph.metainfo.xml     
2022-12-27 09:31:59.000000000 +0100
+++ new/qpwgraph-v0.4.1/src/appdata/org.rncbc.qpwgraph.metainfo.xml     
2023-03-03 17:54:04.000000000 +0100
@@ -37,7 +37,7 @@
  <developer_name>rncbc aka. Rui Nuno Capela</developer_name>
  <update_contact>rn...@rncbc.org</update_contact>
  <releases>
-  <release version="0.3.9" date="2022-12-27" urgency="low" />
+  <release version="0.4.1" date="2023-03-03" urgency="low" />
  </releases>
  <content_rating type="oars-1.0"/>
 </component>
Binary files old/qpwgraph-v0.3.9/src/images/itemJack.png and 
new/qpwgraph-v0.4.1/src/images/itemJack.png differ
Binary files old/qpwgraph-v0.3.9/src/images/itemPulse.png and 
new/qpwgraph-v0.4.1/src/images/itemPulse.png differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/src/qpwgraph.qrc 
new/qpwgraph-v0.4.1/src/qpwgraph.qrc
--- old/qpwgraph-v0.3.9/src/qpwgraph.qrc        2022-12-27 09:31:59.000000000 
+0100
+++ new/qpwgraph-v0.4.1/src/qpwgraph.qrc        2023-03-03 17:54:04.000000000 
+0100
@@ -12,6 +12,8 @@
                <file>images/itemEdit.png</file>
                <file>images/itemPin.png</file>
                <file>images/itemUnpin.png</file>
+               <file>images/itemJack.png</file>
+               <file>images/itemPulse.png</file>
                <file>images/fileNew.png</file>
                <file>images/fileOpen.png</file>
                <file>images/fileSave.png</file>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/src/qpwgraph_canvas.cpp 
new/qpwgraph-v0.4.1/src/qpwgraph_canvas.cpp
--- old/qpwgraph-v0.3.9/src/qpwgraph_canvas.cpp 2022-12-27 09:31:59.000000000 
+0100
+++ new/qpwgraph-v0.4.1/src/qpwgraph_canvas.cpp 2023-03-03 17:54:04.000000000 
+0100
@@ -1,7 +1,7 @@
 // qpwgraph_canvas.cpp
 //
 /****************************************************************************
-   Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+   Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -40,6 +40,9 @@
 #include <QWheelEvent>
 #include <QKeyEvent>
 
+#include <QGestureEvent>
+#include <QPinchGesture>
+
 #include <algorithm>
 
 #include <cmath>
@@ -65,7 +68,7 @@
 qpwgraph_canvas::qpwgraph_canvas ( QWidget *parent )
        : QGraphicsView(parent), m_state(DragNone), m_item(nullptr),
                m_connect(nullptr), m_rubberband(nullptr),
-               m_zoom(1.0), m_zoomrange(false),
+               m_zoom(1.0), m_zoomrange(false), m_gesture(false),
                m_commands(nullptr), m_settings(nullptr), m_patchbay(nullptr),
                m_patchbay_edit(false), m_patchbay_autopin(true),
                m_selected_nodes(0), m_repel_overlapping_nodes(false),
@@ -96,6 +99,8 @@
                SIGNAL(editingFinished()),
                SLOT(editingFinished()));
 
+       QGraphicsView::grabGesture(Qt::PinchGesture);
+
        m_editor->setEnabled(false);
        m_editor->hide();
 
@@ -589,6 +594,9 @@
 // Mouse event handlers.
 void qpwgraph_canvas::mousePressEvent ( QMouseEvent *event )
 {
+       if (m_gesture)
+               return;
+
        m_state = DragNone;
        m_item = nullptr;
        m_pos = QGraphicsView::mapToScene(event->pos());
@@ -614,6 +622,9 @@
 
 void qpwgraph_canvas::mouseMoveEvent ( QMouseEvent *event )
 {
+       if (m_gesture)
+               return;
+
        int nchanged = 0;
 
        QPointF pos = QGraphicsView::mapToScene(event->pos());
@@ -781,6 +792,9 @@
 
 void qpwgraph_canvas::mouseReleaseEvent ( QMouseEvent *event )
 {
+       if (m_gesture)
+               return;
+
        int nchanged = 0;
 
        switch (m_state) {
@@ -1692,4 +1706,48 @@
 }
 
 
+// Gesture event handlers.
+//
+bool qpwgraph_canvas::event ( QEvent *event )
+{
+       if (event->type() == QEvent::Gesture)
+               return gestureEvent(static_cast<QGestureEvent *> (event));
+       else
+               return QGraphicsView::event(event);
+}
+
+
+bool qpwgraph_canvas::gestureEvent ( QGestureEvent *event )
+{
+       if (QGesture *pinch = event->gesture(Qt::PinchGesture))
+               pinchGesture(static_cast<QPinchGesture *> (pinch));
+
+       return true;
+}
+
+
+void qpwgraph_canvas::pinchGesture ( QPinchGesture *pinch )
+{
+       switch (pinch->state()) {
+       case Qt::GestureStarted: {
+               const qreal scale_factor = zoom();
+               pinch->setScaleFactor(scale_factor);
+               pinch->setLastScaleFactor(scale_factor);
+               pinch->setTotalScaleFactor(scale_factor);
+               m_gesture = true;
+               break;
+       }
+       case Qt::GestureFinished:
+               m_gesture = false;
+               // Fall thru...
+       case Qt::GestureUpdated:
+               if (pinch->changeFlags() & QPinchGesture::ScaleFactorChanged)
+                       setZoom(pinch->totalScaleFactor());
+               // Fall thru...
+       default:
+               break;
+       }
+}
+
+
 // end of qpwgraph_canvas.cpp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/src/qpwgraph_canvas.h 
new/qpwgraph-v0.4.1/src/qpwgraph_canvas.h
--- old/qpwgraph-v0.3.9/src/qpwgraph_canvas.h   2022-12-27 09:31:59.000000000 
+0100
+++ new/qpwgraph-v0.4.1/src/qpwgraph_canvas.h   2023-03-03 17:54:04.000000000 
+0100
@@ -1,7 +1,7 @@
 // qpwgraph_canvas.h
 //
 /****************************************************************************
-   Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+   Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -43,6 +43,9 @@
 class QWheelEvent;
 class QKeyEvent;
 
+class QGestureEvent;
+class QPinchGesture;
+
 class qpwgraph_patchbay;
 
 
@@ -227,6 +230,11 @@
        // Keyboard event handler.
        void keyPressEvent(QKeyEvent *event);
 
+       // Gesture event handlers.
+       bool event(QEvent *event);
+       bool gestureEvent(QGestureEvent *event);
+       void pinchGesture(QPinchGesture *pinch);
+
        // Graph node/port key helpers.
        QString nodeKey(qpwgraph_node *node, int n = 0) const;
        QString portKey(qpwgraph_port *port, int n = 0) const;
@@ -258,6 +266,7 @@
        QRubberBand      *m_rubberband;
        qreal             m_zoom;
        bool              m_zoomrange;
+       bool              m_gesture;
 
        qpwgraph_node::IdKeys   m_node_ids;
        qpwgraph_node::NodeKeys m_node_keys;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/src/qpwgraph_config.cpp 
new/qpwgraph-v0.4.1/src/qpwgraph_config.cpp
--- old/qpwgraph-v0.3.9/src/qpwgraph_config.cpp 2022-12-27 09:31:59.000000000 
+0100
+++ new/qpwgraph-v0.4.1/src/qpwgraph_config.cpp 2023-03-03 17:54:04.000000000 
+0100
@@ -1,7 +1,7 @@
 // qpwgraph_config.cpp
 //
 /****************************************************************************
-   Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+   Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -323,7 +323,7 @@
 #endif
 
        m_settings->beginGroup(PatchbayGroup);
-       m_patchbay_toolbar = m_settings->value(PatchbayToolbarKey).toBool();
+       m_patchbay_toolbar = m_settings->value(PatchbayToolbarKey, 
true).toBool();
        m_patchbay_dir = m_settings->value(PatchbayDirKey).toString();
        m_patchbay_path = m_settings->value(PatchbayPathKey).toString();
        m_patchbay_activated = m_settings->value(PatchbayActivatedKey, 
false).toBool();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/src/qpwgraph_config.h 
new/qpwgraph-v0.4.1/src/qpwgraph_config.h
--- old/qpwgraph-v0.3.9/src/qpwgraph_config.h   2022-12-27 09:31:59.000000000 
+0100
+++ new/qpwgraph-v0.4.1/src/qpwgraph_config.h   2023-03-03 17:54:04.000000000 
+0100
@@ -1,7 +1,7 @@
 // qpwgraph_config.h
 //
 /****************************************************************************
-   Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+   Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/src/qpwgraph_connect.cpp 
new/qpwgraph-v0.4.1/src/qpwgraph_connect.cpp
--- old/qpwgraph-v0.3.9/src/qpwgraph_connect.cpp        2022-12-27 
09:31:59.000000000 +0100
+++ new/qpwgraph-v0.4.1/src/qpwgraph_connect.cpp        2023-03-03 
17:54:04.000000000 +0100
@@ -1,7 +1,7 @@
 // qpwgraph_connect.cpp
 //
 /****************************************************************************
-   Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+   Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -213,7 +213,7 @@
                color = qpwgraph_item::foreground().lighter();
        else
                color = qpwgraph_item::foreground();
-       color.setAlpha(m_dimmed ? 160 : 255);
+       color.setAlpha(m_dimmed ? 128 : 255);
 
        const QPalette pal;
        const bool is_darkest = (pal.base().color().value() < 24);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/src/qpwgraph_connect.h 
new/qpwgraph-v0.4.1/src/qpwgraph_connect.h
--- old/qpwgraph-v0.3.9/src/qpwgraph_connect.h  2022-12-27 09:31:59.000000000 
+0100
+++ new/qpwgraph-v0.4.1/src/qpwgraph_connect.h  2023-03-03 17:54:04.000000000 
+0100
@@ -1,7 +1,7 @@
 // qpwgraph_connect.h
 //
 /****************************************************************************
-   Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+   Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/src/qpwgraph_form.cpp 
new/qpwgraph-v0.4.1/src/qpwgraph_form.cpp
--- old/qpwgraph-v0.3.9/src/qpwgraph_form.cpp   2022-12-27 09:31:59.000000000 
+0100
+++ new/qpwgraph-v0.4.1/src/qpwgraph_form.cpp   2023-03-03 17:54:04.000000000 
+0100
@@ -1,7 +1,7 @@
 // qpwgraph_form.cpp
 //
 /****************************************************************************
-   Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+   Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -847,12 +847,28 @@
        static const QString subtitle = PROJECT_DESCRIPTION;
        static const QString website = PROJECT_HOMEPAGE_URL;
        static const QString copyright
-               = "Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All 
rights reserved.";
+               = "Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All 
rights reserved.";
 
-       QString text = "<p>\n";
-       text += "<b>" + title + " - " + subtitle + "</b><br />\n";
+       QStringList list;
+#ifdef CONFIG_DEBUG
+       list << tr("Debugging option enabled.");
+#endif
+#ifndef CONFIG_ALSA_MIDI
+       list << tr("ALSA MIDI support disabled.");
+#endif
+#ifndef CONFIG_SYSTEM_TRAY
+       list << tr("System-tray icon support disabled.");
+#endif
+
+       QString text = "<h1>" + title + "</h1>\n";
+       text += "<p>" + subtitle + "<br />\n";
        text += "<br />\n";
        text += tr("Version") + ": <b>" + version + "</b><br />\n";
+       if (!list.isEmpty()) {
+               text += "<small><font color=\"red\">";
+               text += list.join("<br />\n");
+               text += "</font></small>\n";
+       }
        text += "<br />\n";
        text += tr("Using: Qt %1").arg(qVersion());
 #if defined(QT_STATIC)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/src/qpwgraph_form.h 
new/qpwgraph-v0.4.1/src/qpwgraph_form.h
--- old/qpwgraph-v0.3.9/src/qpwgraph_form.h     2022-12-27 09:31:59.000000000 
+0100
+++ new/qpwgraph-v0.4.1/src/qpwgraph_form.h     2023-03-03 17:54:04.000000000 
+0100
@@ -1,7 +1,7 @@
 // qpwgraph_form.h
 //
 /****************************************************************************
-   Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+   Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/src/qpwgraph_form.ui 
new/qpwgraph-v0.4.1/src/qpwgraph_form.ui
--- old/qpwgraph-v0.3.9/src/qpwgraph_form.ui    2022-12-27 09:31:59.000000000 
+0100
+++ new/qpwgraph-v0.4.1/src/qpwgraph_form.ui    2023-03-03 17:54:04.000000000 
+0100
@@ -3,7 +3,7 @@
  <author>rncbc aka Rui Nuno Capela</author>
  <comment>qpwgraph - A PipeWire Graph Qt GUI Interface
 
-   Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+   Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/src/qpwgraph_patchbay.cpp 
new/qpwgraph-v0.4.1/src/qpwgraph_patchbay.cpp
--- old/qpwgraph-v0.3.9/src/qpwgraph_patchbay.cpp       2022-12-27 
09:31:59.000000000 +0100
+++ new/qpwgraph-v0.4.1/src/qpwgraph_patchbay.cpp       2023-03-03 
17:54:04.000000000 +0100
@@ -1,7 +1,7 @@
 // qpwgraph_patchbay.cpp
 //
 /****************************************************************************
-   Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+   Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -82,14 +82,13 @@
                                        qpwgraph_node *node1 = 
port1->portNode();
                                        qpwgraph_node *node2 = 
port2->portNode();
                                        if (node1 && node2) {
-                                               Item *item2 = new Item(
+                                               addItem(new Item(
                                                        node1->nodeType(),
                                                        port1->portType(),
                                                        node1->nodeName(),
                                                        port1->portName(),
                                                        node2->nodeName(),
-                                                       port2->portName());
-                                               m_items.insert(*item2, item2);
+                                                       port2->portName()));
                                        }
                                }
                        }
@@ -152,10 +151,9 @@
                                        if (node_type > 0 && port_type > 0
                                                && !node1.isEmpty() && 
!port1.isEmpty()
                                                && !node2.isEmpty() && 
!port2.isEmpty()) {
-                                               Item *item = new Item(
+                                               addItem(new Item(
                                                        node_type, port_type,
-                                                       node1, port1, node2, 
port2);
-                                               m_items.insert(*item, item);
+                                                       node1, port1, node2, 
port2));
                                        }
                                }
                        }
@@ -422,6 +420,17 @@
 }
 
 
+// Add a new patchbay rule item.
+void qpwgraph_patchbay::addItem ( Item *item )
+{
+       Item *item2 = m_items.value(*item, nullptr);
+       if (item2)
+               delete item2;
+
+       m_items.insert(*item, item);
+}
+
+
 // Node and port type to text helpers.
 uint qpwgraph_patchbay::nodeTypeFromText ( const QString& text )
 {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/src/qpwgraph_patchbay.h 
new/qpwgraph-v0.4.1/src/qpwgraph_patchbay.h
--- old/qpwgraph-v0.3.9/src/qpwgraph_patchbay.h 2022-12-27 09:31:59.000000000 
+0100
+++ new/qpwgraph-v0.4.1/src/qpwgraph_patchbay.h 2023-03-03 17:54:04.000000000 
+0100
@@ -1,7 +1,7 @@
 // qpraph1_patchbay.h
 //
 /****************************************************************************
-   Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+   Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -22,6 +22,8 @@
 #ifndef __qpwgraph_patchbay_h
 #define __qpwgraph_patchbay_h
 
+#include "qpwgraph_item.h"
+
 #include <QString>
 #include <QList>
 #include <QHash>
@@ -31,6 +33,7 @@
 class qpwgraph_canvas;
 class qpwgraph_connect;
 class qpwgraph_port;
+class qpwgraph_node;
 
 
 //----------------------------------------------------------------------------
@@ -116,6 +119,9 @@
 
 protected:
 
+       // Add a new patchbay rule item.
+       void addItem(Item *item);
+
        // Node and port type to text helpers.
        static uint nodeTypeFromText(const QString& text);
        static const char *textFromNodeType(uint node_type);
@@ -141,10 +147,8 @@
 {
        return qHash(item.node_type)
                 ^ qHash(item.port_type)
-                ^ qHash(item.node1)
-                ^ qHash(item.port1)
-                ^ qHash(item.node2)
-                ^ qHash(item.port2);
+                ^ qHash(item.node1 + item.port1)
+                ^ qHash(item.node2 + item.port2);
 }
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/src/qpwgraph_pipewire.cpp 
new/qpwgraph-v0.4.1/src/qpwgraph_pipewire.cpp
--- old/qpwgraph-v0.3.9/src/qpwgraph_pipewire.cpp       2022-12-27 
09:31:59.000000000 +0100
+++ new/qpwgraph-v0.4.1/src/qpwgraph_pipewire.cpp       2023-03-03 
17:54:04.000000000 +0100
@@ -1,7 +1,7 @@
 // qpwgraph_pipewire.cpp
 //
 /****************************************************************************
-   Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+   Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -38,18 +38,58 @@
 
 
 //----------------------------------------------------------------------------
+// qpwgraph_pipewire icon cache.
+
+
+static
+QIcon qpwgraph_icon ( const QString& name )
+{
+       static QHash<QString, QIcon> icon_cache;
+
+       QIcon icon = icon_cache.value(name);
+       if (icon.isNull()) {
+               if (name.at(0) == ':')
+                       icon = QIcon(name);
+               else
+                       icon = QIcon::fromTheme(name);
+               if (!icon.isNull())
+                       icon_cache.insert(name, icon);
+       }
+
+       return icon;
+}
+
+
+//----------------------------------------------------------------------------
 // qpwgraph_pipewire::Data -- PipeWire graph data structs.
 
+struct qpwgraph_pipewire::Proxy
+{
+       qpwgraph_pipewire *pw;
+       struct pw_proxy *proxy;
+       void *info;
+       pw_destroy_t destroy;
+       struct spa_hook proxy_listener;
+       struct spa_hook object_listener;
+       int pending_seq;
+       struct spa_list pending_link;
+};
+
 struct qpwgraph_pipewire::Object
 {
        enum Type { Node, Port, Link };
 
-       Object(uint oid, Type otype) : id(oid), type(otype) {}
+       Object(uint oid, Type otype) : id(oid), type(otype), p(nullptr) {}
+
+       virtual ~Object() { destroy_proxy(); }
 
-       virtual ~Object() {}
+       void create_proxy(qpwgraph_pipewire *pw);
+       void destroy_proxy ();
 
        uint id;
        Type type;
+
+       Proxy *p;
 };
 
 struct qpwgraph_pipewire::Node : public qpwgraph_pipewire::Object
@@ -67,6 +107,8 @@
        qpwgraph_item::Mode node_mode;
        Types node_types;
        QList<qpwgraph_pipewire::Port *> node_ports;
+       QIcon node_icon;
+       bool node_ready;
 };
 
 struct qpwgraph_pipewire::Port : public qpwgraph_pipewire::Object
@@ -109,12 +151,236 @@
        struct spa_hook registry_listener;
 
        int pending_seq;
+       struct spa_list pending;
        int last_seq;
        int last_res;
        bool error;
 };
 
 
+// sync-methods...
+static
+void qpwgraph_add_pending ( qpwgraph_pipewire::Proxy *p )
+{
+       qpwgraph_pipewire *pw = p->pw;
+       qpwgraph_pipewire::Data *pd = pw->data();
+       if (p->pending_seq == 0)
+               spa_list_append(&pd->pending, &p->pending_link);
+       p->pending_seq = pw_core_sync(pd->core, 0, p->pending_seq);
+}
+
+static
+void qpwgraph_remove_pending ( qpwgraph_pipewire::Proxy *p )
+{
+       if (p->pending_seq != 0) {
+               spa_list_remove(&p->pending_link);
+               p->pending_seq = 0;
+       }
+}
+// sync-methods.
+
+
+// node-events...
+static
+void qpwgraph_node_event_info ( void *data, const struct pw_node_info *info )
+{
+       qpwgraph_pipewire::Object *object
+               = static_cast<qpwgraph_pipewire::Object *> (data);
+       if (object && object->p) {
+               info = pw_node_info_update((struct pw_node_info 
*)object->p->info, info);
+               object->p->info = (void *)info;
+               // Add media.name to node name, settle node icon, if any...
+               if (object->p->info) {
+                       qpwgraph_pipewire::Node *node
+                               = static_cast<qpwgraph_pipewire::Node *> 
(object);
+                       if (node && !node->node_ready) {
+                               QIcon node_icon;
+                               const char *icon_name
+                                       = spa_dict_lookup(info->props, 
PW_KEY_APP_ICON_NAME);
+                               if (icon_name && ::strlen(icon_name) > 0)
+                                       node_icon = qpwgraph_icon(icon_name);
+                               if (node_icon.isNull())
+                                       node_icon = 
qpwgraph_icon(node->node_name.toLower());
+                               if (node_icon.isNull()) {
+                                       const char *client_api
+                                               = spa_dict_lookup(info->props, 
PW_KEY_CLIENT_API);
+                                       if (client_api && ::strlen(client_api) 
> 0) {
+                                               if (::strcmp(client_api, 
"jack") == 0 ||
+                                                       ::strcmp(client_api, 
"pipewire-jack") == 0)
+                                                       node_icon = 
qpwgraph_icon(":images/itemJack.png");
+                                               else
+                                               if (::strcmp(client_api, 
"pulse") == 0 ||
+                                                       ::strcmp(client_api, 
"pipewire-pulse") == 0)
+                                                       node_icon = 
qpwgraph_icon(":images/itemPulse.png");
+                                       }
+                               }
+                               if (!node_icon.isNull())
+                                       node->node_icon = node_icon;
+                               const char *media_name
+                                       = spa_dict_lookup(info->props, 
PW_KEY_MEDIA_NAME);
+                               if (media_name && ::strlen(media_name) > 0) {
+                                       QString& node_name = node->node_name;
+                                       node_name += ' ';
+                                       node_name += '[';
+                                       node_name += media_name;
+                                       node_name += ']';
+                               }
+                               node->node_ready = true;
+                       }
+               }
+       }
+}
+
+static
+const struct pw_node_events qpwgraph_node_events = {
+       .version = PW_VERSION_NODE_EVENTS,
+       .info = qpwgraph_node_event_info,
+};
+// node-events.
+
+
+// port-events...
+static
+void qpwgraph_port_event_info ( void *data, const struct pw_port_info *info )
+{
+       qpwgraph_pipewire::Object *object
+               = static_cast<qpwgraph_pipewire::Object *> (data);
+       if (object && object->p) {
+               info = pw_port_info_update((struct pw_port_info 
*)object->p->info, info);
+               object->p->info = (void *)info;
+       }
+}
+
+static
+const struct pw_port_events qpwgraph_port_events = {
+       .version = PW_VERSION_PORT_EVENTS,
+       .info = qpwgraph_port_event_info,
+};
+// port-events.
+
+
+// link-events...
+static
+void qpwgraph_link_event_info ( void *data, const struct pw_link_info *info )
+{
+       qpwgraph_pipewire::Object *object
+               = static_cast<qpwgraph_pipewire::Object *> (data);
+       if (object && object->p) {
+               info = pw_link_info_update((struct pw_link_info 
*)object->p->info, info);
+               object->p->info = (void *)info;
+       }
+}
+
+static
+const struct pw_link_events qpwgraph_link_events = {
+       .version = PW_VERSION_LINK_EVENTS,
+       .info = qpwgraph_link_event_info,
+};
+// link-events.
+
+
+// proxy-events...
+static void
+qpwgraph_proxy_removed ( void *data )
+{
+       qpwgraph_pipewire::Object *object
+               = static_cast<qpwgraph_pipewire::Object *> (data);
+       if (object && object->p && object->p->proxy) {
+               struct pw_proxy *proxy = object->p->proxy;
+               object->p->proxy = nullptr;
+               pw_proxy_destroy(proxy);
+       }
+}
+
+static void
+qpwgraph_proxy_destroy ( void *data )
+{
+       qpwgraph_pipewire::Object *object
+               = static_cast<qpwgraph_pipewire::Object *> (data);
+       if (object)
+               object->destroy_proxy();
+}
+
+static
+const struct pw_proxy_events qpwgraph_proxy_events = {
+       .version = PW_VERSION_PROXY_EVENTS,
+       .destroy = qpwgraph_proxy_destroy,
+       .removed = qpwgraph_proxy_removed,
+};
+// proxy-events.
+
+// proxy-methods...
+void qpwgraph_pipewire::Object::create_proxy ( qpwgraph_pipewire *pw )
+{
+       if (p) return;
+
+       const char *proxy_type = nullptr;
+       uint32_t version = 0;
+       pw_destroy_t destroy = nullptr;
+       const void *events = nullptr;
+
+       switch (type) {
+       case Node:
+               proxy_type = PW_TYPE_INTERFACE_Node;
+               version = PW_VERSION_NODE;
+               destroy = (pw_destroy_t) pw_node_info_free;
+               events = &qpwgraph_node_events;
+               break;
+       case Port:
+               proxy_type = PW_TYPE_INTERFACE_Port;
+               version = PW_VERSION_PORT;
+               destroy = (pw_destroy_t) pw_port_info_free;
+               events = &qpwgraph_port_events;
+               break;
+       case Link:
+               proxy_type = PW_TYPE_INTERFACE_Link;
+               version = PW_VERSION_LINK;
+               destroy = (pw_destroy_t) pw_link_info_free;
+               events = &qpwgraph_link_events;
+               break;
+       }
+
+       struct pw_proxy *proxy = (struct pw_proxy *)pw_registry_bind(
+               pw->data()->registry, id, proxy_type, version, sizeof(Proxy));
+       if (proxy)
+               p = (Proxy *)pw_proxy_get_user_data(proxy);
+       if (p) {
+               p->pw = pw;
+               p->proxy = proxy;
+               p->destroy = destroy;
+               p->pending_seq = 0;
+               pw_proxy_add_object_listener(proxy,
+                       &p->object_listener, events, this);
+               pw_proxy_add_listener(proxy,
+                       &p->proxy_listener, &qpwgraph_proxy_events, this);
+       }
+}
+
+void qpwgraph_pipewire::Object::destroy_proxy (void)
+{
+       if (p == nullptr)
+               return;
+
+       spa_hook_remove(&p->object_listener);
+       spa_hook_remove(&p->proxy_listener);
+
+       qpwgraph_remove_pending(p);
+
+       if (p->info && p->destroy) {
+               p->destroy(p->info);
+               p->info = nullptr;
+       }
+
+       if (p->proxy) {
+               pw_proxy_destroy(p->proxy);
+               p->proxy = nullptr;
+       }
+
+       p = nullptr;
+}
+// proxy-methods.
+
+
 // registry-events...
 static
 void qpwgraph_registry_event_global (
@@ -125,14 +391,14 @@
        uint32_t version,
        const struct spa_dict *props )
 {
+       if (props == nullptr)
+               return;
+
        qpwgraph_pipewire *pw = static_cast<qpwgraph_pipewire *> (data);
 #ifdef CONFIG_DEBUG
        qDebug("qpwgraph_registry_event_global[%p]: id:%u type:%s/%u", pw, id, 
type, version);
 #endif
 
-       if (props == nullptr)
-               return;
-
        int nchanged = 0;
 
        if (::strcmp(type, PW_TYPE_INTERFACE_Node) == 0) {
@@ -182,7 +448,6 @@
        }
        else
        if (::strcmp(type, PW_TYPE_INTERFACE_Port) == 0) {
-               // TODO: ?...
                const char *str = spa_dict_lookup(props, PW_KEY_NODE_ID);
                const uint node_id = (str ? uint(::atoi(str)) : 0);
                QString port_name;
@@ -249,7 +514,7 @@
        qDebug("qpwgraph_registry_event_global_remove[%p]: id:%u", pw, id);
 #endif
 
-       pw->removeObject(id);
+       pw->removeObjectEx(id);
        pw->changedNotify();
 }
 
@@ -272,6 +537,12 @@
        qDebug("qpwgraph_core_event_done[%p]: id:%u seq:%d", pd, id, seq);
 #endif
 
+       struct qpwgraph_pipewire::Proxy *p, *q;
+       spa_list_for_each_safe(p, q, &pd->pending, pending_link) {
+               if (p->pending_seq == seq)
+                       qpwgraph_remove_pending(p);
+       }
+
        if (id == PW_ID_CORE) {
                pd->last_seq = seq;
                if (pd->pending_seq == seq)
@@ -290,8 +561,9 @@
 #endif
 
        if (id == PW_ID_CORE) {
-               pd->error = true;
                pd->last_res = res;
+               if (res == -EPIPE)
+                       pd->error = true;
        }
 
        pw_thread_loop_signal(pd->loop, false);
@@ -381,6 +653,7 @@
 
        m_data = new Data;
        spa_zero(*m_data);
+       spa_list_init(&m_data->pending);
 
        m_data->loop = pw_thread_loop_new("qpwgraph_thread_loop", nullptr);
        if (m_data->loop == nullptr) {
@@ -435,21 +708,25 @@
 
 void qpwgraph_pipewire::close (void)
 {
+       if (m_data == nullptr)
+               return;
+
        QMutexLocker locker(&g_mutex);
 
        clearObjects();
 
-       if (m_data == nullptr)
-               return;
-
        if (m_data->loop)
                pw_thread_loop_stop(m_data->loop);
 
-       if (m_data->registry)
+       if (m_data->registry) {
+               spa_hook_remove(&m_data->registry_listener);
                pw_proxy_destroy((struct pw_proxy*)m_data->registry);
+       }
 
-       if (m_data->core)
+       if (m_data->core) {
+               spa_hook_remove(&m_data->core_listener);
                pw_core_disconnect(m_data->core);
+       }
 
        if (m_data->context)
                pw_context_destroy(m_data->context);
@@ -620,6 +897,8 @@
        Node *n = findNode(node_id);
        if (n == nullptr)
                return false;
+       if (!n->node_ready)
+               return false;
 
        Port *p = findPort(port_id);
        if (p == nullptr)
@@ -650,7 +929,7 @@
 
        if (add_new && *node == nullptr) {
                *node = new qpwgraph_node(node_id, n->node_name, node_mode, 
node_type);
-               (*node)->setNodeIcon(QIcon(":/images/itemPipewire.png"));
+               (*node)->setNodeIcon(n->node_icon);
                qpwgraph_sect::addItem(*node);
        }
 
@@ -667,14 +946,13 @@
 // PipeWire graph updaters.
 void qpwgraph_pipewire::updateItems (void)
 {
-       QMutexLocker locker(&g_mutex);
-
        if (m_data == nullptr)
                return;
 
 #ifdef CONFIG_DEBUG
        qDebug("qpwgraph_pipewire::updateItems()");
 #endif
+       QMutexLocker locker(&g_mutex);
 
        // 0. Check for core errors...
        //
@@ -691,6 +969,8 @@
                if (object->type != Object::Node)
                        continue;
                Node *n1 = static_cast<Node *> (object);
+               if (!n1->node_ready)
+                       continue;
                foreach (const Port *p1, n1->node_ports) {
                        const qpwgraph_item::Mode port_mode1
                                = p1->port_mode;
@@ -746,14 +1026,13 @@
 
 void qpwgraph_pipewire::clearItems (void)
 {
-       QMutexLocker locker(&g_mutex);
-
        if (m_data == nullptr)
                return;
 
 #ifdef CONFIG_DEBUG
        qDebug("qpwgraph_pipewire::clearItems()");
 #endif
+       QMutexLocker locker(&g_mutex);
 
        // Clean-up all items...
        //
@@ -811,6 +1090,8 @@
 
 void qpwgraph_pipewire::addObject ( uint id, Object *object )
 {
+       object->create_proxy(this);
+
        m_objectids.insert(id, object);
        m_objects.append(object);
 }
@@ -818,7 +1099,7 @@
 
 void qpwgraph_pipewire::removeObject ( uint id )
 {
-       Object *object = m_objectids.value(id, nullptr);
+       Object *object = findObject(id);
        if (object == nullptr)
                return;
 
@@ -844,6 +1125,30 @@
 }
 
 
+void qpwgraph_pipewire::removeObjectEx ( uint id )
+{
+       const bool locked
+               = g_mutex.tryLock();
+
+       removeObject(id);
+
+       if (locked)
+               g_mutex.unlock();
+}
+
+
+void qpwgraph_pipewire::addObjectEx ( uint id, Object *object )
+{
+       const bool locked
+               = g_mutex.tryLock();
+
+       addObject(id, object);
+
+       if (locked)
+               g_mutex.unlock();
+}
+
+
 // Node methods.
 //
 qpwgraph_pipewire::Node *qpwgraph_pipewire::findNode ( uint node_id ) const
@@ -863,8 +1168,10 @@
        node->node_name = node_name;
        node->node_mode = node_mode;
        node->node_types = Node::Types(node_types);
+       node->node_icon = qpwgraph_icon(":/images/itemPipewire.png");
+       node->node_ready = false;
 
-       addObject(node_id, node);
+       addObjectEx(node_id, node);
 
        return node;
 }
@@ -911,7 +1218,7 @@
 
        node->node_ports.append(port);
 
-       addObject(port_id, port);
+       addObjectEx(port_id, port);
 
        return port;
 }
@@ -963,7 +1270,7 @@
 
        port1->port_links.append(link);
 
-       addObject(link_id, link);
+       addObjectEx(link_id, link);
 
        return link;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/src/qpwgraph_pipewire.h 
new/qpwgraph-v0.4.1/src/qpwgraph_pipewire.h
--- old/qpwgraph-v0.3.9/src/qpwgraph_pipewire.h 2022-12-27 09:31:59.000000000 
+0100
+++ new/qpwgraph-v0.4.1/src/qpwgraph_pipewire.h 2023-03-03 17:54:04.000000000 
+0100
@@ -1,7 +1,7 @@
 // qpwgraph_pipewire.h
 //
 /****************************************************************************
-   Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+   Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -81,6 +81,7 @@
        // PipeWire client data struct access.
        //
        struct Data;
+       struct Proxy;
        struct Object;
        struct Node;
        struct Port;
@@ -94,6 +95,9 @@
        void removeObject(uint id);
        void clearObjects();
 
+       void addObjectEx(uint id, Object *object);
+       void removeObjectEx(uint id);
+
        // Node methods....
        Node *findNode(uint node_id) const;
        Node *createNode(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/src/qpwgraph_port.cpp 
new/qpwgraph-v0.4.1/src/qpwgraph_port.cpp
--- old/qpwgraph-v0.3.9/src/qpwgraph_port.cpp   2022-12-27 09:31:59.000000000 
+0100
+++ new/qpwgraph-v0.4.1/src/qpwgraph_port.cpp   2023-03-03 17:54:04.000000000 
+0100
@@ -1,7 +1,7 @@
 // qpwgraph_port.cpp
 //
 /****************************************************************************
-   Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+   Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -143,7 +143,17 @@
 {
        m_title = (title.isEmpty() ? m_name : title);
 
-       m_text->setPlainText(m_title);
+       static const int MAX_TITLE_LENGTH = 29;
+       static const QString ellipsis(3, '.');
+
+       QString text = m_title;
+       const int nlength = text.indexOf(':');
+       if (nlength >= 0)
+               text.remove(0, nlength + 1);
+       if (text.length() >= MAX_TITLE_LENGTH + ellipsis.length())
+               text = ellipsis + text.right(MAX_TITLE_LENGTH);
+
+       m_text->setPlainText(text);
 
        QPainterPath path;
        const QRectF& rect
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qpwgraph-v0.3.9/src/qpwgraph_port.h 
new/qpwgraph-v0.4.1/src/qpwgraph_port.h
--- old/qpwgraph-v0.3.9/src/qpwgraph_port.h     2022-12-27 09:31:59.000000000 
+0100
+++ new/qpwgraph-v0.4.1/src/qpwgraph_port.h     2023-03-03 17:54:04.000000000 
+0100
@@ -1,7 +1,7 @@
 // qpwgraph_port.h
 //
 /****************************************************************************
-   Copyright (C) 2021-2022, rncbc aka Rui Nuno Capela. All rights reserved.
+   Copyright (C) 2021-2023, rncbc aka Rui Nuno Capela. All rights reserved.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License

Reply via email to