1 /*
2   processtracker.cpp
3 
4   This file is part of GammaRay, the Qt application inspection and
5   manipulation tool.
6 
7   Copyright (C) 2016-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
8   Author: Filipe Azevedo <filipe.azevedo@kdab.com>
9 
10   Licensees holding valid commercial KDAB GammaRay licenses may use this file in
11   accordance with GammaRay Commercial License Agreement provided with the Software.
12 
13   Contact info@kdab.com if any conditions of this licensing are not clear to you.
14 
15   This program is free software; you can redistribute it and/or modify
16   it under the terms of the GNU General Public License as published by
17   the Free Software Foundation, either version 2 of the License, or
18   (at your option) any later version.
19 
20   This program is distributed in the hope that it will be useful,
21   but WITHOUT ANY WARRANTY; without even the implied warranty of
22   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23   GNU General Public License for more details.
24 
25   You should have received a copy of the GNU General Public License
26   along with this program.  If not, see <http://www.gnu.org/licenses/>.
27 */
28 
29 #include "processtracker.h"
30 
31 #include <QDebug>
32 #include <QTimer>
33 
34 using namespace GammaRay;
35 
36 class ProcessTracker::D : public QObject
37 {
38     Q_OBJECT
39 
40 public:
41     GammaRay::ProcessTracker *tracker;
42     GammaRay::ProcessTrackerBackend *backend;
43     QTimer *ticker;
44     GammaRay::ProcessTrackerInfo previousInfo;
45     qint64 pid;
46 
D(GammaRay::ProcessTracker * tracker)47     explicit D(GammaRay::ProcessTracker *tracker)
48         : QObject(tracker)
49         , tracker(tracker)
50         , backend(nullptr)
51         , ticker(new QTimer(this))
52         , pid(-1)
53     {
54         ticker->setSingleShot(false);
55 
56         connect(ticker, &QTimer::timeout, this, &D::requestUpdate);
57     }
58 
59 public slots:
requestUpdate()60     void requestUpdate()
61     {
62         if (!backend) {
63             qWarning("%s: Backend not set", Q_FUNC_INFO);
64             return;
65         }
66 
67         if (pid < 0) {
68             qWarning("%s: Pid not set", Q_FUNC_INFO);
69             return;
70         }
71 
72         backend->checkProcess(pid);
73     }
74 
processChecked(const GammaRay::ProcessTrackerInfo & info)75     void processChecked(const GammaRay::ProcessTrackerInfo &info)
76     {
77         if (pid != info.pid) {
78             return;
79         }
80 
81         if (info != previousInfo) {
82             previousInfo = info;
83             emit tracker->infoChanged(info);
84         }
85     }
86 };
87 
ProcessTracker(QObject * parent)88 ProcessTracker::ProcessTracker(QObject *parent)
89     : QObject(parent)
90     , d(new D(this))
91 {
92     qRegisterMetaType<GammaRay::ProcessTrackerInfo>("GammaRay::ProcessTrackerInfo");
93 }
94 
~ProcessTracker()95 ProcessTracker::~ProcessTracker()
96 {
97     stop();
98 }
99 
backend() const100 GammaRay::ProcessTrackerBackend *ProcessTracker::backend() const
101 {
102     return d->backend;
103 }
104 
setBackend(GammaRay::ProcessTrackerBackend * backend)105 void ProcessTracker::setBackend(GammaRay::ProcessTrackerBackend *backend)
106 {
107     if (backend == d->backend) {
108         return;
109     }
110 
111     if (d->backend) {
112         disconnect(d->backend, &ProcessTrackerBackend::processChecked,
113                    d.data(), &D::processChecked);
114     }
115 
116     d->backend = backend;
117 
118     if (d->backend) {
119         connect(d->backend, &ProcessTrackerBackend::processChecked,
120                 d.data(), &D::processChecked, Qt::QueuedConnection);
121     }
122 
123     emit backendChanged(d->backend);
124 }
125 
pid() const126 qint64 ProcessTracker::pid() const
127 {
128     return d->pid;
129 }
130 
isActive() const131 bool ProcessTracker::isActive() const
132 {
133     return d->ticker->isActive();
134 }
135 
setPid(qint64 pid)136 void ProcessTracker::setPid(qint64 pid)
137 {
138     d->previousInfo = ProcessTrackerInfo();
139     d->pid = pid;
140 }
141 
start(int msecs)142 void ProcessTracker::start(int msecs)
143 {
144     d->previousInfo = ProcessTrackerInfo();
145     d->ticker->start(msecs);
146 }
147 
stop()148 void ProcessTracker::stop()
149 {
150     d->previousInfo = ProcessTrackerInfo();
151     d->ticker->stop();
152 }
153 
operator ==(const GammaRay::ProcessTrackerInfo & other) const154 bool ProcessTrackerInfo::operator==(const GammaRay::ProcessTrackerInfo &other) const
155 {
156     return pid == other.pid &&
157             traced == other.traced &&
158             state == other.state
159     ;
160 }
161 
operator !=(const GammaRay::ProcessTrackerInfo & other) const162 bool ProcessTrackerInfo::operator!=(const GammaRay::ProcessTrackerInfo &other) const
163 {
164     return !operator==(other);
165 }
166 
ProcessTrackerBackend(QObject * parent)167 ProcessTrackerBackend::ProcessTrackerBackend(QObject *parent)
168     : QObject(parent)
169 {
170 }
171 
172 #include "processtracker.moc"
173