git: 539c96878523 - main - sysutils/libsysstat-qt6: New port: Library used to query system info and statistics ported to qt6

From: Jose Alonso Cardenas Marquez <acm_at_FreeBSD.org>
Date: Thu, 13 Jun 2024 00:24:19 UTC
The branch main has been updated by acm:

URL: https://cgit.FreeBSD.org/ports/commit/?id=539c968785234fe925d0795081280c9689207d0b

commit 539c968785234fe925d0795081280c9689207d0b
Author:     Jose Alonso Cardenas Marquez <acm@FreeBSD.org>
AuthorDate: 2024-06-13 00:08:35 +0000
Commit:     Jose Alonso Cardenas Marquez <acm@FreeBSD.org>
CommitDate: 2024-06-13 00:08:35 +0000

    sysutils/libsysstat-qt6: New port: Library used to query system info and statistics ported to qt6
    
    Qt-based library to query system information like CPU, memory usage and
    network traffic.
    PR:             278905
    Approved by:    jsm
---
 sysutils/Makefile                                  |   2 +
 sysutils/libsysstat-qt6/Makefile                   |  21 ++
 sysutils/libsysstat-qt6/distinfo                   |   3 +
 sysutils/libsysstat-qt6/files/config.h.in          |   3 +
 sysutils/libsysstat-qt6/files/patch-CMakeLists.txt |  32 +++
 sysutils/libsysstat-qt6/files/patch-cpustat.cpp    | 307 +++++++++++++++++++++
 sysutils/libsysstat-qt6/files/patch-cpustat.h      |  32 +++
 sysutils/libsysstat-qt6/files/patch-cpustat__p.h   |  65 +++++
 sysutils/libsysstat-qt6/files/patch-memstat.cpp    | 123 +++++++++
 sysutils/libsysstat-qt6/files/patch-memstat.h      |  26 ++
 sysutils/libsysstat-qt6/files/patch-netstat.cpp    | 122 ++++++++
 sysutils/libsysstat-qt6/pkg-descr                  |   2 +
 sysutils/libsysstat-qt6/pkg-plist                  |  20 ++
 13 files changed, 758 insertions(+)

diff --git a/sysutils/Makefile b/sysutils/Makefile
index 25665d4d2792..2d0debe2cc0e 100644
--- a/sysutils/Makefile
+++ b/sysutils/Makefile
@@ -680,6 +680,7 @@
     SUBDIR += libptytty
     SUBDIR += libsunacl
     SUBDIR += libsysstat
+    SUBDIR += libsysstat-qt6
     SUBDIR += libtpms
     SUBDIR += libtree
     SUBDIR += libudisks
@@ -727,6 +728,7 @@
     SUBDIR += lxqt-config
     SUBDIR += lxqt-policykit
     SUBDIR += lxqt-powermanagement
+    SUBDIR += lxqt-qt6plugin
     SUBDIR += lxqt-qtplugin
     SUBDIR += lxsplit
     SUBDIR += lxtask
