File indexing completed on 2024-04-28 05:31:43
0001 /* 0002 KSysGuard, the KDE System Guard 0003 0004 SPDX-FileCopyrightText: 2006-2007 John Tapsell <john.tapsell@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #ifndef PROCESSMODEL_P_H_ 0010 #define PROCESSMODEL_P_H_ 0011 0012 #include "ProcessModel.h" 0013 #include <processcore/extended_process_list.h> 0014 0015 #include "../config-ksysguard.h" 0016 #include <QDebug> 0017 #include <QHash> 0018 #include <QList> 0019 #include <QObject> 0020 #include <QPixmap> 0021 #include <QSet> 0022 #include <QTime> 0023 #include <QVariant> 0024 #include <kuser.h> 0025 0026 #if HAVE_X11 0027 #include <X11/Xatom.h> 0028 #include <X11/Xlib.h> 0029 #include <fixx11h.h> 0030 #include <kwindowsystem.h> 0031 #include <netwm.h> 0032 #include <private/qtx11extras_p.h> 0033 0034 struct WindowInfo { 0035 WindowInfo(WId _wid, qlonglong _pid) 0036 : wid(_wid) 0037 , pid(_pid) 0038 { 0039 } 0040 0041 qlonglong pid; 0042 QPixmap icon; 0043 WId wid; 0044 QString name; 0045 }; 0046 #endif 0047 0048 namespace KSysGuard 0049 { 0050 class Processes; 0051 } 0052 0053 class ProcessModelPrivate : public QObject 0054 { 0055 Q_OBJECT 0056 public: 0057 ProcessModelPrivate(); 0058 ~ProcessModelPrivate() override; 0059 public Q_SLOTS: 0060 0061 #if HAVE_X11 0062 /** When an X window is changed, this is called */ 0063 void windowChanged(WId wid, NET::Properties properties, NET::Properties2 properties2); 0064 /** When an X window is created, this is called 0065 */ 0066 void windowAdded(WId wid); 0067 /** When an X window is closed, this is called 0068 */ 0069 void windowRemoved(WId wid); 0070 #endif 0071 0072 /** Change the data for a process. This is called from KSysGuard::Processes 0073 * if @p onlyCpuOrMem is set, only the total cpu usage is updated. 0074 * process->changes contains a bitfield of what has been changed 0075 */ 0076 void processChanged(KSysGuard::Process *process, bool onlyCpuOrMem); 0077 /** Called from KSysGuard::Processes 0078 * This indicates we are about to insert a process in the model. Emit the appropriate signals 0079 */ 0080 void beginInsertRow(KSysGuard::Process *parent); 0081 /** Called from KSysGuard::Processes 0082 * We have finished inserting a process 0083 */ 0084 void endInsertRow(); 0085 /** Called from KSysGuard::Processes 0086 * This indicates we are about to remove a process in the model. Emit the appropriate signals 0087 */ 0088 void beginRemoveRow(KSysGuard::Process *process); 0089 /** Called from KSysGuard::Processes 0090 * We have finished removing a process 0091 */ 0092 void endRemoveRow(); 0093 /** Called from KSysGuard::Processes 0094 * This indicates we are about to move a process in the model from one parent process to another. Emit the appropriate signals 0095 */ 0096 void beginMoveProcess(KSysGuard::Process *process, KSysGuard::Process *new_parent); 0097 /** Called from KSysGuard::Processes 0098 * We have finished moving a process 0099 */ 0100 void endMoveRow(); 0101 0102 public: 0103 /** Connects to the host */ 0104 void setupProcesses(); 0105 /** A mapping of running,stopped,etc to a friendly description like 'Stopped, either by a job control signal or because it is being traced.'*/ 0106 QString getStatusDescription(KSysGuard::Process::ProcessStatus status) const; 0107 0108 /** Return a qt markup tooltip string for a local user. It will have their full name etc. 0109 * This will be slow the first time, as it practically indirectly reads the whole of /etc/passwd 0110 * But the second time will be as fast as hash lookup as we cache the result 0111 */ 0112 inline QString getTooltipForUser(const KSysGuard::Process *process) const; 0113 0114 /** Return a username for a local user if it can, otherwise just their uid. 0115 * This may have been given from the result of "ps" (but not necessarily). 0116 * If it's not found, then it needs to find out the username from the uid. 0117 * This will be slow the first time, as it practically indirectly reads the whole of /etc/passwd 0118 * But the second time will be as fast as hash lookup as we cache the result 0119 * 0120 * If withuid is set, and the username is found, return: "username (Uid: uid)" 0121 */ 0122 inline QString getUsernameForUser(long uid, bool withuid) const; 0123 0124 /** Return the groupname for a given gid. This is in the form of "gid" if not known, or 0125 * "groupname (Uid: gid)" if known. 0126 */ 0127 inline QString getGroupnameForGroup(long gid) const; 0128 #if HAVE_X11 0129 /** On X11 system, connects to the signals emitted when windows are created/destroyed */ 0130 void setupWindows(); 0131 void updateWindowInfo(WId wid, NET::Properties properties, NET::Properties2 properties2, bool newWindow); 0132 QMultiHash<long long, WindowInfo *> mPidToWindowInfo; ///< Map a process pid to X window info if available 0133 QHash<WId, WindowInfo *> mWIdToWindowInfo; ///< Map an X window id to window info 0134 #if HAVE_XRES 0135 bool updateXResClientData(); 0136 void queryForAndUpdateAllXWindows(); 0137 #endif 0138 #endif 0139 void timerEvent(QTimerEvent *event) override; ///< Call dataChanged() for all the processes in mPidsToUpdate 0140 /** @see setIsLocalhost */ 0141 bool mIsLocalhost; 0142 0143 /** A caching hash for tooltips for a user. 0144 * @see getTooltipForUser */ 0145 mutable QHash<long long, QString> mUserTooltips; 0146 0147 /** A caching hash for username for a user uid, or just their uid if it can't be found (as a long long) 0148 * @see getUsernameForUser */ 0149 mutable QHash<long long, QString> mUserUsername; 0150 0151 /** A mapping of a user id to whether this user can log in. We have to guess based on the shell. 0152 * All are set to true to non localhost. 0153 * It is set to: 0154 * 0 if the user cannot login 0155 * 1 is the user can login 0156 * The reason for using an int and not a bool is so that we can do 0157 * \code mUidCanLogin.value(uid,-1) \endcode and thus we get a tristate for whether 0158 * they are logged in, not logged in, or not known yet. 0159 * */ 0160 mutable QHash<long long, int> mUidCanLogin; 0161 0162 /** A translated list of headings (column titles) in the order we want to display them. Used in headerData() */ 0163 QStringList mHeadings; 0164 0165 bool mShowChildTotals; ///< If set to true, a parent will return the CPU usage of all its children recursively 0166 0167 bool mSimple; //< In simple mode, the model returns everything as flat, with no icons, etc. This is set by changing cmbFilter 0168 0169 QTime mLastUpdated; ///< Time that we last updated the processes. 0170 0171 long long mMemTotal; ///< the total amount of physical memory in kb in the machine. We can used this to determine the percentage of memory an app is using 0172 int mNumProcessorCores; ///< The number of (enabled) processor cores in the this machine 0173 0174 QSharedPointer<KSysGuard::ExtendedProcesses> mProcesses; ///< The processes instance 0175 0176 QPixmap mBlankPixmap; ///< Used to pad out process names which don't have an icon 0177 0178 /** Show the process command line options in the process name column */ 0179 bool mShowCommandLineOptions; 0180 0181 bool mShowingTooltips; 0182 bool mNormalizeCPUUsage; 0183 /** When displaying memory sizes, this is the units it should be displayed in */ 0184 ProcessModel::Units mUnits; 0185 ProcessModel::Units mIoUnits; 0186 0187 ProcessModel::IoInformation mIoInformation; 0188 0189 /** The hostname */ 0190 QString mHostName; 0191 bool mHaveTimer; 0192 int mTimerId; 0193 QList<long> mPidsToUpdate; ///< A list of pids that we need to emit dataChanged() for regularly 0194 0195 static const int MAX_HIST_ENTRIES = 100; 0196 static const int MIN_HIST_AGE = 200; ///< If the latest history entry is at least this ms old, a new one gets added 0197 /** Storage for the history entries. We need one per percentage column. */ 0198 QHash<KSysGuard::Process *, QList<ProcessModel::PercentageHistoryEntry>> mMapProcessCPUHistory; 0199 0200 QList<KSysGuard::ProcessAttribute *> mExtraAttributes; 0201 0202 #if HAVE_XRES 0203 bool mHaveXRes; ///< True if the XRes extension is available at run time 0204 QMap<qlonglong, XID> mXResClientResources; 0205 #endif 0206 0207 bool mMovingRow; 0208 bool mRemovingRow; 0209 bool mInsertingRow; 0210 0211 bool mIsX11; 0212 0213 ProcessModel *q; 0214 }; 0215 0216 #endif