Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 applets/dde-apps/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

find_package(Qt${QT_VERSION_MAJOR} ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS DBus)
find_package(DDEApplicationManager REQUIRED)
find_package(GLIB2 REQUIRED COMPONENTS GIO)
find_package(yaml-cpp REQUIRED)

set_source_files_properties(
Expand Down Expand Up @@ -55,10 +56,14 @@ add_library(dde-apps SHARED ${DBUS_INTERFACES}
categoryutils.h
itemspage.cpp
itemspage.h
trashmonitor.cpp
trashmonitor.h
)

target_link_libraries(dde-apps PRIVATE
dde-shell-frame
Qt${QT_VERSION_MAJOR}::Concurrent
GLIB2::GIO
yaml-cpp
)

Expand Down
30 changes: 30 additions & 0 deletions applets/dde-apps/amappitemmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
#include "amappitemmodel.h"
#include "amappitem.h"
#include "appitemmodel.h"
#include "objectmanager1interface.h"

Check warning on line 8 in applets/dde-apps/amappitemmodel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "objectmanager1interface.h" not found.
#include "trashmonitor.h"

#include <DUtil>

Check warning on line 11 in applets/dde-apps/amappitemmodel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <DUtil> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Q_LOGGING_CATEGORY(appsLog, "org.deepin.dde.shell.dde-apps.amappitemmodel")

Expand All @@ -16,6 +17,7 @@
AMAppItemModel::AMAppItemModel(QObject *parent)
: AppItemModel(parent)
, m_manager(new ObjectManager("org.desktopspec.ApplicationManager1", "/org/desktopspec/ApplicationManager1", QDBusConnection::sessionBus(), this))
, m_trashMonitor(new TrashMonitor(this))
, m_ready(false)
{
qRegisterMetaType<ObjectInterfaceMap>();
Expand All @@ -35,6 +37,18 @@
return;
}
appendRow(new AMAppItem(objPath, interfacesAndProperties));
updateTrashIcon();
});

connect(m_trashMonitor, &TrashMonitor::emptyChanged, this, &AMAppItemModel::updateTrashIcon);
connect(this, &QAbstractItemModel::dataChanged, this,
[this](const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles) {
const auto trashIndex = match(index(0, 0), AppItemModel::DesktopIdRole,
QStringLiteral("dde-trash"), 1, Qt::MatchExactly).value(0);
if (trashIndex.isValid() && trashIndex.row() >= topLeft.row() && trashIndex.row() <= bottomRight.row()
&& (roles.isEmpty() || roles.contains(AppItemModel::IconNameRole))) {
updateTrashIcon();
}
});

connect(m_manager, &ObjectManager::InterfacesRemoved, this, [this](const QDBusObjectPath &objPath, const QStringList &interfaces) {
Expand Down Expand Up @@ -69,6 +83,9 @@
appendRow(new AMAppItem(path, app.value()));
}


updateTrashIcon();

m_ready = true;
Q_EMIT readyChanged(true);
qCDebug(appsLog) << "AMAppItemModel is now ready with apps counts:" << rowCount();
Expand All @@ -90,4 +107,17 @@
return nullptr;
}

void AMAppItemModel::updateTrashIcon()
{
auto *trash = appItem(QStringLiteral("dde-trash"));
if (!trash)
return;

const QString iconName = m_trashMonitor->isEmpty()
? QStringLiteral("user-trash")
: QStringLiteral("user-trash-full");
if (trash->appIconName() != iconName)
trash->setAppIconName(iconName);
}

}
6 changes: 5 additions & 1 deletion applets/dde-apps/amappitemmodel.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

Expand All @@ -10,6 +10,7 @@
namespace apps
{
class AMAppItem;
class TrashMonitor;
class AMAppItemModel : public AppItemModel
{
Q_OBJECT
Expand All @@ -25,7 +26,10 @@ class AMAppItemModel : public AppItemModel
void readyChanged(bool);

private:
void updateTrashIcon();

bool m_ready;
ObjectManager *m_manager;
TrashMonitor *m_trashMonitor;
};
}
90 changes: 90 additions & 0 deletions applets/dde-apps/trashmonitor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "trashmonitor.h"

#include <QLoggingCategory>

Check warning on line 7 in applets/dde-apps/trashmonitor.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QLoggingCategory> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Q_LOGGING_CATEGORY(trashMonitorLog, "org.deepin.dde.shell.dde-apps.trash")

namespace apps
{
TrashMonitor::TrashMonitor(QObject *parent)
: QObject(parent)
, m_trash(g_file_new_for_uri("trash:///"))
{
updateState();

GError *error = nullptr;
m_monitor = g_file_monitor_file(m_trash, G_FILE_MONITOR_NONE, nullptr, &error);
if (!m_monitor) {
qCWarning(trashMonitorLog) << "Failed to monitor trash:"
<< (error ? error->message : "unknown error");
g_clear_error(&error);
return;
}

g_signal_connect(m_monitor, "changed", G_CALLBACK(onTrashChanged), this);
}

TrashMonitor::~TrashMonitor()
{
if (m_monitor)
g_object_unref(m_monitor);
if (m_trash)
g_object_unref(m_trash);
}

bool TrashMonitor::isEmpty() const
{
return m_empty;
}

void TrashMonitor::updateState()
{
GError *error = nullptr;
GFileInfo *info = g_file_query_info(m_trash,
G_FILE_ATTRIBUTE_TRASH_ITEM_COUNT,
G_FILE_QUERY_INFO_NONE,
nullptr,
&error);
if (!info) {
qCWarning(trashMonitorLog) << "Failed to query trash item count:"
<< (error ? error->message : "unknown error");
g_clear_error(&error);
return;
}

const bool empty = g_file_info_get_attribute_uint32(info, G_FILE_ATTRIBUTE_TRASH_ITEM_COUNT) == 0;
g_object_unref(info);

if (m_empty == empty)
return;

m_empty = empty;
Q_EMIT emptyChanged(m_empty);
}

void TrashMonitor::onTrashChanged(GFileMonitor *monitor,
GFile *file,
GFile *otherFile,
GFileMonitorEvent eventType,
gpointer userData)
{
Q_UNUSED(monitor)
Q_UNUSED(file)
Q_UNUSED(otherFile)

switch (eventType) {
case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
case G_FILE_MONITOR_EVENT_CHANGED:
case G_FILE_MONITOR_EVENT_CREATED:
case G_FILE_MONITOR_EVENT_DELETED:
static_cast<TrashMonitor *>(userData)->updateState();
break;
default:
break;
}
}
}
40 changes: 40 additions & 0 deletions applets/dde-apps/trashmonitor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#pragma once

#include <QObject>

Check warning on line 7 in applets/dde-apps/trashmonitor.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QObject> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#undef signals
#include <gio/gio.h>

Check warning on line 10 in applets/dde-apps/trashmonitor.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <gio/gio.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#define signals Q_SIGNALS

namespace apps
{
class TrashMonitor : public QObject
{
Q_OBJECT

public:
explicit TrashMonitor(QObject *parent = nullptr);
~TrashMonitor() override;

bool isEmpty() const;

signals:
void emptyChanged(bool empty);

private:
void updateState();
static void onTrashChanged(GFileMonitor *monitor,
GFile *file,
GFile *otherFile,
GFileMonitorEvent eventType,
gpointer userData);

GFile *m_trash = nullptr;
GFileMonitor *m_monitor = nullptr;
bool m_empty = true;
};
}
Loading