diff --git a/sysutils/libsysstat-qt6/Makefile b/sysutils/libsysstat-qt6/Makefile
new file mode 100644
index 000000000000..ccf52c2b58bf
--- /dev/null
+++ b/sysutils/libsysstat-qt6/Makefile
@@ -0,0 +1,21 @@
+PORTNAME=	libsysstat
+PORTVERSION=	1.0.0
+CATEGORIES=	sysutils
+PKGNAMESUFFIX=	-qt6
+
+MAINTAINER=	lxqt@FreeBSD.org
+COMMENT=	Library used to query system info and statistics ported to qt6
+WWW=		https://lxqt-project.org
+
+LICENSE=	LGPL21+
+LICENSE_FILE=	${WRKSRC}/COPYING
+
+USES=		cmake compiler:c++17-lang lxqt:2 pkgconfig tar:xz qt:6
+USE_QT=		base:run tools:build
+USE_LDCONFIG=	yes
+USE_LXQT=	buildtools2
+
+post-extract:
+	@${CP} ${FILESDIR}/config.h.in ${WRKSRC}
+
+.include <bsd.port.mk>
diff --git a/sysutils/libsysstat-qt6/distinfo b/sysutils/libsysstat-qt6/distinfo
new file mode 100644
index 000000000000..52a3d64cabac
--- /dev/null
+++ b/sysutils/libsysstat-qt6/distinfo
@@ -0,0 +1,3 @@
+TIMESTAMP = 1714103030
+SHA256 (lxqt/libsysstat-1.0.0.tar.xz) = f79b5e3e2e79a52b58fab5639f11b7a5f40e4a9995660181712cb4c4cd460435
+SIZE (lxqt/libsysstat-1.0.0.tar.xz) = 17684
diff --git a/sysutils/libsysstat-qt6/files/config.h.in b/sysutils/libsysstat-qt6/files/config.h.in
new file mode 100644
index 000000000000..05211acde503
--- /dev/null
+++ b/sysutils/libsysstat-qt6/files/config.h.in
@@ -0,0 +1,3 @@
+#cmakedefine HAVE_SYSCTL_H
+#cmakedefine HAVE_IF_H
+#cmakedefine HAVE_KVM_H
diff --git a/sysutils/libsysstat-qt6/files/patch-CMakeLists.txt b/sysutils/libsysstat-qt6/files/patch-CMakeLists.txt
new file mode 100644
index 000000000000..985c523ebf7b
--- /dev/null
+++ b/sysutils/libsysstat-qt6/files/patch-CMakeLists.txt
@@ -0,0 +1,32 @@
+--- CMakeLists.txt.orig	2024-04-17 05:57:59.000000000 -0500
++++ CMakeLists.txt	2024-04-25 13:02:12.269260000 -0500
+@@ -28,6 +28,16 @@
+ include(LXQtCreatePortableHeaders)
+ include(LXQtCompilerSettings NO_POLICY_SCOPE)
+ 
++if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
++include(CheckIncludeFiles)
++include(CheckLibraryExists)
++check_include_files("sys/socket.h;net/if.h;net/if_mib.h;net/if_types.h" HAVE_IF_H)
++check_library_exists(kvm kvm_getswapinfo "kvm.h" HAVE_KVM_H)
++check_library_exists(c sysctlbyname "sys/sysctl.h" HAVE_SYSCTL_H)
++configure_file(config.h.in config.h)
++add_definitions("-DHAVE_CONFIG_H=1")
++endif()
++
+ set(CMAKE_AUTOMOC ON)
+ set(CMAKE_INCLUDE_CURRENT_DIR ON)
+ 
+@@ -80,7 +90,11 @@
+         ${SYSSTAT_QM_FILES}
+ )
+ 
+-target_link_libraries(${SYSSTAT_LIBRARY_NAME} Qt6::Core)
++if(HAVE_SYSCTL_H AND HAVE_KVM_H)
++    target_link_libraries(${SYSSTAT_LIBRARY_NAME} c kvm Qt6::Core)
++else()
++    target_link_libraries(${SYSSTAT_LIBRARY_NAME} Qt6::Core)
++endif()
+ 
+ set_target_properties(${SYSSTAT_LIBRARY_NAME} PROPERTIES
+     VERSION ${SYSSTAT_VERSION}
diff --git a/sysutils/libsysstat-qt6/files/patch-cpustat.cpp b/sysutils/libsysstat-qt6/files/patch-cpustat.cpp
new file mode 100644
index 000000000000..8ead007be490
--- /dev/null
+++ b/sysutils/libsysstat-qt6/files/patch-cpustat.cpp
@@ -0,0 +1,307 @@
+--- cpustat.cpp.orig	2021-11-05 10:06:40 UTC
++++ cpustat.cpp
+@@ -22,16 +22,65 @@
+ **  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ **
+ ** END_COMMON_COPYRIGHT_HEADER */
+-
+-
+ #include <unistd.h>
+-
+ #include "cpustat.h"
++#ifdef HAVE_SYSCTL_H
++extern "C"
++{
++    #include <stdlib.h>
++    #include <limits.h>
++    #include <string.h>
++    #include <sys/resource.h> /* CPUSTATES */
++
++    #include <sys/types.h>
++    #include <sys/sysctl.h>
++}
++#endif
+ #include "cpustat_p.h"
+ 
+ 
+ namespace SysStat {
++#ifdef HAVE_SYSCTL_H
++char *GetFirstFragment(char *string, const char *delim)
++{
++    char *token = NULL;
+ 
++    token = strsep(&string, delim);
++    if (token != NULL)
++    {
++        /* We need only the first fragment, so no loop! */
++        return token;
++    }
++    else
++        return NULL;
++}
++
++int GetCpu(void)
++{
++    static int mib[] = { CTL_HW, HW_NCPU };
++    int buf;
++    size_t len = sizeof(int);
++
++    if (sysctl(mib, 2, &buf, &len, NULL, 0) < 0)
++        return 0;
++    else
++        return buf;
++}
++
++/* Frequence is in MHz */
++ulong CpuStatPrivate::CurrentFreq(QString mSource)
++{
++    ulong freq=0;
++    size_t len = sizeof(freq);
++    int i = mSource.mid(3).toInt();
++    if (sysctl(mib2[i],4,&freq, &len, NULL, 0) < 0) {
++        perror("sysctl");
++        return 0;
++    }
++    else
++        return freq;
++}
++#endif
+ CpuStatPrivate::CpuStatPrivate(CpuStat *parent)
+     : BaseStatPrivate(parent)
+     , mMonitoring(CpuStat::LoadAndFrequency)
+@@ -39,7 +88,17 @@ CpuStatPrivate::CpuStatPrivate(CpuStat *parent)
+     mSource = defaultSource();
+ 
+     connect(mTimer, SIGNAL(timeout()), SLOT(timeout()));
+-
++#ifdef HAVE_SYSCTL_H
++    size_t flen=2;
++    size_t alen=4;
++    sysctlnametomib("kern.cp_times",mib0,&flen);
++    sysctlnametomib("kern.cp_time",mib1,&flen);
++    int ncpu = GetCpu();
++    for (int i=0;i<ncpu;i++) {
++    QString cpu_sysctl_name = QString::fromLatin1("dev.cpu.%1.freq").arg(i);
++    sysctlnametomib(cpu_sysctl_name.toStdString().c_str(),mib2[i],&alen);
++    }
++#endif
+     mUserHz = sysconf(_SC_CLK_TCK);
+ 
+     updateSources();
+@@ -47,6 +106,51 @@ CpuStatPrivate::CpuStatPrivate(CpuStat *parent)
+ 
+ void CpuStatPrivate::addSource(const QString &source)
+ {
++#ifdef HAVE_SYSCTL_H
++            char buf[1024];
++            char *tokens, *t;
++            ulong min = 0, max = 0;
++            size_t len = sizeof(buf);
++
++            /* The string returned by the dev.cpu.0.freq_levels sysctl
++             * is a space separated list of MHz/milliwatts.
++             */
++            if (source != QStringLiteral("cpu") && source.mid(0,3).toInt() >-1) {
++
++                if (sysctlbyname(QString::fromLatin1("dev.cpu.%1.freq_levels").arg(source.mid(0,3).toInt()).toStdString().c_str(), buf, &len, NULL, 0) < 0)
++                    return;
++            }
++            t = strndup(buf, len);
++            if (t == NULL)
++            {
++                free(t);
++                return;
++            }
++            while ((tokens = strsep(&t, " ")) != NULL)
++            {
++                char *freq;
++                ulong res;
++
++                freq = GetFirstFragment(tokens, "/");
++                if (freq != NULL)
++                {
++                    res = strtoul(freq, &freq, 10);
++                    if (res > max)
++                    {
++                        max = res;
++                    }
++                    else
++                    {
++                        if ((min == 0) || (res < min))
++                            min = res;
++                    }
++                }
++
++            }
++
++            free(t);
++            mBounds[source] = qMakePair(min, max);
++#else
+     bool ok = false;
+ 
+     uint min = readAllFile(qPrintable(QString::fromLatin1("/sys/devices/system/cpu/%1/cpufreq/scaling_min_freq").arg(source))).toUInt(&ok);
+@@ -56,11 +160,34 @@ void CpuStatPrivate::addSource(const QString &source)
+         if (ok)
+             mBounds[source] = qMakePair(min, max);
+     }
++#endif
+ }
+ 
+ void CpuStatPrivate::updateSources()
+ {
+     mSources.clear();
++#ifdef HAVE_SYSCTL_H
++    mBounds.clear();
++    int cpu;
++
++    cpu = GetCpu();
++    mSources.append(QString::fromLatin1("cpu"));
++    for (int i =0;i<cpu;i++)
++    {
++        mSources.append(QString::fromLatin1("cpu%1").arg(i));
++        addSource(QString::fromLatin1("cpu%1").arg(i));
++    }
++    long max=0;
++    long min=0;
++    for (Bounds::ConstIterator I = mBounds.constBegin(); I != mBounds.constEnd(); ++I)
++    {
++        min += mBounds[I.key()].first;
++        max += mBounds[I.key()].second;
++
++    }
++
++    mBounds[QStringLiteral("cpu")] = qMakePair(min,max);
++#else
+     const QStringList rows = readAllFile("/proc/stat").split(QLatin1Char('\n'), Qt::SkipEmptyParts);
+     for (const QString &row : rows)
+     {
+@@ -98,6 +225,7 @@ void CpuStatPrivate::updateSources()
+                 addSource(QString::fromLatin1("cpu%1").arg(number));
+         }
+     }
++#endif
+ }
+ 
+ CpuStatPrivate::~CpuStatPrivate() = default;
+@@ -124,6 +252,113 @@ void CpuStatPrivate::recalculateMinMax()
+ 
+ void CpuStatPrivate::timeout()
+ {
++#ifdef HAVE_SYSCTL_H
++            if ( (mMonitoring == CpuStat::LoadOnly)
++              || (mMonitoring == CpuStat::LoadAndFrequency) )
++            {
++                int cpuNumber=0;
++                long *cp_times=0;
++
++                if(mSource!=QLatin1String("cpu"))
++                {
++                    size_t cp_size = sizeof(long) * CPUSTATES * GetCpu();
++                    cp_times = (long *)malloc(cp_size);
++                    cpuNumber = mSource.mid(0,3).toInt();
++                    if (sysctl(mib0,2, cp_times, &cp_size, NULL, 0) < 0)
++                        free(cp_times);
++                } else {
++                    size_t cp_size = sizeof(long)*CPUSTATES;
++                    cp_times = (long *)malloc(cp_size);
++                    if(sysctl(mib1,2,cp_times,&cp_size,NULL,0) < 0)
++                    {
++                        perror("sysctl");
++                        free(cp_times);
++                    }
++                }
++                Values current;
++                current.user = static_cast<ulong>(cp_times[CP_USER+cpuNumber*CPUSTATES]);
++                current.nice = static_cast<ulong>(cp_times[CP_NICE+cpuNumber*CPUSTATES]);
++                current.system = static_cast<ulong>(cp_times[CP_SYS+cpuNumber*CPUSTATES]);
++                current.idle = static_cast<ulong>(cp_times[CP_IDLE+cpuNumber*CPUSTATES]);
++                current.other = static_cast<ulong>(cp_times[CP_INTR+cpuNumber*CPUSTATES]);
++                current.total = current.user + current.nice + current.system+current.idle+current.other;
++                float sumDelta = static_cast<float>(current.total - mPrevious.total);
++                if ((mPrevious.total != 0) && ((sumDelta < mIntervalMin) || (sumDelta > mIntervalMax)))
++                {
++                    if (mMonitoring == CpuStat::LoadAndFrequency)
++		            {
++                        float freqRate = 1.0;
++                        ulong freq = CurrentFreq(mSource);
++
++                        if (mSource == QLatin1String("cpu")) {
++                                freq=0;
++                                for (Bounds::ConstIterator I = mBounds.constBegin(); I != mBounds.constEnd(); ++I) {
++                                    if (I.key() != QStringLiteral("cpu"))
++                                    {
++                                        freq += CurrentFreq(I.key());
++                                    }
++                                }
++                            }
++
++                        if (freq > 0)
++                        {
++                            freqRate = static_cast<float>(freq) / static_cast<float>(mBounds[mSource].second);
++                            emit update(0.0, 0.0, 0.0, 0.0, static_cast<float>(freqRate), freq);
++                        }
++                    } else {
++                        emit update(0.0, 0.0, 0.0, 0.0);
++			        }
++                    mPrevious.clear();
++                } else {
++                        if (mMonitoring == CpuStat::LoadAndFrequency)
++                    {
++                        float freqRate = 1.0;
++                        ulong freq = CurrentFreq(mSource);
++
++                        if (freq > 0)
++                        {
++					        if (mSource == QLatin1String("cpu")) {
++                                freq=0;
++                                for (Bounds::ConstIterator I = mBounds.constBegin(); I != mBounds.constEnd(); ++I) {
++                                    if (I.key() != QStringLiteral("cpu"))
++                                    {
++                                        freq += CurrentFreq(I.key());
++                                    }
++                        }
++                        }
++		                freqRate = static_cast<float>(freq) / static_cast<float>(mBounds[mSource].second);
++                           emit update(
++                               static_cast<float>(current.user   - mPrevious.user  ) / sumDelta,
++                               static_cast<float>(current.nice   - mPrevious.nice  ) / sumDelta,
++                               static_cast<float>(current.system - mPrevious.system) / sumDelta,
++                               static_cast<float>(current.other  - mPrevious.other ) / sumDelta,
++                               static_cast<float>(freqRate),
++                               freq);
++
++                        }
++                    }
++                        else
++                        {
++                            emit update(
++                                static_cast<float>(current.user   - mPrevious.user  ) / sumDelta,
++                                static_cast<float>(current.nice   - mPrevious.nice  ) / sumDelta,
++                                static_cast<float>(current.system - mPrevious.system) / sumDelta,
++                                static_cast<float>(current.other  - mPrevious.other ) / sumDelta);
++                        }
++
++                    mPrevious = current;
++                }
++                free(cp_times);
++            }
++            else
++            {
++                ulong freq = 0;
++
++                freq = CurrentFreq(mSource);
++                if (freq > 0)
++                    emit update(freq);
++            }
++#else
+     if ( (mMonitoring == CpuStat::LoadOnly)
+       || (mMonitoring == CpuStat::LoadAndFrequency) )
+     {
+@@ -258,6 +493,7 @@ void CpuStatPrivate::timeout()
+         }
+         emit update(freq);
+     }
++#endif
+ }
+ 
+ QString CpuStatPrivate::defaultSource()
diff --git a/sysutils/libsysstat-qt6/files/patch-cpustat.h b/sysutils/libsysstat-qt6/files/patch-cpustat.h
new file mode 100644
index 000000000000..01720c1d0e1d
--- /dev/null
+++ b/sysutils/libsysstat-qt6/files/patch-cpustat.h
@@ -0,0 +1,32 @@
+--- cpustat.h.orig	2020-11-03 14:45:02 UTC
++++ cpustat.h
+@@ -27,14 +27,19 @@
+ #ifndef LIBSYSSTAT__CPU_STAT__INCLUDED
+ #define LIBSYSSTAT__CPU_STAT__INCLUDED
+ 
+-
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
+ #include <QtCore/QObject>
+ 
+ #include "basestat.h"
+ 
+ 
+ namespace SysStat {
+-
++#ifdef HAVE_SYSCTL_H
++    char *GetFirstFragment(char *string, const char *delim);
++    int GetCpu(void);
++#endif
+ class CpuStatPrivate;
+ 
+ class SYSSTATSHARED_EXPORT CpuStat : public BaseStat
+@@ -54,7 +59,6 @@ class SYSSTATSHARED_EXPORT CpuStat : public BaseStat (
+ 
+     uint minFreq(const QString &source) const;
+     uint maxFreq(const QString &source) const;
+-
+ signals:
+     void update(float user, float nice, float system, float other, float frequencyRate, uint frequency);
+     void update(float user, float nice, float system, float other);
diff --git a/sysutils/libsysstat-qt6/files/patch-cpustat__p.h b/sysutils/libsysstat-qt6/files/patch-cpustat__p.h
new file mode 100644
index 000000000000..3c56a8038991
--- /dev/null
+++ b/sysutils/libsysstat-qt6/files/patch-cpustat__p.h
@@ -0,0 +1,65 @@
+--- cpustat_p.h.orig	2021-04-07 06:58:34 UTC
++++ cpustat_p.h
+@@ -27,6 +27,9 @@
+ #ifndef LIBSYSSTAT__CPU_STAT__PRIVATE__INCLUDED
+ #define LIBSYSSTAT__CPU_STAT__PRIVATE__INCLUDED
+ 
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
+ 
+ #include <QtCore/QObject>
+ #include <QtCore/QtGlobal>
+@@ -52,8 +55,15 @@ class CpuStatPrivate : public BaseStatPrivate (public)
+     CpuStat::Monitoring monitoring() const;
+     void setMonitoring(CpuStat::Monitoring value);
+ 
++#ifdef HAVE_SYSCTL_H
++    ulong minFreq(const QString &source) const;
++    ulong maxFreq(const QString &source) const;
++    ulong CurrentFreq(const QString);
++
++#else
+     uint minFreq(const QString &source) const;
+     uint maxFreq(const QString &source) const;
++#endif
+ 
+ signals:
+     void update(float user, float nice, float system, float other);
+@@ -74,12 +84,21 @@ private slots: (private)
+     {
+         Values();
+ 
++#ifdef HAVE_SYSCTL_H
++        ulong user;
++        ulong nice;
++        ulong system;
++        ulong idle;
++        ulong other;
++        ulong total;
++#else
+         qulonglong user;
+         qulonglong nice;
+         qulonglong system;
+         qulonglong idle;
+         qulonglong other;
+         qulonglong total;
++#endif
+ 
+         void sum();
+ 
+@@ -89,7 +108,14 @@ private slots: (private)
+ 
+     CpuStat::Monitoring mMonitoring;
+ 
++#ifdef HAVE_SYSCTL_H
++    typedef QMap<QString, QPair<ulong, ulong> > Bounds;
++    int mib0[2];
++    int mib1[2];
++    int mib2[512][4];
++#else
+     typedef QMap<QString, QPair<uint, uint> > Bounds;
++#endif
+     Bounds mBounds;
+ 
+     int mUserHz;
diff --git a/sysutils/libsysstat-qt6/files/patch-memstat.cpp b/sysutils/libsysstat-qt6/files/patch-memstat.cpp
new file mode 100644
index 000000000000..78e493983d06
--- /dev/null
+++ b/sysutils/libsysstat-qt6/files/patch-memstat.cpp
@@ -0,0 +1,123 @@
+--- memstat.cpp.orig	2021-11-05 10:06:40 UTC
++++ memstat.cpp
+@@ -26,10 +26,58 @@
+ 
+ #include "memstat.h"
+ #include "memstat_p.h"
++#if defined(HAVE_KVM_H) && defined(HAVE_SYSCTL_H)
++extern "C"
++{
++    #include <paths.h>
++    #include <unistd.h>
++    #include <fcntl.h>
+ 
++    #include <kvm.h>
++    #include <sys/types.h>
++    #include <sys/sysctl.h>
++}
++#endif
+ 
+ namespace SysStat {
++#ifdef HAVE_SYSCTL_H
++int SwapDevices()
++{
++    int buf;
++    size_t len = sizeof(int);
+ 
++    if (sysctlbyname("vm.nswapdev", &buf, &len, NULL, 0) < 0)
++        return 0;
++    else
++        return buf;
++}
++
++qulonglong MemGetByBytes(QString property)
++{
++    qulonglong buf=0;
++    size_t len = sizeof(qulonglong);
++
++    std::string s = property.toStdString();
++    const char *name = s.c_str();
++
++    if (sysctlbyname(name, &buf, &len, NULL, 0) < 0)
++        return 0;
++    else
++        return buf;
++}
++
++qulonglong MemGetByPages(QString name)
++{
++    qulonglong res = 0;
++
++
++    res = MemGetByBytes(name);
++    if (res > 0)
++        res = res * getpagesize();
++
++    return res;
++}
++#endif
+ MemStatPrivate::MemStatPrivate(MemStat *parent)
+     : BaseStatPrivate(parent)
+ {
+@@ -49,8 +97,39 @@ void MemStatPrivate::timeout()
+     qulonglong memBuffers = 0;
+     qulonglong memCached = 0;
+     qulonglong swapTotal = 0;
+-    qulonglong swapFree = 0;
++#ifdef HAVE_SYSCTL_H
++    memTotal = MemGetByBytes(QLatin1String("hw.physmem"));
++    memFree = MemGetByPages(QLatin1String("vm.stats.vm.v_free_count"));
++    memBuffers = MemGetByBytes(QLatin1String("vfs.bufspace"));
++    memCached = MemGetByPages(QLatin1String("vm.stats.vm.v_inactive_count"));
+ 
++#endif
++#ifdef HAVE_KVM_H
++    qulonglong swapUsed = 0;
++    kvm_t *kd;
++    struct kvm_swap kswap[16]; /* size taken from pstat/pstat.c */
++
++    kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open");
++    if (kd == NULL)
++        kvm_close(kd);
++
++    if (kvm_getswapinfo(kd, kswap, (sizeof(kswap) / sizeof(kswap[0])), SWIF_DEV_PREFIX) > 0)
++    {
++        int swapd = SwapDevices();
++        /* TODO: loop over swap devives */
++        if (swapd >= 1)
++        {
++            swapTotal = static_cast<qulonglong>(kswap[0].ksw_total * getpagesize());
++            swapUsed = static_cast<qulonglong>(kswap[0].ksw_used * getpagesize());
++        }
++
++        kvm_close(kd);
++    }
++    else
++        kvm_close(kd);
++#endif
++#ifndef HAVE_SYSCTL_H
++    qulonglong swapFree = 0;
+     const QStringList rows = readAllFile("/proc/meminfo").split(QLatin1Char('\n'), Qt::SkipEmptyParts);
+     for (const QString &row : rows)
+     {
+@@ -72,6 +151,7 @@ void MemStatPrivate::timeout()
+             swapFree = tokens[1].toULong();
+     }
+ 
++#endif
+     if (mSource == QLatin1String("memory"))
+     {
+         if (memTotal)
+@@ -88,8 +168,11 @@ void MemStatPrivate::timeout()
+     {
+         if (swapTotal)
+         {
++#ifndef HAVE_KVM_H
+             float swapUsed_d = static_cast<float>(swapTotal - swapFree) / static_cast<float>(swapTotal);
+-
++#else
++            float swapUsed_d = static_cast<float>(swapUsed) / static_cast<float>(swapTotal);
++#endif
+             emit swapUpdate(swapUsed_d);
+         }
+     }
diff --git a/sysutils/libsysstat-qt6/files/patch-memstat.h b/sysutils/libsysstat-qt6/files/patch-memstat.h
new file mode 100644
index 000000000000..399764f046fb
--- /dev/null
+++ b/sysutils/libsysstat-qt6/files/patch-memstat.h
@@ -0,0 +1,26 @@
+--- memstat.h.orig	2019-01-30 19:24:29 UTC
++++ memstat.h
+@@ -27,7 +27,9 @@
+ #ifndef LIBSYSSTAT__MEM_STAT__INCLUDED
+ #define LIBSYSSTAT__MEM_STAT__INCLUDED
+ 
+-
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
+ #include <QtCore/QObject>
+ 
+ #include "basestat.h"
+@@ -36,7 +38,11 @@
+ namespace SysStat {
+ 
+ class MemStatPrivate;
+-
++#if defined(HAVE_SYSCTL_H) && defined(HAVE_KVM_H)
++    int SwapDevices();
++    qulonglong MemGetByBytes(const QString property);
++    qulonglong MemGetByPages(const QString property);
++#endif
+ class SYSSTATSHARED_EXPORT MemStat : public BaseStat
+ {
+     Q_OBJECT
diff --git a/sysutils/libsysstat-qt6/files/patch-netstat.cpp b/sysutils/libsysstat-qt6/files/patch-netstat.cpp
new file mode 100644
index 000000000000..d62dc5a4a1ac
--- /dev/null
+++ b/sysutils/libsysstat-qt6/files/patch-netstat.cpp
@@ -0,0 +1,122 @@
+--- netstat.cpp.orig	2021-11-05 10:06:40 UTC
++++ netstat.cpp
+@@ -26,8 +26,23 @@
+ 
+ #include "netstat.h"
+ #include "netstat_p.h"
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
+ 
++#if defined(HAVE_SYSCTL_H) && defined(HAVE_IF_H)
++extern "C"
++{
++    #include <net/if.h>
++    #include <net/if_mib.h>
++    #include <net/if_types.h>
++    #include <sys/socket.h> /* PF_LINK */
++    #include <sys/types.h>
++    #include <sys/sysctl.h>
++}
++#endif
+ 
++
+ namespace SysStat {
+ 
+ NetStatPrivate::NetStatPrivate(NetStat *parent)
+@@ -37,6 +52,7 @@ NetStatPrivate::NetStatPrivate(NetStat *parent)
+ 
+     connect(mTimer, SIGNAL(timeout()), SLOT(timeout()));
+ 
++#ifndef HAVE_SYSCTL_H
+ 
+     QStringList rows(readAllFile("/proc/net/dev").split(QLatin1Char('\n'), Qt::SkipEmptyParts));
+ 
+@@ -50,12 +66,79 @@ NetStatPrivate::NetStatPrivate(NetStat *parent)
+ 
+         mSources.append(tokens[0].trimmed());
+     }
++#else
++        int count;
++        size_t len;
++        int cntifmib[] = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_SYSTEM, IFMIB_IFCOUNT };// net.link.generic.system.ifcount;
++        len = sizeof(int);
++        if (sysctl(cntifmib, 5, &count, &len, NULL, 0) < 0)
++            perror("sysctl");
++
++
++        struct ifmibdata ifmd;
++        size_t len1 = sizeof(ifmd);
++        for (int i=1; i<=count;i++) {
++            int name[] = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_IFDATA, i, IFDATA_GENERAL };
++
++            if (sysctl(name, 6, &ifmd, &len1, NULL, 0) < 0) {
++                perror("sysctl");
++            }
++            if ((ifmd.ifmd_data.ifi_type == IFT_ETHER) || (ifmd.ifmd_data.ifi_type == IFT_IEEE80211)) {
++            const char *iface = ifmd.ifmd_name;
++            mSources.append(QString::fromLatin1(iface));
++            }
++        }
++#endif
+ }
+ 
+ NetStatPrivate::~NetStatPrivate() = default;
+ 
+ void NetStatPrivate::timeout()
+ {
++#if defined(HAVE_IF_H) && defined(HAVE_SYSCTL_H)
++    int count;
++    size_t len;
++    int name[] = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_SYSTEM, IFMIB_IFCOUNT };
++    struct ifmibdata ifmd;
++
++    len = sizeof(int);
++    if (sysctl(name, 5, &count, &len, NULL, 0) < 0)
++        return;
++
++    for (int i = 1; i <= count; i++)
++    {
++        len = sizeof(ifmd);
++        int name[] = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_IFDATA, i, IFDATA_GENERAL };
++
++        if (sysctl(name, 6, &ifmd, &len, NULL, 0) < 0)
++            break;
++
++        if ((ifmd.ifmd_data.ifi_type == IFT_ETHER) || (ifmd.ifmd_data.ifi_type == IFT_IEEE80211))
++        {
++            const char *iface = ifmd.ifmd_name;
++            QString interfaceName = QString::fromLatin1(iface);
++            if ((ifmd.ifmd_data.ifi_link_state == LINK_STATE_UP) && (ifmd.ifmd_data.ifi_ipackets > 0))
++            {
++
++
++                Values current;
++                current.received = ifmd.ifmd_data.ifi_ibytes;
++                current.transmitted = ifmd.ifmd_data.ifi_obytes;
++
++                if (!mPrevious.contains(interfaceName))
++                    mPrevious.insert(interfaceName, Values());
++                const Values &previous = mPrevious[interfaceName];
++
++                if (interfaceName == mSource)
++                    emit update((( current.received - previous.received ) * 1000 ) / mTimer->interval(), (( current.transmitted - previous.transmitted ) * 1000 ) / mTimer->interval());
++
++                mPrevious[interfaceName] = current;
++            } else if(interfaceName == mSource)
++                emit(update(0,0));
++
++        }
++    }
++#else
+     QStringList rows(readAllFile("/proc/net/dev").split(QLatin1Char('\n'), Qt::SkipEmptyParts));
+ 
+ 
+@@ -97,6 +180,7 @@ void NetStatPrivate::timeout()
+ 
+         mPrevious[interfaceName] = current;
+     }
++#endif
+ }
+ 
+ QString NetStatPrivate::defaultSource()
diff --git a/sysutils/libsysstat-qt6/pkg-descr b/sysutils/libsysstat-qt6/pkg-descr
new file mode 100644
index 000000000000..0c091aa86aec
--- /dev/null
+++ b/sysutils/libsysstat-qt6/pkg-descr
@@ -0,0 +1,2 @@
+Qt-based library to query system information like CPU, memory usage and
+network traffic.
diff --git a/sysutils/libsysstat-qt6/pkg-plist b/sysutils/libsysstat-qt6/pkg-plist
new file mode 100644
index 000000000000..2cfa71a85d82
--- /dev/null
+++ b/sysutils/libsysstat-qt6/pkg-plist
@@ -0,0 +1,20 @@
+include/sysstat-qt6/SysStat/BaseStat
+include/sysstat-qt6/SysStat/CpuStat
+include/sysstat-qt6/SysStat/Global
+include/sysstat-qt6/SysStat/MemStat
+include/sysstat-qt6/SysStat/NetStat
+include/sysstat-qt6/SysStat/Version
+include/sysstat-qt6/basestat.h
+include/sysstat-qt6/cpustat.h
+include/sysstat-qt6/memstat.h
+include/sysstat-qt6/netstat.h
+include/sysstat-qt6/sysstat_global.h
+include/sysstat-qt6/version.h
+lib/libsysstat-qt6.so
+lib/libsysstat-qt6.so.1
+lib/libsysstat-qt6.so.%%VERSION%%
+libdata/pkgconfig/sysstat-qt6.pc
+share/cmake/sysstat-qt6/sysstat-qt6-config-version.cmake
+share/cmake/sysstat-qt6/sysstat-qt6-config.cmake
+share/cmake/sysstat-qt6/sysstat-qt6-targets-%%CMAKE_BUILD_TYPE%%.cmake
+share/cmake/sysstat-qt6/sysstat-qt6-targets.cmake