1# The QDirStat Packages View
2
3QDirStat can now visualize the file lists of installed packages:
4
5![Packages View Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-pkg-details.png)
6
7I.e. files are now grouped by the package they belong to, and in each subtree
8only the files that belong to the package are displayed: In this example, in
9`/usr/bin` only the `chromium-browser` binary is displayed, not all the other
10files in `/usr/bin`. This is intentional.
11
12Notice that you can also see the grouping in the treemap.
13
14A click on the toplevel item in the tree or on `Pkg:/` in the URL shows the
15packages summary:
16
17![Packages Summary Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-pkg-summary.png)
18
19
20
21## Target Platforms
22
23This works on all Linux distributions using one of those low-level package
24managers:
25
26- Dpkg
27- RPM
28- PacMan
29
30...and of course all higher-level package managers that are based on any of
31them. I.e.
32
33- Debian
34
35- Ubuntu / Kubuntu / Xubuntu / Lubuntu
36
37- SUSE (openSUSE Tumbleweed or Leap, SLES)
38
39- Red Hat (Fedora, RHEL)
40
41- Arch Linux
42
43- Manjaro
44
45It can even handle _rpm_ installed as a foreign package manager on a _dpkg_
46based system (and the other way round); it tries the primary package manager
47first, then any others that are also installed.
48
49Please notice that _apt_, _synaptic_, _zypper_, _pkgkit_ and whatnot are all
50higher level package managers that ultimately use one of the low level ones, so
51even if you only use a higher level package manager, it still works without
52restriction.
53
54
55
56## Package Selection
57
58QDirStat can fetch the information for all installed packages (which may take a
59while) or only for a subset (which is much quicker, of course):
60
61![Screenshot: Packages View limited to "emacs*"](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-pkg-emacs.png)
62
63This example shows all installed packages whose name starts with "emacs".
64
65
66### GUI
67
68Menu _File_ -> _Show Installed Packages_ opens this package selection dialog:
69
70!["Open Packages" Dialog Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-open-pkg-dialog.png)
71
72Enter the search pattern in the input field. The default match mode is _Auto_
73which tries to guess a reasonable mode, but you can also explicitly select one
74of
75
76- Contains
77- Starts with
78- Exact match
79- Wildcard (very much like in the shell)
80- Regular expression
81
82_Auto_ uses heuristics to make an educated guess. The default is "starts with",
83but if the search pattern contains typical regexp special characters, it
84interprets the pattern as a regular expression.
85
86If it detects just `*` (not `.*`) or `?`, it uses _wildcard_.
87
88If the first character is `=`, it uses _exact match_.
89
90All match modes are case insensitive.
91
92
93### Command Line: Pkg URLs
94
95You can also start QDirStat with a `pkg:` or `pkg:/` URL from the command
96line. This also implicitly uses _auto_ mode, so the same heuristics apply to
97interpret the URL:
98
99```
100qdirstat pkg:/chrom
101```
102
103All packages starting with "chrom" or "Chrom" or "CHROM".
104
105_Notice that all patterns are case insensitive -- mostly because distro makers
106and packagers tend to get creative when to use uppercase characters in package
107names, and most users can't remember when or why._
108
109
110```
111qdirstat pkg:/=emacs
112```
113
114Only package "emacs", not "emacs25" or any other starting with "emacs".
115
116
117```
118qdirstat "pkg:/*gtk*"
119```
120
121_Notice that you have to protect the `*` wildcards from the shell by escaping
122them with quotes._
123
124All packages that have "gtk" somewhere in their name.
125
126```
127qdirstat "pkg:/.*qt[45].*"
128```
129
130All Qt4 or Qt5 packages. Notice that the patterns are case insensitive.
131
132```
133qdirstat "pkg:/(firefox|mozilla|chrome|chromium|opera)"
134```
135
136All the well-known browsers on the system. Notice that regular expressions use
137a partial match, so use the `^` and `$` anchors when appropriate.
138
139
140### Command Line: No initial "Choose Directory" Dialog
141
142If you don't pass a command line argument to QDirStat, it will by default open
143a directory selection dialog. This can be avoided with the `-d` or `--dont-ask`
144command line option:
145
146```
147qdirstat -d
148```
149
150Of course you can always simply click that dialog away with the _Cancel_
151button, but it might be useful for `.desktop` files to have that command line
152parameter.
153
154
155## Behind the Scenes
156
157QDirStat uses external commands to get the information, both the list of
158installed packages and the file list for each of the selected packages.
159
160It always fetches the complete package list and then does the filtering
161internally based on the package filter/URL; it does not rely on how each
162external package manager interprets any patterns.
163
164Packages that are installed in multiple versions or for multiple architectures
165are treated internally as separate packages.
166
167
168To get the package list, QDirStat uses any of those commands:
169
170```
171dpkg-query --show --showformat='${Package} | ${Version} | ${Architecture} | ${Status}\n'
172```
173
174```
175rpm -qa --queryformat '%{name} | %{version}-%{release} | %{arch}\n'
176```
177
178```
179pacman -Qn
180```
181
182Then it parses the output of those commands, removes those that don't fit the
183filter criteria and iterates over the remaining ones to get the file list for
184each one with any of those commands:
185
186```
187dpkg-query --listfiles pkgname
188```
189
190```
191rpm -ql pkgname
192```
193
194```
195pacman -Qlq pkgname
196```
197
198Then for each file list entry QDirStat does the usual `lstat()` syscall to get
199up-to-date information about it from the filesystem (the file lists also don't
200contain any information other than the path, not even if it's a file or a
201directory, much less the size).
202
203As you can imagine, waiting for all those external commands to return
204information takes a while, in particular when all installed packages are
205selected to display.
206
207The first version of this took about 3 minutes to fetch all the information for
208a quite normal Xubuntu 18.04 LTS installation -- much longer than just reading
209the complete root filesystem with cold kernel buffers.
210
211This is why now QDirStat starts a number of those external commands in
212parallel; the sweet spot turned out to be 6 of those processes at the same time
213(whenever one is finished, a new one is started so there are always 6 of them
214running). This improved the speed on the same machine to 54 seconds.
215
216The number of background processes can be configured in
217`~/.config/QDirStat/QDirStat.conf`:
218
219```
220[Pkg]
221MaxParallelProcesses=6
222```
223
224For `dpkg` and `rpm` it now uses a single command that fetches the complete
225file list, i.e. all file lists for all installed packages at once. This reduced
226the time on the same machine to 38.5 seconds.
227
228However, this is a tradeoff since fetching that complete file list and parsing
229it takes some time, so this is useful only above a certain number of packages
230(about 200). This limit can be configured in
231
232`~/.config/QDirStat/QDirStat.conf`:
233
234```
235[Pkg]
236MinCachePkgListSize=200
237```
238
239Below that, it uses multiple parallel single calls to get individual file
240lists.
241
242Together with more performance tuning it's now down to 6.5 seconds.
243
244
245| sec   |  Version   | Description                                                         |
246|------:|------------|---------------------------------------------------------------------|
247| 180.0 | ce3e793298 | First pkg view; sequential separate `dpkg -L` calls                 |
248|  53.4 | 68038f0525 | Separate `dpkg -L` calls in multiple background processes           |
249|  38.5 | ce54879a48 | Single `dpkg -S "*"` call to get all file lists for all pkg at once |
250|  37.7 | 45b0a7a941 | Use cache for `lstat()` syscalls                                    |
251|  24.6 | c50e9a7686 | Use slower update timer for tree view while reading                 |
252|   6.5 | a1043a20fb | Keep tree collapsed during reading                                  |
253
254See also [GitHub Issue #101](https://github.com/shundhammer/qdirstat/issues/101).
255
256
257## Limitations
258
259### Cleanups
260
261Some of the cleanup actions are still useful in the packages view, in
262particular "Open Filemanager Here" or "Open Terminal Here".
263
264With everything else, be really, really careful!
265
266Since all the files in that display are by definition system files, think twice
267before deleting any one of them. If in doubt, just don't do it.
268
269Be even more careful when dealing with directories: Remember that you only see
270that part of the directory that belongs to that package. There might be many
271more files in such a directory; for most directories, this is almost
272guaranteed.
273
274If you identify a disk space hog with the packages view, it is strongly advised
275that you use your package manager to try to get rid of it, i.e. uninstall that
276package -- and even then only if you know really well what you are doing.
277
278
279### Dependencies
280
281QDirStat only displays the raw information in the packages view: Just the disk
282usage of each package.
283
284It does not and very likely will not display any dependencies of a package,
285much less indirect dependencies. This is the package manager's job.
286
287If you identified a package that uses a lot of disk space, you will very likely
288find that some other package requires it, and yet another package requires that
289one etc. until you get to the level where you can even recognize a package that
290you actively use.
291
292Big fat `libfoo-locale` might be required by `libfoo` which might be required
293by `foomatic` which might be required by `bar-desktop-base` which may be
294required by not only your favourite desktop environment, but also by your
295favourite media player application `boomplayer`.
296
297As a matter of fact, that is more the norm than the exception. Distro makers
298usually don't include packages just for fun, but because they are needed or at
299least useful in the context of your system.
300
301
302### What...if Scenarios
303
304It would have been very nice to to include a feature like "what would happen if
305I tried to remove that package?", showing the user what other packages would
306also need to be removed.
307
308Most higher-level package managers such as `zypper` or `apt` have a _dry run_
309feature that could be used for this: Try a dry run of removing the `libfoo`
310package, and it will show you all the direct and indirect dependencies, so you
311can make an informed decision if you really can (and want to) live without all
312those packages.
313
314But those commands tend to require root permissions, even for the _dry run_
315mode, and a desktop program like QDirStat asking for your _sudo_ password to
316get those root permissions might be scary (and for good reasons) to many users.
317
318
319## Support for More Package Managers
320
321It's not that hard to add more package managers to the existing set, but there
322must be reasonable support for that by people who actively use that platform
323and who have the know-how to identify and fix problems.
324
325Check out the existing ones to get an idea; it's little more than copy & paste
326programming. Finding the right external programs and the right parameters is
327the major challenge; then there might be some minor programming work for
328parsing the output.
329
330https://github.com/shundhammer/qdirstat/blob/master/src/RpmPkgManager.h
331https://github.com/shundhammer/qdirstat/blob/master/src/RpmPkgManager.cpp
332
333https://github.com/shundhammer/qdirstat/blob/master/src/DpkgPkgManager.h
334https://github.com/shundhammer/qdirstat/blob/master/src/DpkgPkgManager.cpp
335
336https://github.com/shundhammer/qdirstat/blob/master/src/PacManPkgManager.h
337https://github.com/shundhammer/qdirstat/blob/master/src/PacManPkgManager.cpp
338
339