diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/AUTHORS | 2 | ||||
-rw-r--r-- | src/CMakeLists.txt | 45 | ||||
-rw-r--r-- | src/COPYING | 280 | ||||
-rw-r--r-- | src/ChangeLog | 53 | ||||
-rw-r--r-- | src/INSTALL | 167 | ||||
-rw-r--r-- | src/Makefile.am | 50 | ||||
-rw-r--r-- | src/README | 29 | ||||
-rw-r--r-- | src/TODO | 7 | ||||
-rw-r--r-- | src/cr16-app-kcpuload.png | bin | 0 -> 318 bytes | |||
-rw-r--r-- | src/cr32-app-kcpuload.png | bin | 0 -> 581 bytes | |||
-rw-r--r-- | src/cr48-app-kcpuload.png | bin | 0 -> 1310 bytes | |||
-rw-r--r-- | src/icontoggleaction.cpp | 63 | ||||
-rw-r--r-- | src/icontoggleaction.h | 62 | ||||
-rw-r--r-- | src/kcpudock.cpp | 32 | ||||
-rw-r--r-- | src/kcpudock.h | 41 | ||||
-rw-r--r-- | src/kcpuload.cpp | 177 | ||||
-rw-r--r-- | src/kcpuload.desktop | 11 | ||||
-rw-r--r-- | src/kcpuload.h | 72 | ||||
-rw-r--r-- | src/kcpuproc.cpp | 196 | ||||
-rw-r--r-- | src/kcpuproc.h | 170 | ||||
-rw-r--r-- | src/lo16-app-kcpuload.png | bin | 0 -> 328 bytes | |||
-rw-r--r-- | src/lo32-app-kcpuload.png | bin | 0 -> 413 bytes | |||
-rw-r--r-- | src/main.cpp | 64 | ||||
-rw-r--r-- | src/speeddialog.cpp | 63 | ||||
-rw-r--r-- | src/speeddialog.h | 50 | ||||
-rw-r--r-- | src/statdock.cpp | 270 | ||||
-rw-r--r-- | src/statdock.h | 164 | ||||
-rw-r--r-- | src/statpopup.cpp | 485 | ||||
-rw-r--r-- | src/statpopup.h | 320 |
29 files changed, 2873 insertions, 0 deletions
diff --git a/src/AUTHORS b/src/AUTHORS new file mode 100644 index 0000000..4af821b --- /dev/null +++ b/src/AUTHORS @@ -0,0 +1,2 @@ +Markus Gustavsson <[email protected]> +Ben Burton <[email protected]> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..2166732 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,45 @@ +include_directories( + ${CMAKE_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} + ${TDE_LIB_DIR} +) + + +##### kcpuload (executable) + +tde_add_executable( kcpuload AUTOMOC + + SOURCES + icontoggleaction.cpp + kcpudock.cpp + kcpuload.cpp + kcpuproc.cpp + main.cpp + statdock.cpp + speeddialog.cpp + statpopup.cpp + LINK + tdecore-shared + tdeui-shared + + DESTINATION ${BIN_INSTALL_DIR} +) + + +##### icons + +tde_install_icons( kcpuload ) + + +##### other data + +install( FILES kcpuload.desktop + DESTINATION ${APPS_INSTALL_DIR}/System +) diff --git a/src/COPYING b/src/COPYING new file mode 100644 index 0000000..c7aea18 --- /dev/null +++ b/src/COPYING @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/src/ChangeLog b/src/ChangeLog new file mode 100644 index 0000000..c9ce0a5 --- /dev/null +++ b/src/ChangeLog @@ -0,0 +1,53 @@ + + 02-12-20 * Added BSD support thanks to Andy Fawcett and Robbie Ward. + + 02-12-13 * v1.99. + * Ported to KDE3. + * Completely restructured, with the aims of: + - sharing as much code as possible between KCPULoad + and KNetLoad; + - looking and behaving more like other KDE apps + (including more respect for system settings and i18n); + - making the code more maintainable (such as providing + source documentation). + * Removed references to original website which is now offline. + Hopefully the new home will be KDE CVS. + * New maintainer Ben Burton <[email protected]>. + + 00-10-01 * v1.90 Ported to QT 2.x / KDE 1.9x/2.x (prerelease). + + 99-09-15 * Added a split option, which splits the diagram up + into one system-load scale and one user-load scale. + + 99-09-13 * Added German translation thanks to Fredrik Olson. + + 99-09-09 * Added a new Soft diagram option for a smoother curve. + * Added user documentation for installation and usage. + + 99-09-07 * Finished a new specialdesigned QToolTip lookalike, + leftclick to show it, leftclick again or rightclick + on popup to hide, use left mouse on popup to move it. + * Structure changes to make the program use less CPU. + + 99-09-01 * Added colorsetting for CPU2's diagram, and changed + so that SMP options don't appear on non-SMP systems. + + 99-08-30 * Settings are now saved direcly, not only upon quit. + * Added sessionmanagement thanks to Carsten Pfeiffer, + so the program will restart when KDE is restarted. + * Removed QToolTip Popup info dialog from program + because of a mem leak which made the program hang. + * Added several icons for both Color and style menues. + + 99-08-29 * Added two translations, Swedish, and Croatian + thanks to Vladimir Vuksan <[email protected]> + + 99-08-28 * Full SMP support with extra option for multiple + diagrams, one for each CPU or one for both. + * Added labels, so it doesn't look like knetload. + * Added Popup Tooltips with exact utilization values. + + 99-08-11 * Uses qmessagebox.h instead of `outdated' qmsgbox.h. + * Small security fixes. + + 99-08-06 * Program ready for initial release v1.0. diff --git a/src/INSTALL b/src/INSTALL new file mode 100644 index 0000000..02a4a07 --- /dev/null +++ b/src/INSTALL @@ -0,0 +1,167 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes a while. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Type `make install' to install the programs and any data files and + documentation. + + 4. You can remove the program binaries and object files from the + source code directory by typing `make clean'. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..b2b0e42 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,50 @@ + +############################################################################ +# # +# Main KCPULoad sources. # +# # +# KCPULoad is copyright (c) 1999-2000, Markus Gustavsson # +# (c) 2002, Ben Burton # +# # +# This program is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +############################################################################ + +INCLUDES = $(all_includes) + +bin_PROGRAMS = kcpuload + +kcpuload_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TQT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor + +kcpuload_LDADD = $(LIB_TDEUI) + +kcpuload_SOURCES = \ + icontoggleaction.cpp \ + kcpudock.cpp \ + kcpuload.cpp \ + kcpuproc.cpp \ + main.cpp \ + statdock.cpp \ + speeddialog.cpp \ + statpopup.cpp + +noinst_HEADERS = \ + icontoggleaction.h \ + kcpudock.h \ + kcpuload.h \ + kcpuproc.h \ + speeddialog.h \ + statdock.h \ + statpopup.h + +METASOURCES = AUTO + +appsdir = $(kde_appsdir)/System +apps_DATA = kcpuload.desktop + +KDE_ICON = kcpuload + +EXTRA_DIST = AUTHORS COPYING ChangeLog INSTALL README TODO diff --git a/src/README b/src/README new file mode 100644 index 0000000..ff5d0b6 --- /dev/null +++ b/src/README @@ -0,0 +1,29 @@ + +KCPULoad + +This file should only be read as a fast description. The online +KCPULoad handbook contains more detailed information. + +This is a small program for Kicker (the TDE panel). It will show the CPU +usage in the form of one or two configurable diagrams. There are settings +for colors and some different styles. Note that it isn't the real system +load that's shown, but the percent used of the total CPU power, which is +calculated from the number of CPU ticks.. don't ask me what that means :). + +To bring up the settings menu, simply right click on the diagram. Use a +slower update interval to get a more stable and accurate diagram without +flicker. + +If there is more than one CPU on the system, the total CPU usage from both +can be shown, or you can choose to have one separate diagram for each of the +CPUs. Left click on the diagram to bring up a small information box which +will show the exact CPU usage in text form. + +Install: + +./configure +make +make install + + Markus Gustavsson <[email protected]> + diff --git a/src/TODO b/src/TODO new file mode 100644 index 0000000..a3f1ba2 --- /dev/null +++ b/src/TODO @@ -0,0 +1,7 @@ + +DCOP support. +Change the text on colour menu items as docks are created and destroyed. +Support sticky pop-ups. +Have the default location of the pop-up being close to the system tray dock(s). +Support for more than two CPUs. + diff --git a/src/cr16-app-kcpuload.png b/src/cr16-app-kcpuload.png Binary files differnew file mode 100644 index 0000000..aa2ad05 --- /dev/null +++ b/src/cr16-app-kcpuload.png diff --git a/src/cr32-app-kcpuload.png b/src/cr32-app-kcpuload.png Binary files differnew file mode 100644 index 0000000..03e97bf --- /dev/null +++ b/src/cr32-app-kcpuload.png diff --git a/src/cr48-app-kcpuload.png b/src/cr48-app-kcpuload.png Binary files differnew file mode 100644 index 0000000..59aedb3 --- /dev/null +++ b/src/cr48-app-kcpuload.png diff --git a/src/icontoggleaction.cpp b/src/icontoggleaction.cpp new file mode 100644 index 0000000..3e73d98 --- /dev/null +++ b/src/icontoggleaction.cpp @@ -0,0 +1,63 @@ + +/*************************************************************************** + * * + * KCPULoad and KNetLoad are copyright (c) 1999-2000, Markus Gustavsson * + * (c) 2002, Ben Burton * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "icontoggleaction.h" + +IconToggleAction::IconToggleAction( + const TQString& useTextUnchecked, const TQString& useIconUnchecked, + const TQString& useTextChecked, const TQString& useIconChecked, + const TDEShortcut& cut, const TQObject* receiver, const char* slot, + TQObject* parent, const char* name) : + TDEToggleAction(useTextUnchecked, useIconUnchecked, cut, receiver, + slot, parent, name), + textChecked(useTextChecked), textUnchecked(useTextUnchecked), + iconChecked(useIconChecked), iconUnchecked(useIconUnchecked) { +} + +IconToggleAction::IconToggleAction(const TQString& useText, + const TQString& useIconUnchecked, const TQString& useIconChecked, + const TDEShortcut& cut, const TQObject* receiver, const char* slot, + TQObject* parent, const char* name) : + TDEToggleAction(useText, useIconUnchecked, cut, receiver, + slot, parent, name), + textChecked(useText), textUnchecked(useText), + iconChecked(useIconChecked), iconUnchecked(useIconUnchecked) { +} + +IconToggleAction::IconToggleAction( + const TQString& useTextUnchecked, const TQString& useIconUnchecked, + const TQString& useTextChecked, const TQString& useIconChecked, + const TDEShortcut& cut, TQObject* parent, const char* name) : + TDEToggleAction(useTextUnchecked, useIconUnchecked, cut, parent, name), + textChecked(useTextChecked), textUnchecked(useTextUnchecked), + iconChecked(useIconChecked), iconUnchecked(useIconUnchecked) { +} + +IconToggleAction::IconToggleAction(const TQString& useText, + const TQString& useIconUnchecked, const TQString& useIconChecked, + const TDEShortcut& cut, TQObject* parent, const char* name) : + TDEToggleAction(useText, useIconUnchecked, cut, parent, name), + textChecked(useText), textUnchecked(useText), + iconChecked(useIconChecked), iconUnchecked(useIconUnchecked) { +} + +void IconToggleAction::setChecked(bool value) { + if (value != isChecked()) { + setText(value ? textChecked : textUnchecked); + setIcon(value ? iconChecked : iconUnchecked); + } + + TDEToggleAction::setChecked(value); +} + +#include "icontoggleaction.moc" diff --git a/src/icontoggleaction.h b/src/icontoggleaction.h new file mode 100644 index 0000000..c54f120 --- /dev/null +++ b/src/icontoggleaction.h @@ -0,0 +1,62 @@ + +/*************************************************************************** + * * + * KCPULoad and KNetLoad are copyright (c) 1999-2000, Markus Gustavsson * + * (c) 2002, Ben Burton * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef __ICONTOGGLEACTION_H +#define __ICONTOGGLEACTION_H + +#include <tdeaction.h> + +/** + * A toggle action that uses different labels and pixmaps in its + * different states. + */ +class IconToggleAction : public TDEToggleAction { + Q_OBJECT + + + public: + /** + * Constructors. + */ + IconToggleAction( + const TQString& useTextUnchecked, const TQString& useIconUnchecked, + const TQString& useTextChecked, const TQString& useIconChecked, + const TDEShortcut& cut, const TQObject* receiver, const char* slot, + TQObject* parent, const char* name = 0); + IconToggleAction(const TQString& useText, + const TQString& useIconUnchecked, const TQString& useIconChecked, + const TDEShortcut& cut, const TQObject* receiver, const char* slot, + TQObject* parent, const char* name = 0); + IconToggleAction( + const TQString& useTextUnchecked, const TQString& useIconUnchecked, + const TQString& useTextChecked, const TQString& useIconChecked, + const TDEShortcut& cut = TDEShortcut(), TQObject* parent = 0, + const char* name = 0); + IconToggleAction(const TQString& useText, + const TQString& useIconUnchecked, const TQString& useIconChecked, + const TDEShortcut& cut = TDEShortcut(), TQObject* parent = 0, + const char* name = 0); + + /** + * Overridden to include icon adjustment. + */ + virtual void setChecked(bool); + + private: + TQString textChecked, textUnchecked; + /**< The labels to use in the checked and unchecked states. */ + TQString iconChecked, iconUnchecked; + /**< The icons to use in the checked and unchecked states. */ +}; + +#endif diff --git a/src/kcpudock.cpp b/src/kcpudock.cpp new file mode 100644 index 0000000..998cc30 --- /dev/null +++ b/src/kcpudock.cpp @@ -0,0 +1,32 @@ + +/*************************************************************************** + * * + * KCPULoad is copyright (c) 1999-2000, Markus Gustavsson * + * (c) 2002, Ben Burton * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kcpudock.h" + +#include <tdelocale.h> + +KCPUDock::KCPUDock(int whichCPU, StatPopup *parent, const char *name) : + StatDock(whichCPU, i18n("C"), parent, name) { +} + +void KCPUDock::setCPULabel(int set) { + if (set == 1) + setLabel(i18n("C 0")); + else if (set == 2) + setLabel(i18n("C 1")); + else + setLabel(i18n("C")); + + repaint(); +} + diff --git a/src/kcpudock.h b/src/kcpudock.h new file mode 100644 index 0000000..f96e411 --- /dev/null +++ b/src/kcpudock.h @@ -0,0 +1,41 @@ + +/*************************************************************************** + * * + * KCPULoad is copyright (c) 1999-2000, Markus Gustavsson * + * (c) 2002, Ben Burton * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef __KCPUDOCK_H +#define __KCPUDOCK_H + +#include "statdock.h" + +/** + * A KCPULoad system tray window for a specific CPU. + */ +class KCPUDock : public StatDock { + +public: + /** + * Constructor. + */ + KCPUDock(int whichDock, StatPopup *parent = 0, const char *name = 0); + + /** + * Sets the label for this diagram. The label will reflect which + * CPU the diagram represents. + * + * If multiple CPUs are not used, argument cpu should be 0. + * Otherwise argument cpu should be 1 or 2 for the first or second + * CPU respectively. + */ + void setCPULabel(int cpu); +}; + +#endif diff --git a/src/kcpuload.cpp b/src/kcpuload.cpp new file mode 100644 index 0000000..6005313 --- /dev/null +++ b/src/kcpuload.cpp @@ -0,0 +1,177 @@ + +/*************************************************************************** + * * + * KCPULoad is copyright (c) 1999-2000, Markus Gustavsson * + * (c) 2002, Ben Burton * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "icontoggleaction.h" +#include "kcpudock.h" +#include "kcpuload.h" +#include "kcpuproc.h" + +#include <tdeaction.h> +#include <tdeconfig.h> +#include <tdelocale.h> +#include <tdepopupmenu.h> + +KCPULoad::KCPULoad(TQWidget *parent, const char *name) : + StatPopup(true, parent, name) { + // Create the /proc reading class and check for SMP. + proc = new KCPUProc(); + supportSMP = proc->hasSMP(); + + // Set up actions and read the config file. + setupActions(); + + // the vector must not be reallocated during resizing because the class + // that it contains (Reading) cannot be copied safely + r.reserve(proc->cpu.size()); + + // Create system tray windows. + resizeReadings(supportSMP && actSMP->isChecked() ? proc->cpu.size() : 1); + + // Initialise the pop-up window. + readPopupState(); + + // Off we go! + requestResize(); + if (isActive()) + startUpdates(); +} + +KCPULoad::~KCPULoad() { + delete proc; +} + +void KCPULoad::setSMP(bool set) { + if (! supportSMP) + return; + + resizeReadings(set ? proc->cpu.size() : 1); + + requestResize(); + if (isActive()) + takeReading(); + + config->setGroup("General Options"); + config->writeEntry("SMP", set); + config->sync(); +} + +TQString KCPULoad::dockName(int which) const { + return i18n("CPU %1").arg(which+1); +} + +TQColor KCPULoad::defaultDockColor(int which) const { + static const TQColor c[] = { + TQColor(0, 255, 0), + TQColor(255, 0, 0), + TQColor(255, 255, 0), + TQColor(0, 255, 255) + }; + return c[which % (sizeof(c)/sizeof(c[0]))]; +} + +void KCPULoad::setupCustomActions() { + if (supportSMP) { + bool bVal = config->readBoolEntry("SMP", false); + actSMP = new IconToggleAction(i18n("Enable S&MP"), "smp", + i18n("S&MP Enabled"), "smpon", 0, coll, "smp"); + actSMP->setChecked(bVal); + connect(actSMP, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(setSMP(bool))); + } +} + +void KCPULoad::insertCustomItems(TDEPopupMenu* menu) { + if (supportSMP) { + actSMP->plug(menu); + menu->insertSeparator(); + } +} + +void KCPULoad::takeReadingInternal() { + proc->readLoad(); + + if (r.size() > 1) { + if (isSplit()) { + for (int i = 0; i < r.size(); i++) { + r[i].upper = proc->cpu[i].userPercent(); + r[i].lower = proc->cpu[i].systemPercent(); + } + } else { + for (int i = 0; i < r.size(); i++) { + r[i].upper = proc->cpu[i].totalPercent(); + } + } + } else if (r.size() > 0) { + if (isSplit()) { + r[0].upper = proc->all.userPercent(); + r[0].lower = proc->all.systemPercent(); + } else { + r[0].upper = proc->all.totalPercent(); + } + } + + if (isVisible()) { + if (r.size() > 1) { + if (isSplit()) { + TQString user = + i18n("Current CPU User: %1%") + .arg(proc->all.userPercent()); + TQString sys = + i18n("Current CPU System: %1%") + .arg(proc->all.systemPercent()); + for (int i = 0; i < r.size(); i++) { + user += i18n(", C%1: %2%").arg(i+1).arg(r[i].upper); + sys += i18n(", C%1: %2%").arg(i+1).arg(r[i].lower); + } + fullReading = i18n("%1.\n%2.").arg(user, sys); + } else { + TQString total = + i18n("Current CPU usage: %1%") + .arg(proc->all.totalPercent()); + for (int i = 0; i < r.size(); i++) { + total += i18n(", C%1: %2%").arg(i+1).arg(r[i].upper); + } + fullReading = i18n("%1.").arg(total); + } + } else if (r.size() > 0) { + if (isSplit()) { + fullReading = i18n( + "Current CPU User: %1%.\n" + "Current CPU System: %2%.") + .arg(r[0].upper).arg(r[0].lower); + } else { + fullReading = i18n("Current CPU usage: %1%.").arg(r[0].upper); + } + } + } + } + +void KCPULoad::resizeReadings(int n) +{ + int i = r.size(); + r.resize(n); + for (; i < n; i++) { + // action is needed by KCPUDock constructor + r[i].Init(i, this); + KCPUDock* dock = new KCPUDock(i, this); + dock->setCPULabel(i+1); + r[i].dock = dock; + } + // special case single CPU or total + if (n == 1) { + static_cast<KCPUDock*>(r[0].dock)->setCPULabel(0); + } else if (n > 1) { + static_cast<KCPUDock*>(r[0].dock)->setCPULabel(1); + } +} + +#include "kcpuload.moc" diff --git a/src/kcpuload.desktop b/src/kcpuload.desktop new file mode 100644 index 0000000..8182af4 --- /dev/null +++ b/src/kcpuload.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Type=Application +Exec=kcpuload +Icon=kcpuload +X-DocPath=kcpuload/index.html +Terminal=0 +Name=KCPULoad +GenericName=CPU Monitor +Comment=A small CPU usage meter for Kicker +Categories=Qt;TDE;System diff --git a/src/kcpuload.h b/src/kcpuload.h new file mode 100644 index 0000000..892d7db --- /dev/null +++ b/src/kcpuload.h @@ -0,0 +1,72 @@ + +/*************************************************************************** + * * + * KCPULoad is copyright (c) 1999-2000, Markus Gustavsson * + * (c) 2002, Ben Burton * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef __KCPULOAD_H +#define __KCPULOAD_H + +#include "statpopup.h" + +class KCPUProc; +class TDEToggleAction; + +/** + * The specific pop-up window used by KCPULoad. + */ +class KCPULoad : public StatPopup { + Q_OBJECT + + +public: + /** + * Constructor and destructor. + */ + KCPULoad(TQWidget *parent = 0, const char *name = 0); + ~KCPULoad(); + +public slots: + /** + * Slots for menu items. + */ + void setSMP(bool); + +protected: + /** + * Overrides from StatPopup. + */ + virtual TQString dockName(int which) const; + virtual TQColor defaultDockColor(int which) const; + virtual void setupCustomActions(); + virtual void insertCustomItems(TDEPopupMenu* menu); + virtual void takeReadingInternal(); + +private: + /** + * Changes the number of readings. + */ + void resizeReadings(int n); + + /** + * Reading raw CPU information. + */ + KCPUProc* proc; + /**< Used to obtain the raw information. */ + bool supportSMP; + /**< Does this system support SMP at all? */ + + /** + * Actions. + */ + TDEToggleAction* actSMP; +}; + +#endif diff --git a/src/kcpuproc.cpp b/src/kcpuproc.cpp new file mode 100644 index 0000000..f7fbe4f --- /dev/null +++ b/src/kcpuproc.cpp @@ -0,0 +1,196 @@ + +/*************************************************************************** + * * + * KCPULoad is copyright (c) 1999-2000, Markus Gustavsson * + * (c) 2002, Ben Burton * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kcpuproc.h" + +#include <cstdlib> +#include <cstring> + +// BSD-specific includes. +#ifdef Q_OS_BSD4 +#include <sys/dkstat.h> +#include <sys/param.h> +#include <sys/sysctl.h> +#include <string.h> +#include <kvm.h> +#ifdef Q_OS_NETBSD +#include <sys/sched.h> +#endif +#endif + +/** + * Linux + * ----- + * + * System information is read from /proc/stat. + * + * We assume /proc/stat is in one of the following formats: + * + * cpu %d %d %d %d + * .... + * + * cpu %d %d %d %d + * cpu0 %d %d %d %d + * .... + * + * cpu %d %d %d %d + * cpu0 %d %d %d %d + * cpu1 %d %d %d %d + * .... + * + * where each set of four numbers is of the form: + * + * user_ticks nice_ticks system_ticks idle_ticks + * + * We also allow sets of seven numbers instead of four (as provided by + * the 2.6 kernel); the last three of these numbers are ignored. + * + * BSD + * --- + * + * Currently only uni-processor mode is supported for BSD. + * + * BSD code by Andy Fawcett <[email protected]> and + * Robbie Ward <[email protected]>, licensed under GPL2. + * + * Other Operating Systems + * ----------------------- + * + * Please, send in a patch! + * + * The KCPULoad maintainer is currently Ben Burton <[email protected]>, or + * you could submit a patch through the KDE bug tracking system + * (bugs.kde.org). + */ + +KCPUProc::CPU::Ticks::Ticks() : + U(0), S(0), N(0), I(0) +{ } + +KCPUProc::KCPUProc() { + smp = false; + + // Look for SMP support and take a current tick reading. + + // ========== BSD-specific (begin) ========== +#ifdef Q_OS_BSD4 + readLoad(); + return; +#endif + // ========== BSD-specific (end) ========== + + // ========== Linux-specific (begin) ========== +#ifdef Q_OS_LINUX + if ((fd = fopen("/proc/stat", "r")) == 0) + return; + + if (!all.parse(fd)) + return; + CPU c; + while (c.parse(fd)) + cpu.push_back(c); + smp = cpu.size() > 1; +#endif + // ========== Linux-specific (end) ========== +} + +void KCPUProc::readLoad() { + // OS-specific local variables. + + // ========== Linux-specific (begin) ========== +#ifdef Q_OS_LINUX + // Prepare to take the readings. + + if ((fd = fopen("/proc/stat", "r")) == 0) + return; + + // Take a fresh set of current readings (SMP mode). + + all.parse(fd); + for (int i = 0; i < cpu.size(); i++) { + if (!cpu[i].parse(fd)) + break; + } + + // Clean up after taking readings. + + fclose(fd); +#endif + // ========== Linux-specific (end) ========== + + // ========== BSD-specific (begin) ========== +#ifdef Q_OS_BSD4 + static int name2oid[2] = { 0, 3 }; + static int oidCpuTime[CTL_MAXNAME + 2]; + static size_t oidCpuTimeLen = sizeof(oidCpuTime); + long cpuTime[CPUSTATES]; + unsigned int cpuTimeLen = sizeof(cpuTime); + static char *name = "kern.cp_time"; + static int initialized = 0; + + if(smp) { + // Take a fresh set of current readings (SMP mode). + // TODO: Add SMP support for BSD. + } else { + // Take a fresh set of current readings (uni-processor mode). + + // The current readings must now become the previous readings. + all.p = all.c; + + if (! initialized) { + if (sysctl(name2oid, 2, oidCpuTime, &oidCpuTimeLen, name, + strlen(name)) < 0) + return; + + oidCpuTimeLen /= sizeof(int); + initialized = 1; + } + + if (sysctl(oidCpuTime, oidCpuTimeLen, cpuTime, &cpuTimeLen, 0, 0) < 0) + return; + + all.c.U = cpuTime[CP_USER]; + all.c.N = cpuTime[CP_NICE]; + all.c.S = cpuTime[CP_SYS]; + all.c.I = cpuTime[CP_IDLE]; + } +#endif + // ========== BSD-specific (end) ========== +} + +// ========== Linux-specific (begin) ========== +#ifdef Q_OS_LINUX +bool KCPUProc::CPU::parse(FILE* fd) { + char tagbuffer[32+1]; + Ticks n; // new ticks + if (fscanf(fd, "%32s%d%d%d%d", tagbuffer, &n.U, &n.N, &n.S, &n.I) != 5) { + return false; // failure + } + + if (strncmp(tagbuffer, "cpu", 3) != 0) { + return false; // tag mismatch + } + + // shift readings + p = c; + c = n; + + // ignore the rest of the line + int ch; + do { + ch = getc(fd); + } while (ch != '\n' && ch != EOF); + return true; +} +#endif +// ========== Linux-specific (end) ========== diff --git a/src/kcpuproc.h b/src/kcpuproc.h new file mode 100644 index 0000000..8b844f5 --- /dev/null +++ b/src/kcpuproc.h @@ -0,0 +1,170 @@ + +/*************************************************************************** + * * + * KCPULoad is copyright (c) 1999-2000, Markus Gustavsson * + * (c) 2002, Ben Burton * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef __KCPUPROC_H +#define __KCPUPROC_H + +#include <cstdio> +#include <tqglobal.h> +#include <vector> + +/** + * A class used to read raw CPU load details from the system. + * + * See kcpuproc.cpp for details of supported operating systems. + */ +class KCPUProc { +public: + /** + * Constructor. + * + * In the constructor, a set of initial CPU tick readings are taken + * and SMP support is determined. + */ + KCPUProc(); + + /** + * Does this system appear to have SMP? + */ + bool hasSMP() const; + + /** + * Takes a fresh set of CPU tick readings. The numerical statistics + * returned refer to the time period between this reading and the + * previous (or between this reading and the object's construction + * if there was no previous reading). + */ + void readLoad(); + + /** + * Contains tick differences for a CPU. + */ + struct CPU { + /** + * Contains user/system/nice/idle tick readings. + */ + struct Ticks { + int U, S, N, I; + Ticks(); + /** Returns user ticks */ + int u() const { return U; } + /** Returns system ticks */ + int s() const { return S + N; } + /** Returns total (non-idle) ticks */ + int t() const { return U + S + N; } + /** Returns elapsed ticks */ + int e() const { return U + S + N + I; } + }; + + Ticks p; /**< The previous tick readings */ + Ticks c; /**< The last (most recent) tick readings */ + + /** + * The percentage of ticks between the last reading and the previous + * reading used by the user loop (compared to the nice, system and + * idle loops). + * + * This routine involves a short arithmetical calculation. + * If you're paranoid about running time, you might want to cache + * the result. + */ + int userPercent() const; + + /** + * The percentage of ticks between the last reading and the previous + * reading used by the system and nice loops (compared to the user and + * idle loops). + * + * This routine involves a short arithmetical calculation. + * If you're paranoid about running time, you might want to cache + * the result. + */ + int systemPercent() const; + + /** + * The percentage of ticks between the last reading and the previous + * reading used by the user, system and nice loops (compared to the + * idle loop). + * + * This routine involves a short arithmetical calculation. + * If you're paranoid about running time, you might want to cache + * the result. + */ + int totalPercent() const; + + /** + * OS-specific helper routines. + */ + + // ========== Linux-specific (begin) ========== +#ifdef Q_OS_LINUX + /** + * Parses the tick readings of the current line in #fd. + * The return value is \c false if the line does not begin with + * the tag "cpu" (optionally followed by a number). + * If the line can be parsed successfully, the last reading becomes + * the previous reading and the newly parsed reading becomes + * the last reading. + */ + bool parse(FILE* fd); +#endif + // ========== Linux-specific (end) ========== + }; + + /* + * Variables used in all modes. + */ + CPU all; /**< Tick readings for all CPUs. */ + + /* + * Variables used only with SMP. + */ + std::vector<CPU> cpu; /**< Tick readings for CPUs. */ + +private: + /* + * SMP support. + */ + bool smp; + /**< Does this system appear to have SMP? */ + + /** + * OS-specific data members. + */ + + // ========== Linux-specific (begin) ========== +#ifdef Q_OS_LINUX + FILE *fd; + /**< The file /proc/stat. */ +#endif + // ========== Linux-specific (end) ========== +}; + +inline bool KCPUProc::hasSMP() const { + return smp; +} + +inline int KCPUProc::CPU::userPercent() const { + int tot = c.e() - p.e(); + return (tot > 0 ? (100 * (c.u() - p.u())) / tot : 0); +} +inline int KCPUProc::CPU::systemPercent() const { + int tot = c.e() - p.e(); + return (tot > 0 ? (100 * (c.s() - p.s())) / tot : 0); +} +inline int KCPUProc::CPU::totalPercent() const { + int tot = c.e() - p.e(); + return (tot > 0 ? (100 * (c.t() - p.t())) / tot : 0); +} + +#endif diff --git a/src/lo16-app-kcpuload.png b/src/lo16-app-kcpuload.png Binary files differnew file mode 100644 index 0000000..278a3f5 --- /dev/null +++ b/src/lo16-app-kcpuload.png diff --git a/src/lo32-app-kcpuload.png b/src/lo32-app-kcpuload.png Binary files differnew file mode 100644 index 0000000..34606e5 --- /dev/null +++ b/src/lo32-app-kcpuload.png diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..6b587e5 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,64 @@ + +/*************************************************************************** + * * + * KCPULoad is copyright (c) 1999-2000, Markus Gustavsson * + * (c) 2002, Ben Burton * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kcpuload.h" + +#include <tdeaboutdata.h> +#include <tdecmdlineargs.h> +#include <tdelocale.h> +#include <kuniqueapplication.h> + +static const char *description = + I18N_NOOP("A small CPU usage meter for Kicker (the TDE panel)."); +static const char *message = + I18N_NOOP("KCPULoad was first released on the 8th of August, 1999."); +static const char *version = "2.00"; + +int main(int argc, char **argv) { + TDEAboutData aboutData("kcpuload", I18N_NOOP("KCPULoad"), version, + description, TDEAboutData::License_GPL, + "(c) 1999-2000, Markus Gustavsson\n" + "(c) 2002, Ben Burton\n" + "(c) 2009, Timothy Pearson", + message, 0 /* TODO: Website */, "[email protected]"); + + aboutData.addAuthor("Markus Gustavsson", "Original author", + "[email protected]"); + aboutData.addAuthor("Ben Burton", "KDE3 rewrite, current maintainer", + "[email protected]"); + aboutData.addAuthor("Andy Fawcett", "BSD support", + "[email protected]"); + aboutData.addAuthor("Robbie Ward", "BSD support", + "[email protected]"); + + aboutData.addCredit("Njaard, Charles Samuels", + "Support and help with KDE", "[email protected]"); + aboutData.addCredit("rikkus, Rik Hemsley", + "Support and help with KDE", "[email protected]"); + aboutData.addCredit("Mark Halpaap", + "Independent port to KDE3", "[email protected]"); + aboutData.addCredit("Thanks to everyone in #KDE OpenProjects for " + "being supportive and helpful!"); + + TDECmdLineArgs::init(argc, argv, &aboutData); + KUniqueApplication::addCmdLineOptions(); + + if (! KUniqueApplication::start()) { + fprintf(stderr, I18N_NOOP("KCPULoad is already running!\n")); + return 1; + } + + KUniqueApplication app; + app.setMainWidget(new KCPULoad()); + return app.exec(); +} diff --git a/src/speeddialog.cpp b/src/speeddialog.cpp new file mode 100644 index 0000000..845bb2a --- /dev/null +++ b/src/speeddialog.cpp @@ -0,0 +1,63 @@ + +/*************************************************************************** + * * + * KCPULoad and KNetLoad are copyright (c) 1999-2000, Markus Gustavsson * + * (c) 2002, Ben Burton * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "speeddialog.h" + +#include <cstdlib> +#include <kcombobox.h> +#include <tdelocale.h> +#include <tqlabel.h> +#include <tqhbox.h> +#include <tqvalidator.h> + +static int stockSpeed[] = { + 100, 150, 200, 250, 300, 400, 600, 800, 1000, 1200, 1500, 2000, 2500, + 3000, 4000, 5000, 0 +}; + +SpeedDialog::SpeedDialog(int defaultSpeed, TQWidget* parent) : + KDialogBase(parent, "speed dialog", true, + i18n("Select Speed"), Ok|Cancel, Ok), + speed(defaultSpeed) { + TQHBox* page = makeHBoxMainWidget(); + + new TQLabel(i18n("Update interval in milliseconds:"), page); + + KComboBox* speedBox = new KComboBox(true, page); + + TQIntValidator* val = new TQIntValidator(TQT_TQOBJECT(this)); + val->setBottom(1); + speedBox->setValidator(val); + + TQString speedStr; + for (int i = 0; stockSpeed[i]; i++) { + speedStr.setNum(stockSpeed[i]); + speedBox->insertItem(speedStr); + } + + speedStr.setNum(defaultSpeed); + speedBox->setCurrentText(speedStr); + + connect(speedBox, TQT_SIGNAL(textChanged(const TQString&)), + this, TQT_SLOT(updateSpeed(const TQString&))); +} + +int SpeedDialog::getSpeed() const { + return speed; +} + +void SpeedDialog::updateSpeed(const TQString& text) { + speed = atoi(text.ascii()); +} + +#include "speeddialog.moc" diff --git a/src/speeddialog.h b/src/speeddialog.h new file mode 100644 index 0000000..66b4380 --- /dev/null +++ b/src/speeddialog.h @@ -0,0 +1,50 @@ + +/*************************************************************************** + * * + * KCPULoad and KNetLoad are copyright (c) 1999-2000, Markus Gustavsson * + * (c) 2002, Ben Burton * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef __SPEEDDIALOG_H +#define __SPEEDDIALOG_H + +#include <kdialogbase.h> + +/** + * A dialog used to select the update speed for a StatPopup. + */ +class SpeedDialog : public KDialogBase { + Q_OBJECT + + + public: + /** + * Constructor. + */ + SpeedDialog(int defaultSpeed, TQWidget* parent); + + /** + * Returns the speed currently selected in the dialog. + * This is valid after the dialog has closed. + */ + int getSpeed() const; + + private slots: + /** + * Updates the speed variable to reflect the latest changes in + * the speed combo box. + */ + virtual void updateSpeed(const TQString&); + + private: + int speed; + /**< The speed currently selected in the speed combo box. */ +}; + +#endif diff --git a/src/statdock.cpp b/src/statdock.cpp new file mode 100644 index 0000000..36d33cc --- /dev/null +++ b/src/statdock.cpp @@ -0,0 +1,270 @@ + +/*************************************************************************** + * * + * KCPULoad and KNetLoad are copyright (c) 1999-2000, Markus Gustavsson * + * (c) 2002, Ben Burton * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "statdock.h" +#include "statpopup.h" +#include <tqpainter.h> + +const int StatDock::fillLines = 0; +const int StatDock::fillBars = 1; +const int StatDock::fillShaded = 2; + +const TQColor StatDock::colorGrid(120, 120, 120); +const TQColor StatDock::colorGridInactive(60, 60, 60); +const TQColor StatDock::colorLabel(255, 255, 255); +const TQColor StatDock::colorLabelInactive(125, 125, 125); +const TQColor StatDock::colorLower(255, 255, 255); +const TQColor StatDock::colorLowerInactive(125, 125, 125); +const TQColor StatDock::colorBlack(0, 0, 0); + +//#define DOCK_SIZE 24 +#define DOCK_SIZE width() +#define DOCK_SCALE (((float) 105)/((float) (DOCK_SIZE-1))) +#define SOFT_STEP 3 + +StatDock::StatDock(int whichDock, const TQString& useLabel, + StatPopup *parent, const char *name) : + KSystemTray(parent,name), + label(useLabel), + bufUpper(0), + bufLower(0), + pos(0) { + + bufUpper = new int[DOCK_SIZE]; + bufLower = new int[DOCK_SIZE]; + + // Initialise the stored readings. + for (i = 0; i < DOCK_SIZE; i++) + bufUpper[i] = bufLower[i] = 0; + + // Initialise the display. + parent->initDock(this, contextMenu(), whichDock); + setBackgroundColor(colorBlack); + resize(DOCK_SIZE, DOCK_SIZE); + show(); +} + +StatDock::~StatDock() { + delete[] bufUpper; + delete[] bufLower; +} + +void StatDock::resizeEvent ( TQResizeEvent * ) +{ + // Honor Free Desktop specifications that allow for arbitrary system tray icon sizes + int* bufUpperOld; + int* bufLowerOld; + + bufUpperOld = bufUpper; + bufLowerOld = bufLower; + + bufUpper = new int[DOCK_SIZE]; + bufLower = new int[DOCK_SIZE]; + + // Re-initialise the stored readings. + for (i = 0; i < DOCK_SIZE; i++) + bufUpper[i] = bufLower[i] = 0; + + delete[] bufUpperOld; + delete[] bufLowerOld; + + repaint(); +} + +void StatDock::setGrid(bool set) { + grid = set; + repaint(); +} + +void StatDock::setActive(bool set) { + active = set; + repaint(); +} + +void StatDock::setSoft(bool set) { + soft = set; + repaint(); +} + +void StatDock::setSplit(bool set) { + split = set; + repaint(); +} + +void StatDock::setLabelled(bool set) { + labelled = set; + repaint(); +} + +void StatDock::setLabel(const TQString& set) { + label = set; + repaint(); +} + +void StatDock::setFill(int set) { + fill = set; + repaint(); +} + +void StatDock::setColor(const TQColor& set) { + colorUpper = set; + colorUpperInactive = colorUpper.dark(); + repaint(); +} + +void StatDock::clearHistory(void) { + for (i = 0; i < DOCK_SIZE; i++) + bufUpper[i] = bufLower[i] = 0; + repaint(); +} + +void StatDock::addPercentReading(int upper, int lower) { + // Rescale the readings to a measure in pixels. + upper = (int) (((float) upper) / DOCK_SCALE); + lower = (split ? (int) (((float) lower) / DOCK_SCALE) : 0); + + if (soft) { + // Do a bit of juggling to obtain a soft reading. + oldUpper = bufUpper[pos]; + oldLower = bufLower[pos]; + if(++pos >= DOCK_SIZE) + pos = 0; + + // Modify the upper reading. + if (upper > oldUpper + SOFT_STEP) + upper = oldUpper + SOFT_STEP; + else if (upper < oldUpper - SOFT_STEP) + upper = oldUpper - SOFT_STEP; + bufUpper[pos] = upper; + + // Modify the lower reading. + if (split) { + if (lower > oldLower + SOFT_STEP) + lower = oldLower + SOFT_STEP; + else if (lower < oldLower - SOFT_STEP) + lower = oldLower - SOFT_STEP; + } + bufLower[pos] = lower; + } else { + // Just a straight update. + if(++pos >= DOCK_SIZE) + pos = 0; + bufUpper[pos] = upper; + bufLower[pos] = lower; + } + + // Refresh the diagram. + repaint(); +} + +void StatDock::paintEvent(TQPaintEvent*) { + TQPainter p(this); + + // Start by drawing the grid. + if(grid) { + p.setPen((active) ? colorGrid : colorGridInactive); + for(i = (((DOCK_SIZE+1)/5)-1); i < (DOCK_SIZE-1); i=i+((DOCK_SIZE+1)/5)) { + p.drawLine(0, i, (DOCK_SIZE-1), i); + } + } + + if(fill == fillShaded) { + // Shaded + for(i = 0; i < DOCK_SIZE; i++) { + tmpPos = (pos + i + 1) % DOCK_SIZE; + for(j = 0; j <= bufUpper[tmpPos]; j++) { + if (bufUpper[tmpPos] == 0 || j == 0) + p.setPen(colorBlack); + else if (active) + p.setPen(colorUpper.dark((100 * bufUpper[tmpPos]) / j)); + else + p.setPen(colorUpper.dark((200 * bufUpper[tmpPos]) / j)); + + if(split) + p.drawPoint(i, DOCK_SIZE - 1 - j - bufLower[tmpPos]); + else + p.drawPoint(i, DOCK_SIZE - j); + } + + if(split) { + for(j = 0; j <= bufLower[tmpPos]; j++) { + if (bufLower[tmpPos] == 0 || j == 0) + p.setPen(colorBlack); + else if (active) + p.setPen(colorLower.dark((100 * bufLower[tmpPos]) / j)); + else + p.setPen(colorLower.dark((200 * bufLower[tmpPos]) / j)); + + p.drawPoint(i, (DOCK_SIZE-1) - j); + } + } + } + } else if (fill == fillBars) { + // Bars + if(split) { + // Draw the upper bars, then the lower to save on pen + // adjustments. + p.setPen(active ? colorUpper : colorUpperInactive); + for(i = 0; i < DOCK_SIZE; i++) { + tmpPos = (pos + i + 1) % DOCK_SIZE; + p.drawLine(i, DOCK_SIZE - 1 - bufUpper[tmpPos] - + bufLower[tmpPos], i, DOCK_SIZE - 1 - bufLower[tmpPos]); + } + p.setPen(active ? colorLower : colorLowerInactive); + for(i = 0; i < DOCK_SIZE; i++) { + tmpPos = (pos + i + 1) % DOCK_SIZE; + p.drawLine(i, DOCK_SIZE - 1 - bufLower[tmpPos], + i, DOCK_SIZE - 1); + } + } else { + p.setPen(active ? colorUpper : colorUpperInactive); + for(i = 0; i < DOCK_SIZE; i++) { + tmpPos = (pos + i + 1) % DOCK_SIZE; + p.drawLine(i, DOCK_SIZE - 1 - bufUpper[tmpPos], + i, DOCK_SIZE - 1); + } + } + } else { + // Lines + if(split) { + // Draw the upper line, then the lower to save on pen + // adjustments. + p.setPen(active ? colorUpper : colorUpperInactive); + for(i = 0; i < DOCK_SIZE; i++) { + tmpPos = (pos + i + 1) % DOCK_SIZE; + p.drawPoint(i, DOCK_SIZE - 1 - + bufUpper[tmpPos] - bufLower[tmpPos]); + } + p.setPen(active ? colorLower : colorLowerInactive); + for(i = 0; i < DOCK_SIZE; i++) { + tmpPos = (pos + i + 1) % DOCK_SIZE; + p.drawPoint(i, DOCK_SIZE - 1 - bufLower[tmpPos]); + } + } else { + p.setPen(active ? colorUpper : colorUpperInactive); + for(i = 0; i < DOCK_SIZE; i++) { + tmpPos = (pos + i + 1) % DOCK_SIZE; + p.drawPoint(i, DOCK_SIZE - 1 - bufUpper[tmpPos]); + } + } + } + + // Finally label the diagrams. + if(labelled) { + p.setFont(TQFont( "Helvetica", ((8*DOCK_SIZE)/24) )); + p.setPen((active) ? colorLabel : colorLabelInactive); + p.drawText(rect(), AlignLeft | AlignTop, label); + } +} + +#include "statdock.moc" diff --git a/src/statdock.h b/src/statdock.h new file mode 100644 index 0000000..1fb0552 --- /dev/null +++ b/src/statdock.h @@ -0,0 +1,164 @@ + +/*************************************************************************** + * * + * KCPULoad and KNetLoad are copyright (c) 1999-2000, Markus Gustavsson * + * (c) 2002, Ben Burton * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef __STATDOCK_H +#define __STATDOCK_H + +#include <tqcolor.h> +#include <ksystemtray.h> + +class StatPopup; + +/** + * A system tray window that displays a recent history of readings. + * A single application might have many of these windows. + * + * Two simultaneous sets of readings are supported; these will be + * referred to as upper and lower readings. When diagram splitting is + * switched on, these readings will be displayed together on the diagram + * with the upper readings shown above the lower readings. When diagram + * splitting is switched off, only the upper readings will be displayed. + * + * The parent window of a StatDock must be a StatPopup, which provides + * all of the actions in this window's context menu. + */ +class StatDock : public KSystemTray { + Q_OBJECT + + +public: + /** + * Fill style constants. + */ + static const int fillLines; + static const int fillBars; + static const int fillShaded; + + /** + * Colour constants. + */ + static const TQColor colorGrid; + static const TQColor colorGridInactive; + static const TQColor colorLabel; + static const TQColor colorLabelInactive; + static const TQColor colorLower; + static const TQColor colorLowerInactive; + static const TQColor colorBlack; + +public: + /** + * Constructor and destructor. + * + * Note that the constructor will call parent->initDock(). + * + * Parameter whichDock must be 0 or 1 to specify whether this dock + * will become dock[0] or dock[1] in the given StatPopup parent. + * Parameter useLabel should contain the label that will be drawn on + * the diagram if labelling is enabled. + */ + StatDock(int whichDock, const TQString& useLabel, StatPopup *parent, + const char *name = 0); + ~StatDock(); + + /** + * Setting display options. + */ + void setGrid(bool); + void setActive(bool); + void setSoft(bool); + void setSplit(bool); + void setLabelled(bool); + void setLabel(const TQString&); + void setFill(int); + void setColor(const TQColor&); + +public slots: + /** + * Clear the history of recent readings. + * All readings will be reset to zero and the diagram will be + * updated. + */ + void clearHistory(); + + /** + * Add the given pair of readings as the most recent in our list. + * The diagram will be updated accordingly. + * + * Each argument should be a percentage between 0 and 100. + * The sum of both arguments must not exceed 100. + * + * If diagram splitting is switched off, the given lower reading + * will be ignored completely and 0 will be used instead. + * + * @param upper the upper reading in this pair. + * @param lower the lower reading in this pair. + */ + void addPercentReading(int upper, int lower); + +private: + /** + * Repaint this system tray window with a fresh diagram. + */ + void paintEvent(TQPaintEvent*); + +private: + /** + * Display options. + */ + bool grid; + /**< Should the grid be displayed behind the diagram? */ + bool active; + /**< Is this meter currently active? */ + bool soft; + /**< Are we artificially modifying the readings to produce a + soft curve? */ + bool split; + /**< Are we displaying both upper and lower readings? */ + bool labelled; + /**< Should this diagram be labelled? */ + TQString label; + /**< The specific label to draw on this diagram. */ + int fill; + /**< Specifies which of the predefined fill styles to use. */ + TQColor colorUpper; + /**< Colour for displaying the upper readings. */ + TQColor colorUpperInactive; + /**< Colour for displaying the upper readings whilst the diagram + is inactive. */ + + /** + * Stored readings. + */ + int* bufUpper; + /**< Stores our list of recent upper readings. + This list begins at index (pos + 1) as the earliest reading + and cycles around to index (pos) as the latest reading. */ + int* bufLower; + /**< Stores our list of recent lower readings. + This list begins at index (pos + 1) as the earliest reading + and cycles around to index (pos) as the latest reading. */ + int pos; + /**< The index in our arrays of the most recent reading. */ + + + /** + * Temporaries. + */ + int i, j, tmpPos, oldUpper, oldLower; + /**< Temporary variables used during computations. */ + +protected: + void resizeEvent ( TQResizeEvent * ); +}; + +#endif diff --git a/src/statpopup.cpp b/src/statpopup.cpp new file mode 100644 index 0000000..e8c3c8f --- /dev/null +++ b/src/statpopup.cpp @@ -0,0 +1,485 @@ + +/*************************************************************************** + * * + * KCPULoad and KNetLoad are copyright (c) 1999-2000, Markus Gustavsson * + * (c) 2002, Ben Burton * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "icontoggleaction.h" +#include "speeddialog.h" +#include "statdock.h" +#include "statpopup.h" + +#include <tqpainter.h> +#include <tqtimer.h> +#include <tdeaction.h> +#include <kcolordialog.h> +#include <tdeconfig.h> +#include <kdebug.h> +#include <tdeglobal.h> +#include <khelpmenu.h> +#include <kiconloader.h> +#include <tdelocale.h> +#include <tdepopupmenu.h> +#include <twin.h> +#include <cstdlib> + +#define DEFAULT_SPEED 1000 +#define TEXT_EXPANSION_HORIZONTAL 10 +#define TEXT_EXPANSION_VERTICAL 3 + +const TQColor StatPopup::colorBorder(0, 0, 0); + +StatPopup::Reading::Reading() : + dock(0), + actColor(0) +{ } + +StatPopup::Reading::~Reading() +{ + delete actColor; + delete dock; +} + +void StatPopup::Reading::Init(int which, StatPopup* popup) +{ + char colorid[30]; + sprintf(colorid, "Color%d", which); + + color = popup->defaultDockColor(which); + color = popup->config->readColorEntry(colorid, &color); + actColor = new TDEAction(i18n("Color (%1)...").arg(popup->dockName(which)), + "color", 0, TQT_TQOBJECT(popup), TQT_SLOT(selectColor()), popup->coll, colorid); +} + + +StatPopup::StatPopup(bool useSupportSplit, TQWidget *parent, const char *name) : + TQWidget(parent, name, TQt::WStyle_Customize | TQt::WStyle_NoBorder | + TQt::WStyle_StaysOnTop | TQt::WDestructiveClose | TQt::WType_TopLevel), + supportSplit(useSupportSplit) { + // Window management. + KWin::setState(winId(), NET::SkipTaskbar | NET::SkipPager); + + // TODO: Get all-desktops working, even after a hide/reshow. + //KWin::setOnAllDesktops(winId(), true); + + // Basic variable initialisation. + relX = relY = 0; + isDragged = closing = false; + + // Initialise the text contents of this pop-up. + fullReading = i18n("Inactive."); + resizeToText(); + + // Prepare for actions and the config file, but don't actually add + // any actions or read the configuration. + config = TDEGlobal::config(); + coll = new TDEActionCollection(this); + + // Set up a timer for our periodic updates. + timer = new TQTimer(this); + connect(timer, TQT_SIGNAL(timeout()), TQT_TQOBJECT(this), TQT_SLOT(takeReading())); +} + +StatPopup::~StatPopup() { +} + +void StatPopup::readPopupState() { + config->setGroup("Popup Options"); + + // Read the position. + int useX = config->readNumEntry("PopupX", 0); + int useY = config->readNumEntry("PopupY", 0); + if (useX || useY) + move(useX, useY); + + // Show the pop-up if appropriate. + if (config->readBoolEntry("PopupActive", false)) + show(); + else + hide(); +} + +void StatPopup::savePopupState() { + config->setGroup("Popup Options"); + config->writeEntry("PopupActive", isVisible()); + config->writeEntry("PopupX", x()); + config->writeEntry("PopupY", y()); + config->sync(); +} + +void StatPopup::initDock(StatDock* target, TDEPopupMenu* menu, int whichDock) { + // Initialise the menus. + actActive->plug(menu); + actClearHistory->plug(menu); + menu->insertSeparator(); + actSpeed->plug(menu); + if (supportSplit) + actSplit->plug(menu); + menu->insertSeparator(); + + insertCustomItems(menu); + + TDEPopupMenu* fillMenu = new TDEPopupMenu(menu); + actFillLines->plug(fillMenu); + actFillBars->plug(fillMenu); + actFillShaded->plug(fillMenu); + menu->insertItem(SmallIcon("style"), i18n("St&yle"), fillMenu); + + actSoft->plug(menu); + actLabelled->plug(menu); + actGrid->plug(menu); + r[whichDock].actColor->plug(menu); + menu->insertSeparator(); + menu->insertItem(SmallIcon("help"), i18n("&Help"), + (new KHelpMenu(0, TDEGlobal::instance()->aboutData(), false))->menu()); + + // Set up display properties for the dock. + target->setActive(actActive->isChecked()); + target->setSplit(isSplit()); + target->setFill(fillStyle); + target->setSoft(actSoft->isChecked()); + target->setLabelled(actLabelled->isChecked()); + target->setGrid(actGrid->isChecked()); + target->setColor(r[whichDock].color); + setCustomProperties(target); +} + +bool StatPopup::isActive() const { + return actActive->isChecked(); +} + +bool StatPopup::isSplit() const { + return (supportSplit ? actSplit->isChecked() : false); +} + +void StatPopup::setActive(bool set) { + if (set) + startUpdates(); + else + stopUpdates(); + + for (int i = 0; i < r.size(); i++) { + r[i].dock->setActive(set); + } + + config->setGroup("General Options"); + config->writeEntry("Active", set); + config->sync(); +} + +void StatPopup::clearHistory() { + for (int i = 0; i < r.size(); i++) { + r[i].dock->clearHistory(); + } +} + +void StatPopup::selectSpeed() { + SpeedDialog dlg(speed, firstDock()); + if (dlg.exec()) { + int newSpeed = dlg.getSpeed(); + if (newSpeed > 0) { + speed = newSpeed; + if (timer->isActive()) + timer->changeInterval(speed); + + config->setGroup("General Options"); + config->writeEntry("Speed", speed); + config->sync(); + } + } +} + +void StatPopup::setSplit(bool set) { + if (! supportSplit) + return; + + for (int i = 0; i < r.size(); i++) { + r[i].dock->setSplit(set); + } + + requestResize(); + + config->setGroup("General Options"); + config->writeEntry("Split", set); + config->sync(); +} + +void StatPopup::setFillLines() { + fillStyle = StatDock::fillLines; + + actFillLines->setChecked(true); + actFillBars->setChecked(false); + actFillShaded->setChecked(false); + + for (int i = 0; i < r.size(); i++) { + r[i].dock->setFill(StatDock::fillLines); + } + + config->setGroup("General Options"); + config->writeEntry("StyleID", StatDock::fillLines); + config->sync(); +} + +void StatPopup::setFillBars() { + fillStyle = StatDock::fillBars; + + actFillLines->setChecked(false); + actFillBars->setChecked(true); + actFillShaded->setChecked(false); + + for (int i = 0; i < r.size(); i++) { + r[i].dock->setFill(StatDock::fillBars); + } + + config->setGroup("General Options"); + config->writeEntry("StyleID", StatDock::fillBars); + config->sync(); +} + +void StatPopup::setFillShaded() { + fillStyle = StatDock::fillShaded; + + actFillLines->setChecked(false); + actFillBars->setChecked(false); + actFillShaded->setChecked(true); + + for (int i = 0; i < r.size(); i++) { + r[i].dock->setFill(StatDock::fillShaded); + } + + config->setGroup("General Options"); + config->writeEntry("StyleID", StatDock::fillShaded); + config->sync(); +} + +void StatPopup::setSoft(bool set) { + for (int i = 0; i < r.size(); i++) { + r[i].dock->setSoft(set); + } + + config->setGroup("General Options"); + config->writeEntry("Soft", set); + config->sync(); +} + +void StatPopup::setLabelled(bool set) { + for (int i = 0; i < r.size(); i++) { + r[i].dock->setLabelled(set); + } + + config->setGroup("General Options"); + config->writeEntry("Labelled", set); + config->sync(); +} + +void StatPopup::setGrid(bool set) { + for (int i = 0; i < r.size(); i++) { + r[i].dock->setGrid(set); + } + + config->setGroup("General Options"); + config->writeEntry("Grid", set); + config->sync(); +} + +void StatPopup::selectColor() { + // which color? + int whichDock; + if (sscanf(TQT_TQOBJECT(const_cast<TQT_BASE_OBJECT_NAME*>(sender()))->name(), "Color%d", &whichDock) != 1) + return; + if (whichDock < 0 || whichDock >= r.size()) + return; + + if (r[whichDock].dock) { + TQColor ans; + if (KColorDialog::getColor(ans, r[whichDock].color, firstDock()) == + TQDialog::Accepted) { + r[whichDock].color = ans; + r[whichDock].dock->setColor(ans); + + config->setGroup("General Options"); + TQString n; + n.sprintf("Color%d", whichDock); + config->writeEntry(n, ans); + config->sync(); + } + } +} + +StatDock* StatPopup::firstDock() { + return r.size() > 0 ? r[0].dock : 0; +} + +void StatPopup::startUpdates() { + takeReading(); + timer->start(speed); +} + +void StatPopup::stopUpdates() { + timer->stop(); + fullReading = i18n("Inactive."); +} + +void StatPopup::setupActions() { + config->setGroup("General Options"); + bool bVal; + + bVal = config->readBoolEntry("Active", true); + actActive = new TDEToggleAction(i18n("&Active"), 0, coll, "active"); + actActive->setChecked(bVal); + connect(actActive, TQT_SIGNAL(toggled(bool)), TQT_TQOBJECT(this), TQT_SLOT(setActive(bool))); + + actClearHistory = new TDEAction(i18n("&Clear"), "edit-delete", 0, + TQT_TQOBJECT(this), TQT_SLOT(clearHistory()), coll, "clear"); + + speed = config->readNumEntry("Speed", DEFAULT_SPEED); + actSpeed = new TDEAction(i18n("&Speed..."), "speedarrow", 0, + TQT_TQOBJECT(this), TQT_SLOT(selectSpeed()), coll, "speed"); + + if (supportSplit) { + bVal = config->readBoolEntry("Split", true); + actSplit = new IconToggleAction(i18n("Sp&lit Graph"), "split", + i18n("Graph Sp&litting Enabled"), "spliton", 0, coll, "split"); + actSplit->setChecked(bVal); + connect(actSplit, TQT_SIGNAL(toggled(bool)), TQT_TQOBJECT(this), TQT_SLOT(setSplit(bool))); + } + + fillStyle = config->readNumEntry("StyleID", StatDock::fillShaded); + actFillLines = new IconToggleAction(i18n("&Lines"), "lines", "lineson", 0, + TQT_TQOBJECT(this), TQT_SLOT(setFillLines()), coll, "filllines"); + actFillLines->setChecked(fillStyle == StatDock::fillLines); + actFillBars = new IconToggleAction(i18n("&Bars"), "bars", "barson", 0, + TQT_TQOBJECT(this), TQT_SLOT(setFillBars()), coll, "fillbars"); + actFillBars->setChecked(fillStyle == StatDock::fillBars); + actFillShaded = new IconToggleAction(i18n("&Shaded"), "shaded", "shadedon", + 0, TQT_TQOBJECT(this), TQT_SLOT(setFillShaded()), coll, "fillshaded"); + actFillShaded->setChecked(fillStyle == StatDock::fillShaded); + + bVal = config->readBoolEntry("Soft", false); + actSoft = new IconToggleAction(i18n("So&ft Curves"), "soft", + i18n("So&ft Curves Enabled"), "softon", 0, coll, "soft"); + actSoft->setChecked(bVal); + connect(actSoft, TQT_SIGNAL(toggled(bool)), TQT_TQOBJECT(this), TQT_SLOT(setSoft(bool))); + + bVal = config->readBoolEntry("Labelled", true); + actLabelled= new IconToggleAction(i18n("Show &Labels"), "labels", + i18n("&Labels Enabled"), "labelson", 0, coll, "labelled"); + actLabelled->setChecked(bVal); + connect(actLabelled, TQT_SIGNAL(toggled(bool)), TQT_TQOBJECT(this), TQT_SLOT(setLabelled(bool))); + + bVal = config->readBoolEntry("Grid", true); + actGrid = new IconToggleAction(i18n("Show &Grid"), "grid", + i18n("&Grid Enabled"), "gridon", 0, coll, "grid"); + actGrid->setChecked(bVal); + connect(actGrid, TQT_SIGNAL(toggled(bool)), TQT_TQOBJECT(this), TQT_SLOT(setGrid(bool))); + + setupCustomActions(); +} + +void StatPopup::paintEvent(TQPaintEvent*) { + TQPainter p(this); + + // Draw the border. + p.setPen(colorBorder); + p.drawLine(0, 0, width(), 0); + p.drawLine(0, 1, width(), 1); + p.drawLine(0, 2, 0, height()); + p.drawLine(1, 2, 1, height()); + p.drawLine(width() - 2, 2, width() - 2, height()); + p.drawLine(width() - 1, 2, width() - 1, height()); + p.drawLine(2, height() - 2, width() - 2, height() - 2); + p.drawLine(2, height() - 1, width() - 2, height() - 1); + + // Draw the text. + p.setFont(font()); + p.setPen(colorGroup().foreground()); + p.drawText(rect(), AlignHCenter | AlignVCenter, fullReading); +} + +void StatPopup::mousePressEvent(TQMouseEvent* e) { + if(e->button() == Qt::RightButton) { + // Hide the pop-up. + hide(); + } else { + // Begin a drag operation. + isDragged = true; + relX = e->x(); + relY = e->y(); + repaint(); + } +} + +void StatPopup::mouseMoveEvent(TQMouseEvent* e) { + // In the middle of a drag operation. + move(e->globalX() - relX, e->globalY() - relY); +} + +void StatPopup::mouseReleaseEvent(TQMouseEvent* e) { + // The end of a drag operation. + move(e->globalX() - relX, e->globalY() - relY); + isDragged = false; + repaint(); +} + +void StatPopup::closeEvent(TQCloseEvent* e) { + // We're about to close. Save the current state for the last time. + savePopupState(); + closing = true; + TQWidget::closeEvent(e); +} + +void StatPopup::hideEvent(TQHideEvent* e) { + // We're about to hide. Save the current state if we're not + // closing altogether. + if (! closing) + savePopupState(); + TQWidget::hideEvent(e); +} + +void StatPopup::showEvent(TQShowEvent* e) { + // Make sure we're up-to-date and properly resized. + if (isActive()) + takeReading(); + else + resizeToText(); + + // Window management - fix so a taskbar button doesn't appear + KWin::setState(winId(), NET::SkipTaskbar | NET::SkipPager); + + TQWidget::showEvent(e); +} + +void StatPopup::takeReading() { + takeReadingInternal(); + + for (int i = 0; i < r.size(); i++) { + r[i].dock->addPercentReading(r[i].upper, r[i].lower); + } + + if (isVisible()) { + // Only resize if the pop-up is visible; otherwise fullReading + // might be stale anyway so we'll do it when we show the pop-up. + if (resizeRequested) + resizeToText(); + + repaint(); + } +} + +void StatPopup::resizeToText() { + resizeRequested = false; + + TQSize size = fontMetrics().size(0, fullReading); + resize(size.width() + 2 * TEXT_EXPANSION_HORIZONTAL, + size.height() + 2 * TEXT_EXPANSION_VERTICAL); + repaint(); +} + +#include "statpopup.moc" diff --git a/src/statpopup.h b/src/statpopup.h new file mode 100644 index 0000000..1b158a6 --- /dev/null +++ b/src/statpopup.h @@ -0,0 +1,320 @@ + +/*************************************************************************** + * * + * KCPULoad and KNetLoad are copyright (c) 1999-2000, Markus Gustavsson * + * (c) 2002, Ben Burton * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef __STATPOPUP_H +#define __STATPOPUP_H + +#include <tqwidget.h> +#include <vector> // sorry, TQValueVector::erase() does not call destructors + +class TDEAction; +class TDEActionCollection; +class TDEConfig; +class TDEPopupMenu; +class TDERadioAction; +class TDESelectAction; +class TDEToggleAction; +class TQTimer; +class StatDock; + +/** + * A small pop-up window that contains a continually updating display of + * statistics. + * + * This pop-up will be sticky and stay-on-top by default. + * + * Up to two windows docked in the system tray (of class StatDock) can + * be maintained by this pop-up. There should only be one StatPopup + * per application. + * + * Note that initDock() \e must be called when a system tray window is + * created, though it is generally called automatically from the StatDock + * constructor. + * + * Note also that the constructor for this class does \e not call + * setupActions(), readPopupState() or startUpdates(); these must all be + * called by other routines (such as subclass constructors), since they + * require either subclass initialisation or an existing system tray + * window. + */ +class StatPopup : public TQWidget { + Q_OBJECT + + +public: + /** + * Colour constants. + */ + static const TQColor colorBorder; + +public: + /** + * Constructors and destructors. + * + * This constructor will set the config variable but will not read + * any configuration information. See the general class notes also + * for a list of other routines this constructor will not call. + */ + StatPopup(bool useSupportSplit, TQWidget *parent = 0, const char *name = 0); + ~StatPopup(); + + /** + * Geometric pop-up state management. + */ + void readPopupState(); + void savePopupState(); + + /** + * Initialises the given system tray window and its context menu. + * + * All global application properties (i.e., properties held by this + * pop-up) will be propagated to the system tray window, and all + * global application actions will be added to the given menu. + * + * Parameter whichDock must be either 0 or 1 to specify whether the + * given system tray window will become window dock[0] or dock[1]. + * + * This routine \e must be called when a system tray window is first + * created, though in general this will be done automatically by the + * StatDock constructor. + */ + virtual void initDock(StatDock* target, TDEPopupMenu* menu, int whichDock); + + /** + * Is this application currently active (i.e., taking periodic + * readings and displaying them)? + */ + bool isActive() const; + + /** + * Are split diagrams currently enabled? + */ + bool isSplit() const; + + /** + * Returns the frequency of updates in milliseconds. + */ + int getSpeed() const; + +public slots: + /** + * Slots for menu items. + */ + void setActive(bool); + void clearHistory(); + void selectSpeed(); + void setSplit(bool); + void setFillLines(); + void setFillBars(); + void setFillShaded(); + void setSoft(bool); + void setLabelled(bool); + void setGrid(bool); + void selectColor(); + +protected: + /** + * Return a human-readable name and default diagram colour for each + * system tray window. + * The argument given will be either 0 or 1, referring to window + * dock[0] or dock[1] respectively. + */ + virtual TQString dockName(int which) const = 0; + virtual TQColor defaultDockColor(int which) const = 0; + + /** + * Take a fresh reading. Subclasses must override this routine. + * + * This routine must update the array upper. + * If split readings are enabled, it must also update the array lower. + * If this pop-up is visible, it must also update the string fullReading. + */ + virtual void takeReadingInternal() = 0; + + /** + * Sets up any actions specific to subclasses of StatPopup. + * The global configuration should be read at this point to set the + * initial states of these actions. + * + * This routine will be called during setupActions(). + */ + virtual void setupCustomActions() {} + + /** + * Inserts any menu items specific to subclasses of StatPopup into + * the given menu. If any items are inserted, a separator should + * be inserted after them. + * + * This routine will be called during initDock(). + */ + virtual void insertCustomItems(TDEPopupMenu*) {} + + /** + * Propagates any properties specific to subclasses of StatPopup to + * the given system tray window during its initialisation. + * + * This routine will be called during initDock(). + */ + virtual void setCustomProperties(StatDock*) {} + + /** + * Returns the first non-null pointer out of dock[0] and dock[1], or + * returns null if both these pointers are null. + */ + StatDock* firstDock(); + + /** + * Start and stop the periodic taking of readings. + */ + void startUpdates(); + void stopUpdates(); + + /** + * Set up the collection of appliation-wide actions. + * The global configuration will be read at this point to set the + * initial states of these actions. + */ + virtual void setupActions(); + + /** + * Request that this pop-up be resized at the next reading according + * to its text contents. The pop-up will be resized \e after the + * reading is taken. + */ + void requestResize(); + + /** + * Custom painting routine. + */ + void paintEvent(TQPaintEvent *); + + /** + * Overrides for dragging support. + */ + void mousePressEvent(TQMouseEvent *); + void mouseReleaseEvent(TQMouseEvent *); + void mouseMoveEvent(TQMouseEvent *); + + /** + * Overrides for saving the popup state. + */ + void closeEvent(TQCloseEvent *); + void hideEvent(TQHideEvent *); + void showEvent(TQShowEvent *); + +protected slots: + /** + * Take a fresh reading and update all visual elements accordingly. + */ + void takeReading(); + +protected: + /** + * Configuration and GUI elements. + */ + TDEConfig* config; + /**< The configuration for the underlying application. */ + + /** + * Contains the readings per CPU. + */ + struct Reading { + StatDock* dock; + /**< The system tray window maintained by this pop-up. + May be null. */ + int upper; + /**< The upper reading taken during the last reading. */ + int lower; + /**< The lower reading taken during the last reading. */ + TQColor color; + /**< The colour used in the system tray diagram. */ + TDEAction* actColor; + /**< The menu item to change the colour of this dock. */ + Reading(); + ~Reading(); + void Init(int which, StatPopup* popup); + }; + std::vector<Reading> r; + /**< The readings maintained by this pop-up. */ + TDEActionCollection* coll; + /**< The collection of all application-level actions. */ + + TQString fullReading; + /**< A full string describing the last reading taken, + to be displayed in this pop-up. */ + +private: + /** + * Resize this pop-up according to its text contents (i.e., the + * variable fullReading). A little extra room will be added to + * accomodate potential minor variations in the text. + */ + void resizeToText(); + +private: + /** + * Update support. + */ + TQTimer* timer; + /**< The timer handling periodic updates. */ + int speed; + /**< The frequency of updates in milliseconds. */ + + /* + * Diagram support. + */ + int fillStyle; + /**< The fill style used in the system tray diagrams. */ + bool supportSplit; + /**< Does this application support split diagrams? */ + + /** + * Pop-up support. + */ + int relX; + /**< The X coordinate of this pop-up at the beginning of a drag + operation. */ + int relY; + /**< The Y coordinate of this pop-up at the beginning of a drag + operation. */ + bool isDragged; + /**< Are we in the middle of a drag operation? */ + bool closing; + /**< Have we received a close event? */ + bool resizeRequested; + /**< Has a pop-up resize been requested? */ + + /** + * Actions + */ + TDEToggleAction* actActive; + TDEAction* actClearHistory; + TDEAction* actSpeed; + TDEToggleAction* actSplit; + TDEToggleAction* actFillLines; + TDEToggleAction* actFillBars; + TDEToggleAction* actFillShaded; + TDEToggleAction* actSoft; + TDEToggleAction* actLabelled; + TDEToggleAction* actGrid; +}; + +inline int StatPopup::getSpeed() const { + return speed; +} + +inline void StatPopup::requestResize() { + resizeRequested = true; +} + +#endif |